WSGI

1. 瀏覽器請(qǐng)求動(dòng)態(tài)頁(yè)面過程

2. WSGI

怎么在你剛建立的Web服務(wù)器上運(yùn)行一個(gè)Django應(yīng)用Flask應(yīng)用,如何不做任何改變而適應(yīng)不同的web架構(gòu)呢?

在以前,選擇 Python web 架構(gòu)會(huì)受制于可用的web服務(wù)器,反之亦然。如果架構(gòu)和服務(wù)器可以協(xié)同工作,那就好了:

但有可能面對(duì)(或者曾有過)下面的問題,當(dāng)要把一個(gè)服務(wù)器和一個(gè)架構(gòu)結(jié)合起來時(shí),卻發(fā)現(xiàn)他們不是被設(shè)計(jì)成協(xié)同工作的:

3.png

那么,怎么可以不修改服務(wù)器和架構(gòu)代碼而確??梢栽诙鄠€(gè)架構(gòu)下運(yùn)行web服務(wù)器呢?答案就是 Python Web Server Gateway Interface (或簡(jiǎn)稱 WSGI,讀作“wizgy”)。

WSGI允許開發(fā)者將選擇web框架和web服務(wù)器分開。可以混合匹配web服務(wù)器和web框架,選擇一個(gè)適合的配對(duì)。比如,可以在Gunicorn 或者 Nginx/uWSGI 或者 Waitress上運(yùn)行 Django, Flask, 或 Pyramid。真正的混合匹配,得益于WSGI同時(shí)支持服務(wù)器和架構(gòu):

web服務(wù)器必須具備WSGI接口,所有的現(xiàn)代Python Web框架都已具備WSGI接口,它讓你不對(duì)代碼作修改就能使服務(wù)器和特點(diǎn)的web框架協(xié)同工作。

WSGI由web服務(wù)器支持,而web框架允許你選擇適合自己的配對(duì),但它同樣對(duì)于服務(wù)器和框架開發(fā)者提供便利使他們可以專注于自己偏愛的領(lǐng)域和專長(zhǎng)而不至于相互牽制。其他語言也有類似接口:java有Servlet API,Ruby 有 Rack。

3.定義WSGI接口

WSGI接口定義非常簡(jiǎn)單,它只要求Web開發(fā)者實(shí)現(xiàn)一個(gè)函數(shù),就可以響應(yīng)HTTP請(qǐng)求。我們來看一個(gè)最簡(jiǎn)單的Web版本的“Hello World!”:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return 'Hello World!'

上面的application()函數(shù)就是符合WSGI標(biāo)準(zhǔn)的一個(gè)HTTP處理函數(shù),它接收兩個(gè)參數(shù):

  • environ:一個(gè)包含所有HTTP請(qǐng)求信息的dict對(duì)象;
  • start_response:一個(gè)發(fā)送HTTP響應(yīng)的函數(shù)。

整個(gè)application()函數(shù)本身沒有涉及到任何解析HTTP的部分,也就是說,把底層web服務(wù)器解析部分和應(yīng)用程序邏輯部分進(jìn)行了分離,這樣開發(fā)者就可以專心做一個(gè)領(lǐng)域了

不過,等等,這個(gè)application()函數(shù)怎么調(diào)用?如果我們自己調(diào)用,兩個(gè)參數(shù)environ和start_response我們沒法提供,返回的str也沒法發(fā)給瀏覽器。

所以application()函數(shù)必須由WSGI服務(wù)器來調(diào)用。有很多符合WSGI規(guī)范的服務(wù)器。而我們此時(shí)的web服務(wù)器項(xiàng)目的目的就是做一個(gè)既能解析靜態(tài)網(wǎng)頁(yè)還可以解析動(dòng)態(tài)網(wǎng)頁(yè)的服務(wù)器

4. web服務(wù)器-----WSGI協(xié)議---->web框架 傳遞的字典

{
    'HTTP_ACCEPT_LANGUAGE': 'zh-cn',
    'wsgi.file_wrapper': <built-infunctionuwsgi_sendfile>,
    'HTTP_UPGRADE_INSECURE_REQUESTS': '1',
    'uwsgi.version': b'2.0.15',
    'REMOTE_ADDR': '172.16.7.1',
    'wsgi.errors': <_io.TextIOWrappername=2mode='w'encoding='UTF-8'>,
    'wsgi.version': (1,0),
    'REMOTE_PORT': '40432',
    'REQUEST_URI': '/',
    'SERVER_PORT': '8000',
    'wsgi.multithread': False,
    'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'HTTP_HOST': '172.16.7.152: 8000',
    'wsgi.run_once': False,
    'wsgi.input': <uwsgi._Inputobjectat0x7f7faecdc9c0>,
    'SERVER_PROTOCOL': 'HTTP/1.1',
    'REQUEST_METHOD': 'GET',
    'HTTP_ACCEPT_ENCODING': 'gzip,deflate',
    'HTTP_CONNECTION': 'keep-alive',
    'uwsgi.node': b'ubuntu',
    'HTTP_DNT': '1',
    'UWSGI_ROUTER': 'http',
    'SCRIPT_NAME': '',
    'wsgi.multiprocess': False,
    'QUERY_STRING': '',
    'PATH_INFO': '/index.html',
    'wsgi.url_scheme': 'http',
    'HTTP_USER_AGENT': 'Mozilla/5.0(Macintosh;IntelMacOSX10_12_5)AppleWebKit/603.2.4(KHTML,likeGecko)Version/10.1.1Safari/603.2.4',
    'SERVER_NAME': 'ubuntu'
}

應(yīng)用程序示例


import time

def application(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-Type', 'text/html')]
    start_response(status, response_headers)
    return str(environ) + '==Hello world from a simple WSGI application!--->%s\n' % time.ctime()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容