上篇“python之簡析restful”描述了restful框架,但是代碼部分的例子不能算是一個
框架,很混亂,也僅僅作為演示。
今天介紹本人重新構思后的restful框架。如果你了解restful就應該知道,restful架構的軟件
提供的api並不是確定的,比如: /wm/[a]?p&v=3,這里表示a可以選擇不同的值,具體選擇什么值
需要看提供的手冊,“?”后的屬性也不確定(v=3僅是舉例,p也並不是必須加的)。作為開發者設計
這些url並要求使用者使用這樣的規則得到想要的資源。對於真實的用戶的請求就要根據設計的api
解析出所要的值做后續的處理並得到用戶所要的資源。
本人實現的getAttribute()函數就是為了獲得“?”之前被中括號包表示部分的值,比如用戶輸入
/wm/12?p&v=23,對應的api是/wm/[a]?p&v=3,通過a=getAttrbiute('a')我們就能得到a=12,通過
t=query('p')就能得到t是真,如果用戶不加p就是假,同理,v=query(‘v’)得到23.
還是通過代碼說明吧(python-2.7.5):
1 #-*-coding:UTF-8-*- 2 import socket 3 #import thread 4 import select 5 from urlparse import urlparse 6 7 class Restful: 8 def __init__(self,ip='127.0.0.1',port=12345): 9 self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 10 self.server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 11 self.server.bind((ip,port)) 12 self.server.listen(1) 13 self.client=None 14 self.uri=None 15 self.path=None 16 self.method=None 17 self.body=None 18 self.header=None 19 self.resourceMethod=[] 20 self.urlparser=None 21 self.rest={} 22 def router(self,uri,method='GET'): #這里使用了一點技巧 23 self.uri=uri 24 self.resourceMethod.append(method) 25 def _rout(func): 26 self.rest[uri]=func 27 return _rout 28 def getClientInfo(self): 29 self.client,_=self.server.accept() 30 data=self.client.recv(4096) 31 32 tmp=data.split('\r\n') 33 firstLine=tmp[0] 34 firstLine=firstLine.split() 35 self.method=firstLine[0] 36 self.path=firstLine[1] 37 self.urlparser=urlparse(self.path) 38 l=len(tmp) 39 self.header=tmp[1:l-2] 40 self.body=tmp[l-1] 41 42 res=self.__getKey() 43 if res is None: 44 print 'Url no match' 45 self.client.close() 46 return None 47 print '-->',self.uri 48 if 'GET'==self.__isMethod('GET'): 49 self.do_GET() 50 elif 'POST' ==self.__isMethod('POST'): 51 self.do_POST() 52 elif 'DELETE' == self.__isMethod('DELETE'): 53 self.do_DELETE() 54 elif 'PUT' == self.__isMethod('PUT'): 55 self.do_PUT() 56 def getAttribute(self,attr): #上面介紹的getAttribute()函數在這兒 57 attrs=self.urlparser.path.split('/') 58 formatAttrs=self.uri.split('/') 59 for i in range(len(attrs)): 60 if attr in formatAttrs[i]: 61 return attrs[i] 62 return '' 63 def query(self,param): #上面介紹的query()函數在這兒 64 vals=self.urlparser.query.split('&') 65 if 'POST' == self.__isMethod('POST'): 66 postvals=self.body.split('&') 67 vals+=postvals 68 res=None 69 for v in vals: 70 if param in v: 71 if '=' in v: 72 res= v.split('=')[1] 73 else: 74 res= True 75 if res: 76 return res 77 else: 78 return None 79 def __isMethod(self,m): 80 if m==self.method and m in self.resourceMethod: 81 return m 82 else: 83 return None 84 def __getKey(self): 85 for k in self.rest.keys(): 86 c=k.find('[') 87 ktmp=k[:c] 88 if ktmp in self.urlparser.path: 89 self.uri=k 90 break 91 if self.uri: 92 return True 93 return None 94 def do_GET(self): 95 src=self.rest[self.uri]() 96 self.blocking(src) 97 def do_POST(self): 98 src=self.rest[self.uri]() 99 self.blocking(src) 100 def do_DELETE(self): 101 src=self.rest[self.uri]() 102 self.blocking(src) 103 def do_PUT(self): 104 src=self.rest[self.uri]() 105 self.blocking(src) 106 def run(self): 107 while True: 108 self.getClientInfo() 109 def blocking(self,sendInfo): 110 response='HTTP/1.1 200 OK\r\n'+ \ 111 'Content-type: text/html\r\n\r\n' 112 sendInfo=response+sendInfo+'\r\n' 113 self.client.send(sendInfo) 114 self.client.close() 115 116 #------------Test------------------ #這里是測試部分也是例子 117 rest=Restful() 118 @rest.router('/wm/[a]?') #例子1,router()第二個參數默認是GET方法 119 def test(): 120 a=rest.getAttribute('a') 121 v=rest.query('u') 122 if not v: 123 v='' 124 elif v is True: 125 v='\"true\"' 126 return '{\"test\":'+a+',\"value\":'+v+'}' 127 128 @rest.router('/vpc/[b]') #例子2 129 def test(): 130 attrB=rest.getAttribute('b') 131 return '{\"vpc\":'+attrB+'}' 132 133 @rest.router('/post','POST') #例子3,這里router()第二個參數是POST 134 def testPost(): 135 p=rest.query('p') 136 v=rest.query('v') 137 return '{\"q\":'+p+',\"v\":'+v+'}' 138 rest.run()
通過116行一下的部分我們知道,對於使用restful框架僅僅先實例化Restful類,然后利用
裝飾器提供api,例如:@rest.router('/wm/[a]?'),並實現GET(router函數第二個參數默認為
GET方法)訪問的資源函數,想要獲得用戶實際的值就要通過上面介紹過的兩個函數;最后利用實例
rest.run()運行。
下面是例子1測試:http://127.0.0.1:12345/wm/1?u=12
url中的1和12是不確定部分。
下面是測試例子3的,但是是POST請求使用瀏覽器不方便,就使用curl。
curl -d "p=4&v=1" http://127.0.0.1:12345/post
得到:
{"q":4,"v":1}
測試結果沒做過多的處理,僅僅是獲得請求的值。
好了,使用就是這樣,很簡單。當然還有不足地方,后續更新。
https://github.com/915546302/restful