(1)CGIhtml
CGI(Common Gateway Interface)通用網關接口,即接口協議,前端向服務器發送一個URL(攜帶請求類型、參數、cookie等信息)請求,服務器把這個請求的各類參數寫進進程的環境變量,好比
REQUEST_METHOD,PATH_INFO之類的,而後開啓 cgi模塊之後,將其發送給CGI程序,CGI程序(能夠由各類語言編寫,好比C、C ++、VB 和Delphi 等)從環境變量中解析出各類參數,而後向標準輸出輸出內容(好比cout了一段HTML代碼),這些內容沒有被打印到控制檯上,而是最終響應給了你的瀏覽器,渲染出了網頁。每一次向CGI發送請求,都會生成一個CGI進程,這就是所謂的fork-and-exec模式,這也一般是致使併發瓶頸的癥結,反向代理加上大型的的分佈式系統能夠必定程度上減輕這些壓力。前端
(2)WSGIpython
WSGI(Python Web Server Gateway Interface,縮寫爲WSGI)web服務器網關接口,也是接口協議,前端向服務器發送一個URL(攜帶請求類型、參數、cookie等信息)請求,服務器把這個請求的各類參數傳給WSGI模塊,wsgi將各類參數進行python化,封裝爲request對象傳遞給按照WSGI接口標準調用註冊的WSGI Application,並返回response參數給客戶端。web
wsgiref是python內置庫,實現了一個簡單的WSGI Server和WSGI Application,使用該庫咱們將很容易實現自定義的web架構而不用考慮TCP/HTTP層協議,庫源碼位於/django/lib/wsgiref文件夾,該庫提供了5個模塊:redis
* util -- Miscellaneous useful functions and wrappers * headers -- Manage response headers * handlers -- base classes for server/gateway implementations * simple_server -- a simple BaseHTTPServer that supports WSGI * validate -- validation wrapper that sits between an app and a server to detect errors in either
下面主要對simple_server模塊的重點函數和使用方法進行說明django
(1)先上一段代碼瀏覽器
該代碼來自simple_server.py的最後7行服務器
if __name__ == '__main__': with make_server('', 8000, demo_app) as httpd: sa = httpd.socket.getsockname() print("Serving HTTP on", sa[0], "port", sa[1], "...") import webbrowser webbrowser.open('http://localhost:8000/xyz?abc') httpd.handle_request() # serve one request, then exit
這段代碼表達兩個意思:啓動服務---->處理'http://localhost:8000/xyz?abc'請求cookie
(2)分析make_server啓動服務過程架構
server_class傳入兩個參數,第一個元組(host,ip),第二個WSGIRequestHandler類,第一個參數用於socketserver.TCPServer啓動服務(圖中標記1),第二個參數WSGIRequestHandler用於BaseServer類初始化self.RequestHandlerClass屬性(圖中標記2),用於finish_request()函數進行對象初始化(圖中的標記3),主要目的實現後面回調函數調用
(3)分析handle_request()函數處理過程
該函數的實現過程在基類BaseServer中,該函數主要實現如下功能(這裏不討論epoll異步併發,相關epoll的內容能夠看我以前的博客):
get_request()---->verify_request()---->process_request()---->shutdown_request()
單看函數名就應該明白整個流程了
(4)如今到重點了,看demo_app回調是如何實現的
接下來主要分析下make_server()函數的第三個參數demo_app是如何實現調用的
經過源碼咱們看到,finish_request()函數中實現了RequestHandlerClass初始化,也就是WSGIRequestHandler初始化
def finish_request(self, request, client_address): """Finish one request by instantiating RequestHandlerClass.""" self.RequestHandlerClass(request, client_address, self)
來張圖一看什麼都清楚了
a. 服務啓動後,WSGIServer經過set_app將回調函數保存起來
b. finish_request()對WSGIRequestHandler進行實例化,調用其基類BaseRequestHandle的構造函數,構造函數中又調用了handle處理函數,因爲派生類WSGIRequestHandler重寫了handle方法,實則調用的是WSGIRequestHandler類的handle函數,如上圖標記3,獲得回調函數對象,並執行。
def run(self, application): try: self.setup_environ() self.result = application(self.environ, self.start_response) self.finish_response() 。。。。。。。。。。。。。。
到如今爲止一切就都清楚了!接下來就能夠自由的對回調函數進行處理了!
模仿django架構的model---->route---->view--->template模型實現http請求,顯示網頁
(1)models.py
使用redis的建立兩個字符串結構name和url
import redis class Model: def __init__(self): conn = redis.Redis() self.name = conn.get('name') self.url = conn.get('url')
(2)urls.py
import views urlpattern = ((r'/fate0729/', views.login),)
(3)views.py
實現經過model對模板進行渲染
from models import Model import re def render(html_path, **wargvs): with open(html_path, 'r') as pf: data = ''.join(pf.readlines()) print(data) if wargvs is not None: # 爲了測試這裏使用了固定格式obj.attr results = re.findall(r'{{(.*)}}', data) for result in results: obj_attr_list = result.partition('.') obj = wargvs.get(obj_attr_list[0]) attr = obj_attr_list[-1] regex = r'{{.*\.%s}}' %(attr) value = getattr(obj,attr).decode('utf-8') print(attr,value) data = re.sub(regex,str(value), data) return data.encode('utf-8') def login(request): model = Model() return render('web.html', **{'model':model})
(4)main.py
from wsgiref.simple_server import make_server import urls def routers(): urlpattern=urls.urlpattern return urlpattern def applications(environ,start_response): path=environ.get("PATH_INFO") start_response('200 OK', [('Content-Type', 'text/html'),('Charset', 'utf8')]) urlpattern=routers() func=None for item in urlpattern: if path==item[0]: func=item[1] break if func: return [func(environ)] else: return [b"<h1>404!<h1>"] if __name__ == '__main__': conn = make_server('127.0.0.1', 8001, applications) print('server is working...') conn.serve_forever()
(5)測試
python main.py
打開瀏覽器輸入:127.0.0.1/fate0729/