Web架構的引入

來源:互聯網
上載者:User

標籤:set   初始化   mat   open   insert   執行   end   使用者   str   

為什麼會有web架構

有了上一篇內容,靜態、動態web伺服器的實現,已經掌握了用戶端請求到伺服器處理的機制。在動態資源處理中,根據請求 .py 匯入模組應用,然後調用應用入口程式實現動態處理。但是在真實的項目中,肯定有很多應用(.py檔案),按照這種處理機制(每個應用中都要寫一個入口,設定狀態代碼、headers)不符合架構設計原則,這一部分肯定是可以複用的,所用應用應該公用一個入口,這就引入一個概念web架構。

設計思路
  • 把每個應用中入口 application(env,start_response) 提取到web伺服器中,然後在入口中通過路由機制分發到各應用中處理。
代碼如下:- WebFramework.py
`# coding:utf-8import timefrom MyWebServer import WebServerHTML_ROOT_DIR = "./static"class Application(object):    ‘‘‘自訂通用的web架構‘‘‘    # 初始化路由資訊    def __init__(self,urls):        self.urls = urls    # 匹配路由    def __call__(self, env, start_response):        path = env.get("PATH_INFO", "/")        # /static/index.html        if path.startswith("/static"):            file_name = path[7:]            # 開啟檔案,讀取內容            try:                file = open(HTML_ROOT_DIR + file_name, "rb")            except IOError:                # 代表未找到路由資訊,404錯誤                status = "404 Not Found"                headers = []                start_response(status, headers)                return "not found"            else:                file_data = file.read()                file.close()                status = "200 OK"                headers = []                start_response(status, headers)                return file_data.decode("utf-8")        for url,handler in self.urls:            if path == url:                return handler(env,start_response)        # 未匹配到        status = ‘404 Not Found‘        headers = []        start_response(status,headers)        return ‘not found‘def showtime(env,start_response):    status = ‘200 OK‘    headers = [        (‘Content-Type‘, ‘text/plain‘)    ]    start_response(status, headers)    return str(time.time())def sayhello(env,start_response):    status = ‘200 OK‘    headers = [        (‘Content-Type‘,‘text/plain‘)    ]    start_response(status,headers)    return ‘say hello‘def helloworld(env,start_response):    status = ‘200 OK‘    headers =[        (‘Content-Type‘,‘text/plain‘)    ]    start_response(status,headers)    return ‘hello world‘if __name__ == ‘__main__‘:    urls = [        (‘/‘, showtime),        (‘/sayhello‘,sayhello),        (‘/helloworld‘,helloworld)    ]    app = Application(urls)    webServer = WebServer(app)    webServer.bind(8000)    webServer.start()`
- MyWebServer.py
`# coding:utf-8import socketimport reimport sysfrom multiprocessing import ProcessHTML_ROOT_DIR = ‘./static‘WSGI_PY = ‘./wsgipy‘class WebServer(object):    ‘‘‘    簡單的webserver    ‘‘‘    def __init__(self,application):        ‘‘‘application:架構‘‘‘        self.sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        self.sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        self.app = application    def start(self):        self.sock_server.listen(128)        while True:            sock_client, addr = self.sock_server.accept()            print(‘[%s,%s]使用者已串連......‘ % addr)            handle_client_process = Process(target=self.handle_client, args=(sock_client,))            handle_client_process.start()            sock_client.close()    def start_response(self, status, headers):        """                 status = "200 OK"            headers = [                ("Content-Type", "text/plain")            ]            star                """        resp_headers = ‘HTTP/1.1 ‘ + status + ‘\r\n‘        for header in headers:            resp_headers += ‘%s: %s\r\n‘ % header        self.resp_headers = resp_headers    def handle_client(self, sock_client):        ‘‘‘處理用戶端請求‘‘‘        recv_data = sock_client.recv(1024)        #print(‘請求資料:‘, recv_data)        req_lines = recv_data.splitlines()        #for line in req_lines:        #    print(line)        req_start_line = req_lines[0]        #print(req_start_line.decode(‘utf-8‘))        file_name = re.match(r"\w+ +(/[^ ]*) ", req_start_line.decode("utf-8")).group(1)        method = re.match(r"(\w+) +/[^ ]* ", req_start_line.decode("utf-8")).group(1)        env = {            "PATH_INFO": file_name,            "METHOD": method        }        response_body = self.app(env, self.start_response)        response = self.resp_headers + "\r\n" + response_body        # 向用戶端返迴響應資料        sock_client.send(bytes(response, "utf-8"))        # 關閉用戶端串連        sock_client.close()    def bind(self, port):        self.sock_server.bind((‘‘, port))def main():    sys.path.insert(1,WSGI_PY)        webServer = WebServer()    webServer.bind(8000)    webServer.start()if __name__ == ‘__main__‘:    main()`
啟動

