1.HTTP協議|web框架

一、web應用 

  Web應用程序是一種能夠經過Web訪問的應用程序,程序的最大好處是用戶很容易訪問應用程序,用戶只須要有瀏覽器便可,不須要再安裝其餘軟件。應用程序有兩種模式C/S、B/S。C/S是客戶端/服務器端程序,也就是說這類程序通常獨立運行。而B/S就是瀏覽器端/服務器端應用程序,這類應用程序通常藉助谷歌,火狐等瀏覽器來運行。WEB應用程序通常是B/S模式。Web應用程序首先是「應用程序」,和用標準的程序語言,如java,python等編寫出來的程序沒有什麼本質上的不一樣。在網絡編程的意義下,瀏覽器是一個socket客戶端,服務器是一個socket服務端。html

web框架

  Web框架(Web framework)是一種開發框架,用來支持動態網站、網絡應用和網絡服務的開發。這大多數的web框架提供了一套開發和部署網站的方式,也爲web行爲提供了一套通用的方法。web框架已經實現了不少功能,開發人員使用框架提供的方法而且完成本身的業務邏輯,就能快速開發web應用了。瀏覽器和服務器的是基於HTTP協議進行通訊的。也能夠說web框架就是在以上十幾行代碼基礎上擴展出來的,有不少簡單方便使用的方法,大大提升了開發的效率。java

wsgiref模塊

  最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。python

若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。mysql

正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口協議來實現這樣的服務器軟件,讓咱們專心用Python編寫Web業務。這個接口就是WSGI :Web Server Gateway Interface。而wsgiref 模塊就是python基於wsgi協議開發的服務模塊。web

from wsgiref.simple_server import make_ser

遵循http協議,字符串必須按照某種格式發給瀏覽器。sql

最簡單的web請求過程: 數據庫

服務端server編程

import socket
sock = socket.socket()
sock.bind(('127.0.0.1',8800))
sock.listen(5)

while 1:
    print('server waiting')
    conn,addr = sock.accept() #請求
    data = conn.recv(1024) #拿到請求信息
    print("data",data)                <h1> Hello luffycity </h1>
    conn.send(b"HTTP/1.1 200 OK\r\n\r\nHello luffycity!")  #與瀏覽器的通信,要遵循HTTP協議去發送請求數據,瀏覽器也會按這種協議進行解析;200是顯示狀態碼,
    conn.close()  #前面爲響應首行,後邊是響應體,以\r\n兩個空格隔開。

打印:
server waiting
data b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nUpgrade-Insecure-Requests: 1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n'
server waiting
data b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n'
server waiting

 

import socket
sock = socket.socket()
sock.bind(('127.0.0.1',8800))
sock.listen(5)

while 1:
    print('server waiting')
    conn,addr = sock.accept()
    data = conn.recv(1024)
    print("data",data)

    #################讀取html文件;直接返回一個html頁面##################
    with open('index.html','rb')as f:
        data = f.read()
    conn.send((b"HTTP/1.1 200 OK\r\n\r\n%s"%data))
    conn.close()

打印:(get請求)
server waiting  #第一個/ 爲路徑部分; GET / HTTP/1.1 爲請求體;以換行符\r\n把他們隔開,都是一個個頭-請求頭;兩個\r\n\r\n後邊就是請求體
data b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n'
server waiting
data b'GET /kris?name=kris&age=22 HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nUpgrade-Insecure-Requests: 1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: sessionid=4sr81dc29tzw0gb1h2zxoqvumbbe6u1z; csrftoken=i1XjCb7mAKefMkNzUUqIvjHpL598C6IC8V0u0AKkPdh03eL7NzPvExLSBE1eLxOA\r\n\r\n' data b
'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n' server waiting
####################Html文件代碼################
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Hello Luffycity!</h1> <img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=16535fed6163f6241c5d3e05bf7f8cc5/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg"> <a href="http://www.luffycity.com">路飛學城</a> </body> </html>

post請求瀏覽器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="http://127.0.0.1:8800/" method="post">
        用戶名<input type="text" name="user">
        密碼<input type="password" name="pwd">
        <input type="submit">
    </form>
</body>
</html>
import socket
sock = socket.socket()
sock.bind(('127.0.0.1',8800))
sock.listen(5)

