溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

51web開發(fā)3_路由功能_exc_路由正則匹配

發(fā)布時(shí)間:2020-06-15 02:14:04 來源:網(wǎng)絡(luò) 閱讀:174 作者:chaijowin 欄目:編程語言

?

?

目錄

ver1... 1

ver2,路由字典實(shí)現(xiàn)... 2

ver3,將路由功能封裝成類:... 4

ver4404處理,webob.exc異常:... 5

ver5,注冊(cè)函數(shù)改造:... 7

路由正則匹配:... 10

?

?

?

?

web框架開發(fā):

route路由:

簡單說,就是路怎么走,按不同的路徑分發(fā)數(shù)據(jù);

url就是不同資源的路徑,不同的路徑應(yīng)對(duì)應(yīng)不同的應(yīng)用程序來處理;

所以,代碼中應(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

?

?

ver1

例:

@dec.wsgify

def app(request):

??? res = Response()

??? if request.path == '/':

??????? res.body = '<h2>welcome</h2>'.encode()

??? elif request.path == '/python':

??????? res.body = '<h2>hello python</h2>'.encode()

??? else:

??????? res.status_code = 404

??????? res.body = 'Not Found'.encode()

??? return res

?

?

ver2,路由字典實(shí)現(xiàn)

?

例:

def index(request):

??? res = Response()

??? res.body = '<h2>welcome</h2>'.encode()

??? return res

?

def showpython(request):

??? res = Response()

??? res.body = '<h2>hello python</h2>'.encode()

??? return res

?

def notfound(request):

??? res = Response()

??? res.body = '<h2>Not Found</h2>'.encode()

??? 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 = '<h2>welcome</h2>'.encode()

??? return res

?

def showpython(request):

??? res = Response()

??? res.body = '<h2>hello python</h2>'.encode()

??? return res

?

def notfound(request):

??? res = Response()

??? res.body = '<h2>Not Found</h2>'.encode()

??? 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 = '<h2>welcome</h2>'.encode()

??? return res

?

def showpython(request):

??? res = Response()

??? res.body = '<h2>hello python</h2>'.encode()

??? return res

?

def notfound(request):

??? res = Response()

??? res.body = '<h2>Not Found</h2>'.encode()

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

?

?

ver3,將路由功能封裝成類:

思考如何把哪些函數(shù)放到外面;

好處,封裝在類里的,隨著類中代碼越來越多,方便之后移走,模塊化;

?

例:

from webob import Request, Response, dec

from wsgiref.simple_server import make_server

?

def index(request):

??? res = Response()

??? res.body = '<h2>welcome</h2>'.encode()

??? return res

?

def showpython(request):

??? res = Response()

??? res.body = '<h2>hello python</h2>'.encode()

??? return res

?

class Application:

??? def notfound(self, request):

??????? res = Response()

??????? res.body = '<h2>Not Found</h2>'.encode()

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

?

?

ver4,404處理,webob.exc異常:

查看源碼:

class HTTPNotFound(HTTPClientError):?? #繼承順序HTTPClientError-->HTTPError-->WSGIHTTPException-->Response

??? code = 404

??? title = 'Not Found'

??? explanation = ('The resource could not be found.')

?

注:

code、title、explanation,頁面展示先是這三個(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 = '<h2>Not Found</h2>'.encode()

??? #???? 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('您訪問的頁面被外星人劫持了')?? #所有異常都拋404,即便是內(nèi)部定義的函數(shù)有問題也這樣,沒必要拋5XX之類的錯(cuò)誤,防止別人拿到相關(guān)信息反推服務(wù)器版本之類的,b端不能看到服務(wù)器這邊的異常

51web開發(fā)3_路由功能_exc_路由正則匹配

?

例:

class MyHTTPNotFound(exc.HTTPNotFound):

??? code = 404

??? title = 'nimei'

??? explanation = 'nimeide'

?

class Application:

??? # def notfound(self, request):

??? #???? res = Response()

??? #???? res.body = '<h2>Not Found</h2>'.encode()

??? #???? 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('您訪問的頁面被外星人劫持了')

??????????? raise MyHTTPNotFound()

51web開發(fā)3_路由功能_exc_路由正則匹配

?

?

ver5,注冊(cè)函數(shù)改造:

到此步,一個(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('您訪問的頁面被外星人劫持了')

??????????? raise MyHTTPNotFound()

?

# Application.register('/', index)

# Application.register('/python', showpython)

?

@Application.register('/')

def index(request):

??? res = Response()

??? res.body = '<h2>welcome</h2>'.encode()

??? return res

?

@Application.register('/python')

def showpython(request):

??? res = Response()

??? res.body = '<h2>hello python</h2>'.encode()

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

?

?

例,簡潔代碼:

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 = '<h2>welcome</h2>'.encode()

??? return res

?

@Application.register('/python')

def showpython(request):

??? res = Response()

??? res.body = '<h2>hello python</h2>'.encode()

??? 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)的正則,所以不依賴第三方庫;

?

regex=re.compile(r'PATTERN')?? #編譯正則表達(dá)式;url只一行單選模式即可

regex.match(STRING)?? #必須從頭開始匹配,只匹配一次

regex.search(STRING)?? #只匹配一次

regex.fullmatch(STRING)?? #完全匹配

regex.findall(STRING)?? #從頭開始找,找到所有匹配

?

py中分組捕獲:

/(?P<biz>.*)/(?P<url>.*)?? #貪婪

/(?P<biz>.*?)/(?P<url>.*?)?? #非貪婪

?

例:

@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 = '<h2>hello python</h2>'.encode()

??? return res

?

@Application.register('^/$')

def index(request):

??? res = Response()

??? res.body = '<h2>welcome</h2>'.encode()

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

?

?

?

?

?

?

?

?

?

?

?


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI