成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[轉(zhuǎn)]深入理解wsgiref

Moxmi / 2320人閱讀

摘要:原地址介紹要很好地理解下面的代碼,最好有一定的編程基礎(chǔ),了解的基本概念和流程。這個文件主要是的處理過程,定義調(diào)用處理等等。

原地址:http://cizixs.com/2014/11/09/...
1. 介紹

要很好地理解下面的代碼,最好有一定的 socket 編程基礎(chǔ),了解 socket 的基本概念和流程。

wsgiref 是 PEP 333 定義的 wsgi 規(guī)范的范例實現(xiàn),里面的功能包括了:

操作 wsgi 的環(huán)境變量

應(yīng)答頭部的處理

實現(xiàn)簡單的 HTTP server

簡單的對程序端和服務(wù)器端校驗函數(shù)

我們先看一個簡單的代碼實例,然后跟著例子去理解源碼:

1.1 app.py
# pep333 定義的程序端可調(diào)用對象

def hello_world_app(environ, start_response):
    status = "200 OK" # HTTP Status
    headers = [("Content-type", "text/plain")] # HTTP Headers
    start_response(status, headers)

    # The returned object is going to be printed
    return ["Hello World"]
1.2 server.py
from app import hello_world_app
from wsgiref.simple_server import make_server

httpd = make_server("", 8000, hello_world_app)
print "Serving on port 8000..."

# Serve until process is killed
httpd.serve_forever()

然后執(zhí)行 python server.py 啟動 sever,用 curl 發(fā)送一個請求 curl -i http://localhost:8000/,會有以下輸出:

HTTP/1.0 200 OK
Date: Sat, 08 Nov 2014 09:08:05 GMT
Server: WSGIServer/0.1 Python/2.7.3
Content-type: text/plain
Content-Length: 12

Hello World

server 的終端會有一條記錄:

Serving on port 8000...
localhost - - [08/Nov/2014 09:08:05] "GET / HTTP/1.1" 200 12
2. 源碼分析

你可以使用 python -c "import wsgiref; help(wsgiref)" 查看 wsgiref 庫的路徑和簡介等信息,wsgiref 文件夾的結(jié)構(gòu)如下:

wsgiref
    |-- handlers.py            # 核心代碼,負(fù)責(zé) wsgi 程序的處理
    |-- headers.py             # 頭部處理的代碼
    |-- __init__.py            # 
    |-- simple_server.py       # 簡單的 wsgi HTTP 服務(wù)器實現(xiàn)
    |-- util.py                # 幫助函數(shù)
    `-- validate.py            # wsgi 格式檢查和校驗

主要的代碼結(jié)構(gòu)如下圖所示:

2.1 simple_server.py

我們先看一下 make_server 是怎么啟動一個 wsgi 服務(wù)器的:

def make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler):
    server = server_class((host, port), handler_class)
    server.set_app(app)
    return server

這個函數(shù)做的事情就是:監(jiān)聽在本地的端口上,接受來自客戶端的請求,通過 WSGIServer 和 WSGIRequestHandler 處理后,把請求交給程序的的可調(diào)用對象 app,然后返回 app 的結(jié)果給客戶端。

這里有兩個重要的類:WSGIServer 和 WSGIRequestHandler。下面分別看一下它們的代碼和執(zhí)行的功能。

2.2 WSGIServer
class WSGIServer(HTTPServer):

    """BaseHTTPServer that implements the Python WSGI protocol"""

    application = None

    def server_bind(self):
        """Override server_bind to store the server name."""
        HTTPServer.server_bind(self)
        self.setup_environ()

    def setup_environ(self):
        # Set up base environment
        env = self.base_environ = {}
        env["SERVER_NAME"] = self.server_name
        env["GATEWAY_INTERFACE"] = "CGI/1.1"
        env["SERVER_PORT"] = str(self.server_port)
        env["REMOTE_HOST"]=""
        env["CONTENT_LENGTH"]=""
        env["SCRIPT_NAME"] = ""

    def get_app(self):
        return self.application

    def set_app(self,application):
        self.application = application

WSGIServer 在原來的 HTTPServer 上面封裝了一層,在原來的 HTTPServer 的基礎(chǔ)上又額外做了下面的事情:

覆寫原來的 server_bind 函數(shù),添加初始化 environ 變量的動作

添加了處理滿足 wsgi 的 app 函數(shù):set_app 和 get_app

2.3 WSGIRequestHandler
class WSGIRequestHandler(BaseHTTPRequestHandler):

    server_version = "WSGIServer/" + __version__

    def get_environ(self):
        env = self.server.base_environ.copy()
        env["SERVER_PROTOCOL"] = self.request_version
        env["REQUEST_METHOD"] = self.command
        if "?" in self.path:
            path,query = self.path.split("?",1)
        else:
            path,query = self.path,""

        env["PATH_INFO"] = urllib.unquote(path)
        env["QUERY_STRING"] = query

        host = self.address_string()
        if host != self.client_address[0]:
            env["REMOTE_HOST"] = host
        env["REMOTE_ADDR"] = self.client_address[0]

        if self.headers.typeheader is None:
            env["CONTENT_TYPE"] = self.headers.type
        else:
            env["CONTENT_TYPE"] = self.headers.typeheader

        length = self.headers.getheader("content-length")
        if length:
            env["CONTENT_LENGTH"] = length

        for h in self.headers.headers:
            k,v = h.split(":",1)
            k=k.replace("-","_").upper(); v=v.strip()
            if k in env:
                continue                    # skip content length, type,etc.
            if "HTTP_"+k in env:
                env["HTTP_"+k] += ","+v     # comma-separate multiple headers
            else:
                env["HTTP_"+k] = v
        return env

    def get_stderr(self):
        return sys.stderr

    def handle(self):
        """Handle a single HTTP request"""

        self.raw_requestline = self.rfile.readline()
        if not self.parse_request(): # An error code has been sent, just exit
            return

        handler = ServerHandler(
            self.rfile, self.wfile, self.get_stderr(), self.get_environ()
        )
        handler.request_handler = self      # backpointer for logging
        handler.run(self.server.get_app())

這個類從名字就能知道它的功能——處理客戶端的 HTTP 請求,它也是在原來處理 http 請求的BaseHTTPRequestHandler 類上添加了 wsgi 規(guī)范相關(guān)的內(nèi)容。

get_environ: 解析 environ 變量

handle: 處理請求,把封裝的環(huán)境變量交給 ServerHandler,然后由 ServerHandler 調(diào)用 wsgi app,ServerHandler 類會在下面介紹。

2.4 handler.py

這個文件主要是 wsgi server 的處理過程,定義 start_response、調(diào)用 wsgi app 、處理 content-length 等等。

2.5 UML類圖

3. 一條 HTTP 請求的過程

服務(wù)器端啟動服務(wù),等到客戶端輸入 curl -i http://localhost:8000/ 命令,摁下回車鍵,看到終端上的輸出,整個過程中,wsgi 的服務(wù)器端發(fā)生了什么呢?

服務(wù)器程序創(chuàng)建 socket,并監(jiān)聽在特定的端口,等待客戶端的連接

客戶端發(fā)送 http 請求

socket server 讀取請求的數(shù)據(jù),交給 http server

http server 根據(jù) http 的規(guī)范解析請求,然后把請求交給 WSGIServer

WSGIServer 把客戶端的信息存放在 environ 變量里,然后交給綁定的 handler 處理請求

HTTPHandler 解析請求,把 method、path 等放在 environ,然后 WSGIRequestHandler 把服務(wù)器端的信息也放到 environ 里

WSGIRequestHandler 調(diào)用綁定的 wsgi ServerHandler,把上面包含了服務(wù)器信息,客戶端信息,本次請求信息得 environ 傳遞過去

wsgi ServerHandler 調(diào)用注冊的 wsgi app,把 environ 和 start_response 傳遞過去

wsgi app 將reponse header、status、body 回傳給 wsgi handler

然后 handler 逐層傳遞,最后把這些信息通過 socket 發(fā)送到客戶端

客戶端的程序接到應(yīng)答,解析應(yīng)答,并把結(jié)果打印出來。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/41435.html

相關(guān)文章

  • flask源碼分析,run函數(shù)啟動分析

    摘要:對背后運行機(jī)制感興趣,參考網(wǎng)上資料,結(jié)合源碼分析函數(shù)運行時的機(jī)制,主要整理出函數(shù)調(diào)用棧。以分析首先官方文檔經(jīng)典示例現(xiàn)在來分析啟動時發(fā)生了什么代碼只列出用到的函數(shù),去掉注釋等函數(shù)導(dǎo)入運行函數(shù)主要運行調(diào)用返回類,然后調(diào)用返回類的。 對flask背后運行機(jī)制感興趣,參考網(wǎng)上資料,結(jié)合源碼分析run函數(shù)運行時的機(jī)制,主要整理出函數(shù)調(diào)用棧。以flask0.1分析 首先Flask官方文檔經(jīng)典示例 ...

    Tony 評論0 收藏0
  • 通讀Python官方文檔之wsgiref(未完成)

    摘要:一般來說,這一例行程序用于處理請求的每一部分,例如把路徑作為一系列字典鍵值進(jìn)行處理。,必須是按照中所規(guī)定地鍵值元組列表。行為時回車換行。這個包裝器也可能用模塊指明那些有問題的,但不完全違反的行為。 wsgirf-WSGI功能及參考實現(xiàn) 源碼:Lib/wsgiref Web服務(wù)器網(wǎng)關(guān)接口(Web Server Gateway Interface, WSGI),是用Python寫的一個服務(wù)...

    mumumu 評論0 收藏0
  • Django運行方式及處理流程總結(jié)(xianglong.me)

    摘要:所以,我按照自己的邏輯總結(jié)了一下項目的運行方式和對的基本處理流程。二請求處理流程和其他框架一樣,的處理流程基本類似接受,返回內(nèi)容。在中,中間件組件用字符串表示指向中間件類名的完整路徑。 之前在網(wǎng)上看過一些介紹Django處理請求的流程和Django源碼結(jié)構(gòu)的文章,覺得了解一下這些內(nèi)容對開發(fā)Django項目還是很有幫助的。所以,我按照自己的邏輯總結(jié)了一下Django項目的運行方式和對Re...

    MudOnTire 評論0 收藏0
  • Web 開發(fā)學(xué)習(xí)筆記(4) --- 重定向與HSTS

    摘要:回顧通過前幾篇文章的內(nèi)容我們已經(jīng)搭建了基于框架的一個簡單的應(yīng)用的代碼如下此外我們還為其申請了公網(wǎng)和域名并且部署了的證書現(xiàn)在當(dāng)我們在瀏覽器地址欄輸入即可訪問我們的網(wǎng)站不過我們的網(wǎng)站目前還存在幾個問題無法訪問每次都需要用戶手動輸入前綴以制定形式 回顧 通過前幾篇文章的內(nèi)容, 我們已經(jīng)搭建了基于 Flask 框架的一個簡單的 Web 應(yīng)用, server.py 的代碼如下 from f...

    kevin 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<