while 1:
    print('server waiting')
    conn,addr = sock.accept()
    data = conn.recv(1024) #
    print("data",data)

    #讀取html文件
    with open('login.html','rb')as f:
        data = f.read()
    conn.send((b"HTTP/1.1 200 OK\r\n\r\n%s"%data))
    conn.close()

打印:(post請求)
server waiting     請求首行,請求頭、請求頭、......,請求數據
data b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nUpgrade-Insecure-Requests: 1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n'
server waiting
data b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n'
server waiting
data b''
server waiting
data b''
server waiting
data b''
server waiting
data b''
server waiting    
data b'POST / HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nContent-Length: 20\r\nCache-Control: max-age=0\r\nOrigin: http://127.0.0.1:8800\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\nuser=egon&pwd=abc123'
server waiting
data b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8800\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8800/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=Mrqe5gm2pfaQy6LqXAJDqcWWU3BfTFrB0LMMhAEv2Pi0STKVn95bR6ODrDPZn34j\r\n\r\n'
server waiting


請求首行
請求頭 請求頭 請求頭 .... 請求體(a
=1&b=2) # 注意:只有POST請求才會有請求體 b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8880\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: csrftoken=IU9cIEWdRzTx7gm6JIjASm9TZJSve8jUGcfXPbgTXpSW0iHot1NOxpjdroESRB4f\r\n\r\n' b'GET /yuan?name=yuan&age=22 HTTP/1.1\r\nHost: 127.0.0.1:8880\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: csrftoken=IU9cIEWdRzTx7gm6JIjASm9TZJSve8jUGcfXPbgTXpSW0iHot1NOxpjdroESRB4f\r\n\r\n' b'POST / HTTP/1.1\r\nHost: 127.0.0.1:8880\r\nConnection: keep-alive\r\nContent-Length: 20\r\nPragma: no-cache\r\nCache-Control: no-cache\r\nOrigin: http://127.0.0.1:8880\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8880/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\nCookie: csrftoken=IU9cIEWdRzTx7gm6JIjASm9TZJSve8jUGcfXPbgTXpSW0iHot1NOxpjdroESRB4f\r\n\r\nuser=bisheng&pwd=456' URL: 協議://IP:端口(80)/路徑?a=1&b=2
?以前的都是路徑,?以後的爲請求數據

 

二、http協議簡介 

特性:服務器

  http協議是基於TCP/IP協議之上的應用層協議

基於請求響應模式:先從客戶端開始創建通訊的,服務器端在沒有 接收到請求以前不會發送響應;

無狀態保持:HTTP是一種不保存狀態,即無狀態(stateless)協議,HTTP協議 自身不對請求和響應之間的通訊狀態進行保存,也就是說在HTTP這個級別,協議對於發送過的請求或響應都不作持久化處理。

使用HTTP協議,每當有新的請求發送時,就會有對應的新響應產 生。協議自己並不保留以前一切的請求或響應報文的信息。這是爲了更快地處理大量事務,確保協議的可伸縮性,而特地把HTTP協議設計成 如此簡單的。但是,隨着Web的不斷髮展,因無狀態而致使業務處理變得棘手 的狀況增多了。好比,用戶登陸到一家購物網站,即便他跳轉到該站的 其餘頁面後,也須要能繼續保持登陸狀態。針對這個實例,網站爲了能 夠掌握是誰送出的請求,須要保存用戶的狀態。HTTP/1.1雖然是無狀態協議,但爲了實現指望的保持狀態功能, 因而引入了Cookie技術。有了Cookie再用HTTP協議通訊,就能夠管 理狀態了。

無鏈接的含義是限制每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接。採用這種方式能夠節省傳輸時間。

 

請求協議與響應協議

  http協議包含由瀏覽器發送數據到服務器須要遵循的請求協議與服務器發送數據到瀏覽器須要遵循的請求協議。用於HTTP協議交互的信被爲HTTP報文。請求端(客戶端)的HTTP報文 作請求報文,響應端(服務器端)的 作響應報文。HTTP報文自己是由多行數據構成的字 文本。 

請求協議:請求報文的構成見下

