Web架構原理

來源:互聯網
上載者:User

標籤:web   python   架構   

前提

一個web架構需要包含的組件或者功能有:

  1. request and response

  2. cookies and session

  3. template engine

  4. wsgi app and wsgi server

對於所有的Web應用,本質上其實就是一個socket服務端,使用者的瀏覽器其實就是一個socket用戶端。

wsgi

首先要瞭解WSGI的相關知識,如下:

  • web server:指的是軟體程式,它從用戶端接受請求,然後返回一個Response,需要注意的是它不建立Response,web app才是建立Response的主體。

  • web app:根據url來建立響應並將響應傳回給web server。

  • WSGI:是一個規範,描述了web server如何與web app互動、web app如何處理請求,它規定每個app必須是一個可調用的對象(方法或者類),接受兩個參數environ和start_response。

實現web server

environ和start_response都是伺服器提供的,所以服務端這邊需要提供如下:

  1. 準備environ參數;

  2. 定義start_response函數;

  3. 調用程式端的可調用對象;

代碼具體如下(取自PEP 333):

import os, sysenc, esc = sys.getfilesystemencoding(), ‘surrogateescape‘def unicode_to_wsgi(u):    # Convert an environment variable to a WSGI "bytes-as-unicode" string    return u.encode(enc, esc).decode(‘iso-8859-1‘)def wsgi_to_bytes(s):    return s.encode(‘iso-8859-1‘)def run_with_cgi(application):    # environ參數,裡面是HTTP請求的環境變數    environ = {k: unicode_to_wsgi(v) for k,v in os.environ.items()}    environ[‘wsgi.input‘]        = sys.stdin.buffer    environ[‘wsgi.errors‘]       = sys.stderr    environ[‘wsgi.version‘]      = (1, 0)    environ[‘wsgi.multithread‘]  = False    environ[‘wsgi.multiprocess‘] = True    environ[‘wsgi.run_once‘]     = True    if environ.get(‘HTTPS‘, ‘off‘) in (‘on‘, ‘1‘):        environ[‘wsgi.url_scheme‘] = ‘https‘    else:        environ[‘wsgi.url_scheme‘] = ‘http‘    headers_set = []    headers_sent = []    # 將應答的資料輸出到終端    def write(data):        out = sys.stdout.buffer        if not headers_set:             raise AssertionError("write() before start_response()")        elif not headers_sent:             # Before the first output, send the stored headers             status, response_headers = headers_sent[:] = headers_set             out.write(wsgi_to_bytes(‘Status: %s\r\n‘ % status))             for header in response_headers:                 out.write(wsgi_to_bytes(‘%s: %s\r\n‘ % header))             out.write(wsgi_to_bytes(‘\r\n‘))        out.write(data)        out.flush()    # 根據程式傳過來的狀態和頭部參數設定響應的狀態和頭部    def start_response(status, response_headers, exc_info=None):        if exc_info:            try:                if headers_sent:                    # Re-raise original exception if headers sent                    raise exc_info[1].with_traceback(exc_info[2])            finally:                exc_info = None     # avoid dangling circular ref        elif headers_set:            raise AssertionError("Headers already set!")        headers_set[:] = [status, response_headers]        return write    # 調用用戶端的對象,並且輸出返回的結果    result = application(environ, start_response)    try:        for data in result:            if data:    # don‘t send headers until body appears                write(data)        if not headers_sent:            write(‘‘)   # send headers now if body was empty    finally:        if hasattr(result, ‘close‘):            result.close()
web app

因為服務端和用戶端需要共同遵守WSGI協議內容,所以用戶端這邊需要使用到服務端提供的environ和start_response,web app需要返回的類型需要是可迭代的。這裡分為三種類型的實現,分別是函數,類,執行個體;

函數
HELLO_WORLD = b"Hello world!\n"# 1. 可調用對象是一個函數def application(environ, start_response):    # HTTP response code and message    status = ‘200 OK‘    # 應答的頭部是一個列表,每對索引值都必須是一個 tuple。    response_headers = [(‘Content-Type‘, ‘text/plain‘),                        (‘Content-Length‘, str(len(HELLO_WORLD)))]    # 調用伺服器程式提供的 start_response,填入兩個參數    start_response(status, response_headers)    # 返回必須是 iterable    return [HELLO_WORLD]
# 2. 可調用對象是一個類class AppClass:    """這裡的可調用對象就是 AppClass 這個類,調用它就能產生可以迭代的結果。          使用方法類似於:        for result in AppClass(env, start_response):             do_somthing(result)    """    def __init__(self, environ, start_response):        self.environ = environ        self.start = start_response    def __iter__(self):        status = ‘200 OK‘        response_headers = [(‘Content-type‘, ‘text/plain‘)]        self.start(status, response_headers)        yield HELLO_WORLD
執行個體
# 3. 可調用對象是一個執行個體class AppClass:    """這裡的可調用對象就是 AppClass 的執行個體,使用方法類似於:        app = AppClass()        for result in app(environ, start_response):             do_somthing(result)    """    def __init__(self):        pass    def __call__(self, environ, start_response):        status = ‘200 OK‘        response_headers = [(‘Content-type‘, ‘text/plain‘)]        self.start(status, response_headers)        yield HELLO_WORLD


Web架構原理

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.