1.了解SWGI
一個Web應(yīng)用的本質(zhì)就是:
- 瀏覽器發(fā)送一個HTTP請求娇未;
- 服務(wù)器收到請求淫僻,生成一個HTML文檔;
- 服務(wù)器把HTML文檔作為HTTP響應(yīng)的Body發(fā)送給瀏覽器蛛芥;
- 瀏覽器收到HTTP響應(yīng)商膊,從HTTP Body取出HTML文檔并顯示。
所以,最簡單的Web應(yīng)用就是先把HTML用文件保存好规脸,用一個現(xiàn)成的HTTP服務(wù)器軟件坯约,接收用戶請求,從文件中讀取HTML莫鸭,返回闹丐。Apache、Nginx被因、Lighttpd等這些常見的靜態(tài)服務(wù)器就是干這件事情的卿拴。
如果要動態(tài)生成HTML,就需要把上述步驟自己來實現(xiàn)梨与。不過堕花,接受HTTP請求、解析HTTP請求粥鞋、發(fā)送HTTP響應(yīng)都是苦力活缘挽,如果我們自己來寫這些底層代碼,還沒開始寫動態(tài)HTML呢呻粹,就得花個把月去讀HTTP規(guī)范壕曼。
正確的做法是底層代碼由專門的服務(wù)器軟件實現(xiàn),我們用Python專注于生成HTML文檔等浊。因為我們不希望接觸到TCP連接腮郊、HTTP原始請求和響應(yīng)格式,所以筹燕,需要一個統(tǒng)一的接口轧飞,讓我們專心用Python編寫Web業(yè)務(wù)
這個接口就是WSGI:Web Server Gateway Interface
from wsgiref.simple_server import make_server,demo_app
# 提供兩個必須變量
def app(environ,start_response):
# 調(diào)用start_response發(fā)送頭部
from io import StringIO
#StringIO 把字符串緩存在內(nèi)存中,操作函數(shù)與文件操作基本相同
stdout = StringIO()
# stdout.write('浪里個浪')
# 把字符串輸出到文件中
print("Hello world撒踪,你大爺?shù)?", file=stdout)
h = sorted(environ.items())
for k, v in h:
print(k, '=', repr(v), file=stdout)
# 響應(yīng)http響應(yīng)函數(shù)
start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
# stdout 獲取內(nèi)存中緩存的全部字符串
return [stdout.getvalue().encode("utf-8")]
# 創(chuàng)建服務(wù)器對象 ip地址 端口號 處理http響應(yīng)函數(shù)
server = make_server('0.0.0.0',9000,app)
# 啟動服務(wù)器
server.serve_forever()
make_server()函數(shù):
第一個參數(shù):host 地址
第二個參數(shù):端口號
第三個參數(shù):可調(diào)用對象
- 接收兩個必選參數(shù)environ过咬、start_response,以及一個可選參數(shù)exc_info制妄。參數(shù)名不是固定的援奢,這就意味著你必須使用位置參數(shù)而非關(guān)鍵字參數(shù)(這應(yīng)該是用來約束wsgi服務(wù)器的)
- environ存放CGI規(guī)定的變量一及別的變量。
- start_response 是一個可調(diào)用對象忍捡,通過類似start_response('200 OK',[('Content-Type','text/html'))來發(fā)送http的響應(yīng)的頭部集漾。
- exc_info 只有start_response()被錯誤處理程序調(diào)用時,這個參數(shù)才會提供砸脊,并且是有應(yīng)用對象提供具篇。
返回值是字節(jié)類型的元組,用來表示http body
start_response 函數(shù):
發(fā)送了HTTP響應(yīng)的Header凌埂,注意Header只能發(fā)送一次驱显,也就是只能調(diào)用一次start_response()函數(shù)。start_response()函數(shù)接收兩個參數(shù),一個是HTTP響應(yīng)碼埃疫,一個是一組list表示的HTTP Header伏恐,每個Header用一個包含兩個str的tuple表示。
app函數(shù)return的返回值將作為HTTP響應(yīng)的Body發(fā)送給瀏覽器栓霜。
注意:return app函數(shù)的返回值之前翠桦,必須調(diào)用start_response 把HTTP響應(yīng)的Header返回出去。
無論多么復(fù)雜的Web應(yīng)用程序胳蛮,入口都是一個WSGI處理函數(shù)销凑。HTTP請求的所有輸入信息都可以通過environ獲得,HTTP響應(yīng)的輸出都可以通過start_response()加上函數(shù)返回值作為Body仅炊。
可調(diào)用對象的通過類的實現(xiàn)方式:
class App:
def __call__(self,environ,start_response):
start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
body = '你是豬嗎'
for i, j in environ.items():
body += '<p>' + (str(i) + ':::::' + str(j) + '<br><p>')
return [body.encode('utf-8')]
app = App()
# 創(chuàng)建服務(wù)器對象 ip地址 端口號 處理http響應(yīng)函數(shù)
server = make_server('0.0.0.0',9000,app)
# 啟動服務(wù)器
server.serve_forever()