get請求沒有請求體,會放在url後面;只有post請求才有請求體;

請求方式: get與post請求

  • GET提交的數據會放在URL以後,以?分割URL和傳輸數據,參數之間以&相連,如EditBook?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的請求體中.
  • GET提交的數據大小有限制(由於瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.
    GET與POST請求在服務端獲取請求數據方式不一樣。
get(查數據庫的某些資源);
post添加刪除修改,作數據庫更新操做。

響應協議

 響應格式:

響應狀態碼

重定向(地址搬家了,換成另一個域名了。)

3.web框架

wsgi接口協議,基於接口實現的wsgiref

.ico是瀏覽器發的一個圖標請求;

圖標請求

 wsgiref到底爲咱們作了什麼事情?(解析數據和封裝數據)

.拿到的那個字符串data就是根據Http協議封裝好的,怎麼解析它,拿到路徑和數據信息呢??
按照http協議解包, dict/obj d={"path":"/login"} #d.get("path") # 按着http請求協議解析數據 # 專一與web業務開發 # path=d.get("path") 取到當前請求的路徑, # # if path=="/login": # return login.html # 按着http響應協議封裝數據 (組裝Http響應格式,才能返回數據)

 

wsgiref模塊

最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。

若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。

正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口協議來實現這樣的服務器軟件,讓咱們專心用Python編寫Web業務。這個接口就是WSGI:Web Server Gateway Interface。而wsgiref模塊就是python基於wsgi協議開發的服務模塊。

把data數據解析成environ字典;start_response和return共同組成一個相應體。

from wsgiref.simple_server import make_server

def application(environ, start_response): #請求來了就用application來處理,回調函數;按着http協議解析數據全部的數據:把data數據解析成了environ這個字典;按這http協議進行組裝數據,格式就是按照這種start_response來給咱們處理格式
    #按着http協議解析數據:environ;按着http協議組裝數據:start_response
  start_response(
'200 OK', [('Content-Type','text/html')]) #這裏邊放一個字符串(響應首行,'200 OK'),一個列表(響應頭,能夠爲空;狀態碼、響應頭 print("PATH", environ.get("PATH_INFO")) path = environ.get("PATH_INFO") #得到當前請求路徑 if path == "/favicon.ico": '''return [b"hello favicon.ico"] #瀏覽器想獲得一個圖片你卻給了它個字符串''' with open("favicon.ico",'rb') as f: data = f.read() return [data] return [b'<h1>Hello,web!</h1>'] #響應數據;響應首行、響應頭、響應數據這3個(start_response和return)共同組成一個響應體; httpd = make_server('', 8080, application) #封裝的socket;make_server要實例化下,傳參實例化一個類對象; id地址、端口,調用application回調函數 print('Serving HTTP on port 8000.。') #開始監聽HTTP請求: httpd.serve_forever() #等待用戶連接:conn,addr=sock.accept();一旦請求進來它就回去調用application(environ,start_response)函數 打印: Serving HTTP on port 8000.。 PATH /kris 127.0.0.1 - - [24/May/2018 17:48:56] "GET /kris HTTP/1.1" 200 19 127.0.0.1 - - [24/May/2018 17:48:56] "GET /favicon.ico HTTP/1.1" 200 25214 PATH /favicon.ico

方案一:

from wsgiref.simple_server import make_server

def application(environ, start_response): #請求來了就用application來處理;全部的數據都在environ這個字典裏,start_response來給咱們處理格式
    start_response('200 OK', [('Content-Type','text/html')]) #狀態碼、響應頭
    print("PATH", environ.get("PATH_INFO"))
    path = environ.get("PATH_INFO")
    if path == "/favicon.ico":           #瀏覽器發的圖標請求;
        '''return [b"hello favicon.ico"] #瀏覽器想獲得一個圖片你卻給了它個字符串''' hello favicon.ico,不該該返回一個字符串
        with open("favicon.ico",'rb') as f:  #把圖標文件打開。
            data = f.read()
        return [data]
    elif path == "/login":
        with open("login.html","rb")as f:
            data = f.read()
        return [data] #wsgiref規定的返回的必須是字節數據;
    elif path == "/index":
        with open("index.html","rb")as f:
            data = f.read()
        return [data]
    return [b'<h1>Hello,web!</h1>']
httpd = make_server('', 8080, application) #封裝的socket
print('Serving HTTP on port 8000.。')
#開始監聽HTTP請求:
httpd.serve_forever()
#打印:
Serving HTTP on port 8000.。
PATH /index 127.0.0.1 - - [24/May/2018 18:00:55] "GET /index HTTP/1.1" 200 394
127.0.0.1 - - [24/May/2018 18:07:08] "GET /index/login HTTP/1.1" 200 19
PATH /index/login
PATH /login
127.0.0.1 - - [24/May/2018 18:07:21] "GET /login HTTP/1.1" 200 363

方案2 改善

from wsgiref.simple_server import make_server

def login(): #給它加個參數environ,下面傳了你就要接收這個參數。給它傳請求接收信息,它用不用的到再說;如想獲取當前請求方式,請求數據都在environ這個字典裏邊。
    with open("login.html","rb")as f:
        data = f.read()
    return data
def index(): #environ
    with open("index.html","rb")as f:
        data = f.read()
    return data
def favi(): #environ
    with open("favicon.ico", "rb")as f:
        data = f.read()
    return data #大家返回數據data,我把數據data返回到列表裏即[func()]

def reg(): #environ
    with open("regs.html", "rb")as f:
        data = f.read()
    return data

def application(environ, start_response): #請求來了就用application來處理;全部的數據都在environ這個字典裏,start_response來給咱們處理格式
    start_response('200 OK', [('Content-Type','text/html')]) #狀態碼、響應頭
    print("PATH", environ.get("PATH_INFO"))
    #當前請求路徑
    path = environ.get("PATH_INFO")
  #解耦 #再多加個路徑,給它加個元組就能夠了。
    url_patterns = [
        ("/login", login),
        ("/regs", reg),
        ("/index", index),
        ("/favicon.ico",favi)
    ]

    func = None 
    for item in url_patterns:
        if path == item[0]:  #item[0] ---->> /login /regs /index /favicon.ico
            func = item[1]  #跟上邊的匹配成功了,執行這個函數就能夠了。
            break
    if func: #func默認爲None,都匹配不成功仍是爲None;func一旦有值,說明某次匹配成功了
        return [func()]  #返回個列表;函數執行了都有返回值,把函數的返回值data數據加到列表裏邊去; 給它加個參數environ即請求信息,必須給你傳上,你函數用到就拿
    else:
        return [b'404!']

httpd = make_server('', 8080, application) #封裝的socket
print('Serving HTTP on port 8000.。')
#開始監聽HTTP請求:
httpd.serve_forever()

打印:(與瀏覽器的交互)
Serving HTTP on port 8000.。
PATH /
127.0.0.1 - - [24/May/2018 18:31:58] "GET / HTTP/1.1" 200 4
127.0.0.1 - - [24/May/2018 18:32:08] "GET /login HTTP/1.1" 200 363
PATH /login
PATH /reg
127.0.0.1 - - [24/May/2018 18:32:17] "GET /reg HTTP/1.1" 200 4
127.0.0.1 - - [24/May/2018 18:32:22] "GET /regs HTTP/1.1" 200 157
PATH /regs

繼續優化(web框架的使用,若要加一個時間的功能函數,只須要加在url和視圖函數裏邊添加就能夠了)

把html和圖標放在templates裏邊

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Hello Luffycity!</h1>
    <img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=16535fed6163f6241c5d3e05bf7f8cc5/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg">
    <a href="http://www.luffycity.com">路飛學城</a>
</body>
</html>

 

views.py(保存全部的視圖函數和全部的邏輯處理函數的功能)

#把這些函數都放在一個py文件裏邊
def login(environ):  #必須給它傳請求接收信息,用不用獲得再說
    with open("templates/login.html","rb")as f:
        data = f.read()
    return data
def index(environ):
    with open("templates/index.html","rb")as f:
        data = f.read()
    return data
def favi(environ):
    with open("templates/favicon.ico", "rb")as f: 
        data = f.read()
    return data #大家返回數據,我把數據返回到列表裏

def reg(environ):
    with open("templates/regs.html", "rb")as f:
        data = f.read()
    return data

 

urls.py(分發功能)

from views import *
url_patterns = [
        ("/login", login),  #視圖函數
        ("/regs", reg),
        ("/index", index),
        ("/favicon.ico",favi)
]

main.py(封裝socket和整個程序的啓動功能)

from wsgiref.simple_server import make_server

def application(environ, start_response): #請求來了就用application來處理;全部的數據都在environ這個字典裏,start_response來給咱們處理格式
    start_response('200 OK', [('Content-Type','text/html')]) #狀態碼、響應頭
    print("PATH", environ.get("PATH_INFO"))
    #當前請求路徑
    path = environ.get("PATH_INFO")

    from urls import url_patterns
    func = None
    for item in url_patterns:
        if path == item[0]:
            func = item[1]  #跟上邊的login匹配成功了
            break
    if func:
        return [func(environ)]
    else:
        return [b'404!']

httpd = make_server('', 8080, application) #封裝的socket
print('Serving HTTP on port 8000.。')
#開始監聽HTTP請求:
httpd.serve_forever()

擴展框架關於數據庫的操做

models.py

#生成用戶表

import pymysql
#鏈接數據庫
conn = pymysql.connect(host='127.0.0.1',port= 3306,user = 'root',passwd='',db='new_web') #db:庫名
#建立遊標
cur = conn.cursor()

sql='''
create table userinfo(
        id INT PRIMARY KEY ,
        name VARCHAR(32) ,
        password VARCHAR(32)
)

'''
cur.execute(sql)

#提交
conn.commit()
#關閉指針對象
cur.close()
#關閉鏈接對象
conn.close()

而後要去在mysql裏邊去建立用戶表,添加字段。

mysql> create database new_web;
Query OK, 1 row affected (0.21 sec)

mysql> use new_web;
Database changed
mysql>
mysql> show tables;
+-------------------+
| Tables_in_new_web |
+-------------------+
| userinfo          |
+-------------------+
1 row in set (0.17 sec)

mysql> desc userinfo; +----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int(11)     | NO   | PRI | NULL    |       |
| name     | varchar(32) | YES  |     | NULL    |       |
| password | varchar(32) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.04 sec)

