上篇“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