国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[轉]深入理解wsgiref

Moxmi / 2307人閱讀

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

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

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

wsgiref 是 PEP 333 定義的 wsgi 規范的范例實現,里面的功能包括了:

操作 wsgi 的環境變量

應答頭部的處理

實現簡單的 HTTP server

簡單的對程序端和服務器端校驗函數

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

1.1 app.py
# pep333 定義的程序端可調用對象

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()

然后執行 python server.py 啟動 sever,用 curl 發送一個請求 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 文件夾的結構如下:

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

主要的代碼結構如下圖所示:

2.1 simple_server.py

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

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

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

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

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 的基礎上又額外做了下面的事情:

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

添加了處理滿足 wsgi 的 app 函數: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 規范相關的內容。

get_environ: 解析 environ 變量

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

2.4 handler.py

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

2.5 UML類圖

3. 一條 HTTP 請求的過程

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

服務器程序創建 socket,并監聽在特定的端口,等待客戶端的連接

客戶端發送 http 請求

socket server 讀取請求的數據,交給 http server

http server 根據 http 的規范解析請求,然后把請求交給 WSGIServer

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

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

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

wsgi ServerHandler 調用注冊的 wsgi app,把 environ 和 start_response 傳遞過去

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

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

客戶端的程序接到應答,解析應答,并把結果打印出來。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41435.html

相關文章

  • flask源碼分析,run函數啟動分析

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

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

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

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

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

    MudOnTire 評論0 收藏0
  • Web 開發學習筆記(4) --- 重定向與HSTS

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

    kevin 評論0 收藏0

發表評論

0條評論

Moxmi

|高級講師

TA的文章

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