入口實在WebFramework.py 中,直接啟動該檔案,用戶端請求指定路徑即可看到效果。但是對於大多架構都是通過命令列啟動,我們不可能在程式中這樣啟動,而且對於webserver來說始終是不變得,變的是web架構,所以改造成命令列啟動,代碼如下:

- WebFramework.py
`# coding:utf-8import timeHTML_ROOT_DIR = "./static"class Application(object):    ‘‘‘自訂通用的web架構‘‘‘    # 初始化路由資訊    def __init__(self,urls):        self.urls = urls    # 匹配路由    def __call__(self, env, start_response):        path = env.get("PATH_INFO", "/")        # /static/index.html        if path.startswith("/static"):            file_name = path[7:]            # 開啟檔案,讀取內容            try:                file = open(HTML_ROOT_DIR + file_name, "rb")            except IOError:                # 代表未找到路由資訊,404錯誤                status = "404 Not Found"                headers = []                start_response(status, headers)                return "not found"            else:                file_data = file.read()                file.close()                status = "200 OK"                headers = []                start_response(status, headers)                return file_data.decode("utf-8")        for url,handler in self.urls:            if path == url:                return handler(env,start_response)        # 未匹配到        status = ‘404 Not Found‘        headers = []        start_response(status,headers)        return ‘not found‘def showtime(env,start_response):    status = ‘200 OK‘    headers = [        (‘Content-Type‘, ‘text/plain‘)    ]    start_response(status, headers)    return str(time.time())def sayhello(env,start_response):    status = ‘200 OK‘    headers = [        (‘Content-Type‘,‘text/plain‘)    ]    start_response(status,headers)    return ‘say hello‘def helloworld(env,start_response):    status = ‘200 OK‘    headers =[        (‘Content-Type‘,‘text/plain‘)    ]    start_response(status,headers)    return ‘hello world‘urls = [    (‘/‘, showtime),    (‘/sayhello‘,sayhello),    (‘/helloworld‘,helloworld)]app = Application(urls)# if __name__ == ‘__main__‘:#     urls = [#         (‘/‘, showtime),#         (‘/sayhello‘,sayhello),#         (‘/helloworld‘,helloworld)#     ]#     app = Application(urls)##     webServer = WebServer(app)#     webServer.bind(8000)#     webServer.start() `
- MyWebServer.py
`# coding:utf-8import socketimport reimport sysfrom multiprocessing import ProcessHTML_ROOT_DIR = ‘./static‘WSGI_PY = ‘./wsgipy‘class WebServer(object):    ‘‘‘    簡單的webserver    ‘‘‘    def __init__(self,application):        ‘‘‘application:架構‘‘‘        self.sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        self.sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        self.app = application    def start(self):        self.sock_server.listen(128)        while True:            sock_client, addr = self.sock_server.accept()            print(‘[%s,%s]使用者已串連......‘ % addr)            handle_client_process = Process(target=self.handle_client, args=(sock_client,))            handle_client_process.start()            sock_client.close()    def start_response(self, status, headers):        """                 status = "200 OK"            headers = [                ("Content-Type", "text/plain")            ]            star                """        resp_headers = ‘HTTP/1.1 ‘ + status + ‘\r\n‘        for header in headers:            resp_headers += ‘%s: %s\r\n‘ % header        self.resp_headers = resp_headers    def handle_client(self, sock_client):        ‘‘‘處理用戶端請求‘‘‘        recv_data = sock_client.recv(1024)        #print(‘請求資料:‘, recv_data)        req_lines = recv_data.splitlines()        #for line in req_lines:        #    print(line)        req_start_line = req_lines[0]        #print(req_start_line.decode(‘utf-8‘))        file_name = re.match(r"\w+ +(/[^ ]*) ", req_start_line.decode("utf-8")).group(1)        method = re.match(r"(\w+) +/[^ ]* ", req_start_line.decode("utf-8")).group(1)        env = {            "PATH_INFO": file_name,            "METHOD": method        }        response_body = self.app(env, self.start_response)        response = self.resp_headers + "\r\n" + response_body        # 向用戶端返迴響應資料        sock_client.send(bytes(response, "utf-8"))        # 關閉用戶端串連        sock_client.close()    def bind(self, port):        self.sock_server.bind((‘‘, port))def main():    sys.path.insert(1,WSGI_PY)    if len(sys.argv) < 2:        sys.exit("python MyWebServer.py Module:app")    module_name, app_name = sys.argv[1].split(‘:‘)    m = __import__(module_name)    app = getattr(m,app_name)    webServer = WebServer(app)    webServer.bind(8000)    webServer.start()if __name__ == ‘__main__‘:    main()`
調用方式

在命令列中,執行如下命令即可啟動webserver服務,模組名稱:應用程式框架名, 其中這裡的app指的是WebFramework.py中Application類的執行個體,其實也就是應用程式框架的執行個體。後續自訂架構的時候,直接調用即可。

`python MyWebServer.py WebFramework:app  `

代碼已上傳到github:python 小程式

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.