mysql> insert userinfo values(1,"kris","123");
Query OK, 1 row affected (0.24 sec)

mysql> select * from userinfo;
+----+------+----------+
| id | name | password |
+----+------+----------+
|  1 | kris | 123      |
+----+------+----------+
1 row in set (0.00 sec)

urls.py

from views import *
url_patterns = [
        ("/login", login),  #視圖函數
        ("/regs", regs),
        ("/index", index),
        ("/favicon.ico",favi),
        ("/timer",timer),
        ("/auth",auth),
]

 

backend.html

<body>
<h3>login successful</h3>
</body>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h4>登陸頁面</h4> 
    <form action="http://127.0.0.1:8080/auth" method="post">    action=必需要加好,否則不跳轉哦
        用戶名<input type="text" name="user">
        密碼<input type="password" name="pwd">
        <input type="submit">
    </form>
</body>
</html>

views.py

 
  
import pymysql
from urllib.parse import parse_qs
def timer(environ):
    import datetime
    now = datetime.datetime.now().strftime("%y-%m-%d %X")
    return now.encode("utf8")

def auth(request): #把用戶名和密碼取出來
    try:
        request_body_size = int(request.get('CONTENT_LENGTH', 0)) #拿到請求體的長度
    except (ValueError):
        request_body_size = 0
    request_body = request['wsgi.input'].read(request_body_size)
    data = parse_qs(request_body)

    user = data.get(b"user")[0].decode("utf8")
    pwd = data.get(b"pwd")[0].decode("utf8")

    # 鏈接數據庫
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='new_web')  # db:庫名
    # 建立遊標
    cur = conn.cursor()
    SQL = "select * from userinfo WHERE NAME ='%s' AND PASSWORD ='%s'" % (user, pwd)
    cur.execute(SQL)

    if cur.fetchone():
        f = open("templates/backend.html", "rb")
        data = f.read()
        data = data.decode("utf8")
        return data.encode("utf8")
    else:
        return b"user or pwd is wrong"

 

web框架 功能總結

相關文章
相關標籤/搜索