?
專注于為中小企業(yè)提供網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)西和免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上1000+企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
?
目錄
ver1:...1
ver2,路由字典實(shí)現(xiàn)...2
ver3,將路由功能封裝成類:...4
ver4,404處理,webob.exc異常:...5
ver5,注冊(cè)函數(shù)改造:...7
路由正則匹配:...10
?
?
?
?
web框架開發(fā):
route路由:
簡(jiǎn)單說(shuō),就是路怎么走,按不同的路徑分發(fā)數(shù)據(jù);
url就是不同資源的路徑,不同的路徑應(yīng)對(duì)應(yīng)不同的應(yīng)用程序來(lái)處理;
所以,代碼中應(yīng)增加對(duì)路徑的分析處理;
?
不管是靜態(tài)web服務(wù)器,還是動(dòng)態(tài)web服務(wù)器,都需要路徑和資源(或處理程序)的映射,最終返回html的文本;
靜態(tài)web server,解決路徑和文件之間的映射;
動(dòng)態(tài)web server,解決路徑和應(yīng)用程序之間的映射;
所有的web框架都是如此,都有路徑配置;
?
?
路由功能實(shí)現(xiàn):
例:
增加路由:
/?? #返回歡迎內(nèi)容
/python?? #返回hello python
其它?? #404
?
?
例:
@dec.wsgify
def app(request):
??? res = Response()
??? if request.path == '/':
??????? res.body = '
??? elif request.path == '/python':
??????? res.body = '
??? else:
??????? res.status_code = 404
??????? res.body = 'Not Found'.encode()
??? return res
?
?
?
例:
def index(request):
??? res = Response()
??? res.body = '
??? return res
?
def showpython(request):
??? res = Response()
??? res.body = '
??? return res
?
def notfound(request):
??? res = Response()
??? res.body = '
??? return res
?
@dec.wsgify
def app(request):
??? if request.path == '/':
??????? return index(request)
??? elif request.path == '/python':
??????? return showpython(request)
??? else:
??????? return notfound(request)
?
例:
def index(request):
??? res = Response()
??? res.body = '
??? return res
?
def showpython(request):
??? res = Response()
??? res.body = '
??? return res
?
def notfound(request):
??? res = Response()
??? res.body = '
??? return res
?
route_table = {
??? '/': index,
??? '/python': showpython
}
?
@dec.wsgify
def app(request):
??? return route_table.get(request.path, notfound)(request)
?
例:
增加注冊(cè)功能;
def index(request):
??? res = Response()
??? res.body = '
??? return res
?
def showpython(request):
??? res = Response()
??? res.body = '
??? return res
?
def notfound(request):
??? res = Response()
??? res.body = '
??? return res
?
route_table = {}
?
def register(path, handler):
??? route_table[path] = handler
???
register('/', index)
register('/python', showpython)
?
@dec.wsgify
def app(request):
??? return route_table.get(request.path, notfound)(request)
?
?
思考如何把哪些函數(shù)放到外面;
好處,封裝在類里的,隨著類中代碼越來(lái)越多,方便之后移走,模塊化;
?
例:
from webob import Request, Response, dec
from wsgiref.simple_server import make_server
?
def index(request):
??? res = Response()
??? res.body = '
??? return res
?
def showpython(request):
??? res = Response()
??? res.body = '
??? return res
?
class Application:
??? def notfound(self, request):
??????? res = Response()
??????? res.body = '
??????? return res
?
??? ROUTE_TABLE = {}?? #類屬性
?
??? @classmethod?? #類方法和普通方法都可,最好用類方法
??? def register(cls, path, handler):
??????? cls.ROUTE_TABLE[path] = handler
?
??? @dec.wsgify
??? def __call__(self, request:Request) -> Response:
??????? return self.ROUTE_TABLE.get(request.path, self.notfound)(request)
?
Application.register('/', index)
Application.register('/python', showpython)
?
if __name__ == '__main__':
??? ip = '127.0.0.1'
??? port = 9999
??? app = Application()
??? # app.register('/', index)?? #實(shí)例也可注冊(cè),但這樣不好
??? # app.register('/python', showpython)
??? server = make_server(ip, port, app)
??? try:
??????? server.serve_forever()
??? except KeyboardInterrupt:
??????? pass
??? finally:
??????? server.shutdown()
??????? server.server_close()
?
?
查看源碼:
class HTTPNotFound(HTTPClientError):?? #繼承順序HTTPClientError-->HTTPError-->WSGIHTTPException-->Response
??? code = 404
??? title = 'Not Found'
??? explanation = ('The resource could not be found.')
?
注:
code、title、explanation,頁(yè)面展示先是這三個(gè),再是自定義的body內(nèi)容;
若要覆蓋body,要在Response的__init__()中設(shè)置;
class Response(object):
??? def __init__(self, body=None, status=None, headerlist=None, app_iter=None,
???????????????? content_type=None, conditional_response=None, charset=_marker,
???????????????? **kw):
?
例:
class Application:
??? # def notfound(self, request):
??? #???? res = Response()
??? #???? res.body = '
??? #???? return res
?
??? ROUTE_TABLE = {}
?
??? @classmethod
??? def register(cls, path, handler):
??????? cls.ROUTE_TABLE[path] = handler
?
??? @dec.wsgify
??? def __call__(self, request:Request) -> Response:
??????? try:
??????????? return self.ROUTE_TABLE[request.path](request)
??????? except:
??????????? # return self.notfound(request)
??????????? raise exc.HTTPNotFound('您訪問(wèn)的頁(yè)面被外星人劫持了')?? #所有異常都拋404,即便是內(nèi)部定義的函數(shù)有問(wèn)題也這樣,沒必要拋5XX之類的錯(cuò)誤,防止別人拿到相關(guān)信息反推服務(wù)器版本之類的,b端不能看到服務(wù)器這邊的異常
?
例:
class MyHTTPNotFound(exc.HTTPNotFound):
??? code = 404
??? title = 'nimei'
??? explanation = 'nimeide'
?
class Application:
??? # def notfound(self, request):
??? #???? res = Response()
??? #???? res.body = '
??? #???? return res
?
??? ROUTE_TABLE = {}
?
??? @classmethod
??? def register(cls, path, handler):
??????? cls.ROUTE_TABLE[path] = handler
?
??? @dec.wsgify
??? def __call__(self, request:Request) -> Response:
??????? try:
????? ??????return self.ROUTE_TABLE[request.path](request)
??????? except:
??????????? # return self.notfound(request)
??????????? # raise exc.MyHTTPNotFound('您訪問(wèn)的頁(yè)面被外星人劫持了')
??????????? raise MyHTTPNotFound()
?
?
到此步,一個(gè)框架的雛形基本完成;
Application()是wsgi app,這個(gè)應(yīng)用程序已變成了一個(gè)路由程序,處理邏輯已移到外面,外面的這部分就是留給程序員要完成的;
?
例:
from webob import Request, Response, dec, exc
from wsgiref.simple_server import make_server
?
class MyHTTPNotFound(exc.HTTPNotFound):
??? code = 404
??? title = 'nimei'
??? explanation = 'nimeide'
?
class Application:
?
??? ROUTE_TABLE = {}
?
??? @classmethod
??? def register(cls, path):
??????? def wrapper(handler):
??????????? cls.ROUTE_TABLE[path] = handler
??????????? return handler
??????? return wrapper
?
??? @dec.wsgify
??? def __call__(self, request:Request) -> Response:
??????? try:
??????????? return self.ROUTE_TABLE[request.path](request)
??????? except:
??????????? # raise exc.MyHTTPNotFound('您訪問(wèn)的頁(yè)面被外星人劫持了')
??????????? raise MyHTTPNotFound()
?
# Application.register('/', index)
# Application.register('/python', showpython)
?
@Application.register('/')
def index(request):
??? res = Response()
??? res.body = '
??? return res
?
@Application.register('/python')
def showpython(request):
??? res = Response()
??? res.body = '
??? return res
?
if __name__ == '__main__':
??? ip = '127.0.0.1'
??? port = 9999
??? app = Application()
??? # app.register('/', index)
??? # app.register('/python', showpython)
??? server = make_server(ip, port, app)
??? try:
??????? server.serve_forever()
??? except KeyboardInterrupt:
??????? pass
??? finally:
??????? server.shutdown()
??????? server.server_close()
?
?
例,簡(jiǎn)潔代碼:
from wsgiref.simple_server import make_server
from webob import Request, Response, dec, exc
?
class Application:
??? ROUTE_TABLE = {}
?
??? @classmethod
??? def register(cls, path):
??????? def wrapper(handler):
??????????? cls.ROUTE_TABLE[path] = handler
??????????? return handler
??????? return wrapper
?
??? @dec.wsgify
??? def __call__(self, request:Request) -> Response:
??????? try:
??????????? return self.ROUTE_TABLE[request.path](request)
??????? except:
??????????? raise exc.HTTPNotFound()
?
@Application.register('/')
def index(request):
??? res = Response()
??? res.body = '
??? return res
?
@Application.register('/python')
def showpython(request):
??? res = Response()
??? res.body = '
??? return res
?
if __name__ == '__main__':
??? ip = '127.0.0.1'
??? port = 9999
??? server = make_server(ip, port, Application())
??? try:
??????? server.serve_forever()
??? except:
??????? pass
??? finally:
??????? server.shutdown()
??????? server.server_close()
?
?
以上的路由實(shí)現(xiàn),非常死板,用re改造;
注冊(cè)的時(shí)候,存入不再是路徑字符串,而是pattern;
__call__()實(shí)現(xiàn)模式和傳入路徑的比較;
?
注:
httpd編譯安裝前要裝pcre;
nginx自身已打包好相關(guān)的正則,所以不依賴第三方庫(kù);
?
regex=re.compile(r'PATTERN')?? #編譯正則表達(dá)式;url只一行單選模式即可
regex.match(STRING)?? #必須從頭開始匹配,只匹配一次
regex.search(STRING)?? #只匹配一次
regex.fullmatch(STRING)?? #完全匹配
regex.findall(STRING)?? #從頭開始找,找到所有匹配
?
py中分組捕獲:
/(?P
/(?P
?
例:
@Application.register('/python$')?? #只匹配/python
@Application.register('^/$')?? #只匹配根,放最后匹配
?
例:
from wsgiref.simple_server import make_server
from webob import Request, Response, dec, exc
import re
?
class Application:
??? # ROUTE_TABLE = {}
??? ROUTE_TABLE = []?? #[(re.compile(pattern), handler)],二元組列表;此處用列表或有序字典;用dict不合適,key是路徑模式,不能保證其順序,匹配的時(shí)候應(yīng)是有序的
?
??? @classmethod
??? def register(cls, pattern):
??????? def wrapper(handler):
??????????? cls.ROUTE_TABLE.append((re.compile(pattern), handler))??#注冊(cè)的時(shí)候編譯正則表達(dá)式
??????????? return handler
??????? return wrapper
?
??? @dec.wsgify
??? def __call__(self, request:Request) -> Response:
??????? for regex, handler in self.ROUTE_TABLE:
???? ???????matcher = regex.search(request.path)??#match()、search()均可
??????????? if matcher:
??????????????? return handler(request)
??????? raise exc.HTTPNotFound()
?
@Application.register('^/python$')?? #有匹配的順序,根放到最后;showpython=Application.register('^/python$')(showpython)
def showpython(request):
??? res = Response()
??? res.body = '
??? return res
?
@Application.register('^/$')
def index(request):
??? res = Response()
??? res.body = '
??? return res
?
if __name__ == '__main__':
??? ip = '127.0.0.1'
??? port = 9999
??? server = make_server(ip, port, Application())
??? try:
??????? server.serve_forever()
??? except:
??????? pass
??? finally:
??????? server.shutdown()
??????? server.server_close()
?
?
?
?
?
?
?
?
?
?
?