python實(shí)現(xiàn)web應(yīng)用框架之增加動(dòng)態(tài)路由
今天我們將繼續(xù)對(duì)該框架進(jìn)行路由添加正則表達(dá)式。
本篇文章所依賴的python
環(huán)境為:
路由添加正則表達(dá)式有什么用?
在介紹之前,我們首先要介紹一下Get
獲取資源的時(shí)候,有如下幾種傳參方式:
- 使用
key...value
的形式,將參數(shù)放到url
問號(hào)?
后面,如:http://127.0.0.1/userInfo?name=pdudo
- 在
url
中以路徑參數(shù)的方式傳遞,例如:http://127.0.0.1/userInfo/pdudo/info
。 - 在請(qǐng)求頭中傳遞參數(shù),請(qǐng)求頭是以
key...value
的形式存儲(chǔ)的,當(dāng)然也可以自定義存放請(qǐng)求參數(shù)。
上述的第二種以路徑參數(shù)的方式傳參,就是我們這邊文章所描述的點(diǎn)。
為什么需要這樣做呢?
假設(shè)我們現(xiàn)在正在寫一個(gè)功能,他需要返回傳上來的用戶信息,接口為: /userInfo/userid/infos
,其中userid
是動(dòng)態(tài)的,所以接口可以是/userInfo/c12345/infos
,也可以是/userInfo/d33456/infos
等等。
如果是這種情況,我們應(yīng)該怎么樣樣定義路由呢? 是在項(xiàng)目中給每個(gè)人都定義一個(gè)路由信息么?
很顯然不是的,如果這個(gè)時(shí)候,注冊(cè)的路由恰恰好是正則的,可以獲取客戶端傳上來的參數(shù),例如:/userInfo/pdudo/info
,函數(shù)將會(huì)獲取pdudo
,這樣不是很好么?
這就需要用到正則了。
如何定義動(dòng)態(tài)路由
由于我們此前已經(jīng)寫好了定義靜態(tài)路由的相關(guān)方法,所以我們?cè)诙x動(dòng)態(tài)路由的時(shí)候,最好加一個(gè)識(shí)別參數(shù),告訴框架,這個(gè)路由是靜態(tài)的 還是 動(dòng)態(tài)的。
由于是動(dòng)態(tài)路由,所以在路由url
中,有些值肯定是動(dòng)態(tài)的,如何在區(qū)別于靜態(tài)的值和動(dòng)態(tài)的值呢? 在該框架中,我們將動(dòng)態(tài)值用大括號(hào)括起來,比如: /userInfo/{userID}/infos
,其中userID
是動(dòng)態(tài)的,可以是任何值組成,但是/userInfo
和/infos
必須是靜態(tài)的,而且先后順序也是固定的。
所以說,我們可以約束一下,在定義動(dòng)態(tài)路由的時(shí)候,需要告訴框架,我這個(gè)是動(dòng)態(tài)路由,以及動(dòng)態(tài)url
。
所以我們準(zhǔn)備將動(dòng)態(tài)路由定義規(guī)劃如下:
@myWeb.routes(path="/jobs/{jobID}/startd",methods="post",regular=True) def startJobs(r,cData): print("cData: " ,cData)
上述代碼,是我們即將完善功能后的代碼案例,其中regular
為True
代表該路由是動(dòng)態(tài)的,path
的值為/jobs/{jobID}/startd
,其中jobID
也是動(dòng)態(tài)的,可以被任何值代替。
最后是函數(shù)將接收2個(gè)參數(shù),r
的值代表wsgi
中的environ
信息。 而cData
則代表從客戶端上報(bào)的值,即:jobID
的替代值。
注冊(cè)動(dòng)態(tài)路由
如上我們已經(jīng)約束好了一個(gè)動(dòng)態(tài)路由的添加規(guī)則,那么我們?nèi)绾巫?cè)動(dòng)態(tài)路由呢?
首先肯定的是,動(dòng)態(tài)路由肯定不能和靜態(tài)路由放在一起,所以我們定義了新的字典用于存放動(dòng)態(tài)路由的信息,如:
mapGetRegularRouting = {} mapPostRegularRouting = {}
而后則是我們需要將注冊(cè)的路由信息轉(zhuǎn)換為正則表達(dá)式,這里舉個(gè)例子:
我們注冊(cè)的路由是這樣的: /jobs/{jobID}/startd
,我們需要將其轉(zhuǎn)換為正則表達(dá)式,正則表達(dá)式的值是這樣的: ^/jobs/(.*?)/startd$
。
關(guān)于這段正則表達(dá)式,它的含義是 匹配以/jobs/
開頭和/startd
結(jié)尾的字符串,并且將匹配到的信息(.*
的值)存儲(chǔ)到元組中。
注意這里.*
后面的問號(hào)?
代表不啟用貪婪匹配,也就是最小化匹配。
現(xiàn)在的問題是,如何將{jobsID}
給轉(zhuǎn)換為(.*?)
呢? 在python
中,可以使用re.sub
進(jìn)行替換操作,我們可以使用如下語(yǔ)句,將{jobsID}
給替換為(.*?)
,代碼如下:
import re print(re.sub("{.*?}","(.*?)","/jobs/{jobID}/startd"))
如上代碼執(zhí)行的結(jié)果為:
最后將該路由信息存儲(chǔ)到上述定義好的字典中即可,代碼片段如下:
reFindall = re.compile(r"{(.*?)}") reSubAll = re.compile(r"{.*?}") parameter = re.findall(reFindall,self.path) reText = re.sub(reSubAll,"(.*?)",self.path) reText = f"{reText}$" regular = { "original": self.path, "reText": reText, "parameter": parameter, "func": func } # ... if self.re: mapPostRegularRouting[regular["reText"]] = regular
至此,我們的動(dòng)態(tài)路由就已經(jīng)注冊(cè)好了。
匹配動(dòng)態(tài)路由
相比于注冊(cè)動(dòng)態(tài)路由,當(dāng)客戶端請(qǐng)求來了之后,匹配動(dòng)態(tài)路由會(huì)很麻煩,因?yàn)闆]有請(qǐng)求報(bào)文不是告訴你,這是動(dòng)態(tài)路由還是靜態(tài)路由,所以說,匹配動(dòng)態(tài)路由很麻煩。
我們匹配動(dòng)態(tài)路由想到的時(shí)候笨辦法,即: 先匹配靜態(tài)路由,若靜態(tài)路由匹配不到,則再匹配動(dòng)態(tài)路由,若動(dòng)態(tài)路由都匹配不到的話,則選用默認(rèn)路由。
匹配靜態(tài)路由和動(dòng)態(tài)路由,前面篇章已經(jīng)介紹過了,所以這里不再贅述,這里就介紹如何匹配動(dòng)態(tài)路由。
所謂的動(dòng)態(tài)路由規(guī)則匹配,實(shí)際上就是拿著客戶端上傳的url
,挨個(gè)對(duì)我們已有的正則表達(dá)式做輪訓(xùn),若匹配成功則退出循環(huán),若匹配失敗,最后就返回一個(gè)默認(rèn)路由即可,匹配正則表達(dá)式代碼如下:
for key in RegularRouting.keys(): if re.match(key, path): isRegular = True collText = re.findall(key, path) func = RegularRouting[key]["func"] break else: func = Route["/*"]
框架運(yùn)行效果展示
關(guān)于
myWeb.py
由于很長(zhǎng),有100多行,不好截圖,也不好純復(fù)制代碼了,所以放到了gitee
上面:gitee.com/pdudo/golea…
我們簡(jiǎn)單寫幾個(gè)demo
測(cè)試一下web
框架,代碼如下:
import myWeb import wsgiref.simple_server @myWeb.routes(path="/ip",methods="all") def indx(r): print(r["REMOTE_ADDR"]) return (200,r["REMOTE_ADDR"]) @myWeb.routes(path="/hello/{name}",methods="get",regular=True) def helloWold(r,cData): name = cData[0] return (200,"hello %s" % (name)) def main(): s = wsgiref.simple_server.make_server('', 8888, myWeb.application) s.serve_forever() if __name__ == '__main__': main()
上述代碼,我們首先引入了myWeb
和wsgiref
模塊,前置是我們自己寫的,后則是一個(gè)滿足wsgi
服務(wù)器框架,在代碼中,我們定義了2個(gè)路由信息,一個(gè)是靜態(tài)路由,一個(gè)是動(dòng)態(tài)路由,其中靜態(tài)路由的函數(shù)是indx
,路由信息是/ip
,匹配的客戶端請(qǐng)求方法為get
或者post
,該方法主要返回ip
地址。
動(dòng)態(tài)路由的函數(shù)則是helloWold
,它將匹配到以/hello/
為首的路由信息,匹配客戶端請(qǐng)求方法為get
,還函數(shù)主要獲取用戶發(fā)送的動(dòng)態(tài)值,并且以hello
等返回給客戶端。
在主函數(shù)中,我們啟動(dòng)一個(gè)簡(jiǎn)單的wsgi
服務(wù)器,入口為myWeb
的application
方法 。
代碼運(yùn)行效果如下:
我們分別使用get
和post
方法,請(qǐng)求本地/ip
路由,可見都回復(fù)回來了,而后我們?cè)L問/hello/pdudo
和/hello/juejin
,他們也分別回復(fù)了hello pdudo
和hello juejin
。
總結(jié)
本篇文件介紹了將此前的web
框架,路由修改為正則表達(dá)式形式,具體添加方式為: 在進(jìn)行路由注冊(cè)的時(shí)候,將其路由信息轉(zhuǎn)換為正則表達(dá)式,而在進(jìn)行路由匹配的時(shí)候,先匹配靜態(tài)服務(wù)器,若靜態(tài)服務(wù)器沒有,再進(jìn)行正則匹配,若正則匹配依然不行,則返回最后的默認(rèn)頁(yè)面。
以上就是python實(shí)現(xiàn)web應(yīng)用框架之增加動(dòng)態(tài)路由的詳細(xì)內(nèi)容,更多關(guān)于python增加動(dòng)態(tài)路由的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實(shí)現(xiàn)語(yǔ)音合成功能詳解
這篇文章主要為大家介紹了一個(gè)通過Python制作的小工具,可以實(shí)現(xiàn)語(yǔ)音識(shí)別以及文字轉(zhuǎn)語(yǔ)音的功能,文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的可以動(dòng)手試一試2022-01-01python try except 捕獲所有異常的實(shí)例
今天小編就為大家分享一篇python try except 捕獲所有異常的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-10-10OpenCV+Python識(shí)別車牌和字符分割的實(shí)現(xiàn)
這篇文章主要介紹了OpenCV+Python識(shí)別車牌和字符分割的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01python paramiko模塊學(xué)習(xí)分享
這篇文章主要為大家分享了python paramiko模塊的學(xué)習(xí)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Python實(shí)現(xiàn)簡(jiǎn)單猜拳游戲
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)簡(jiǎn)單猜拳游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01