类Flask框架实现
路由route

路由功能实现
路由类实现


#路由
# url = 'http://127.0.0.1:9999/python/index.html?id=5&name=wayne&age=20'
# path = '/python/index.html'
class Router:
ROUTETABLE = {}
def register(self,path,handler):
self.ROUTETABLE[path] = handler
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>'
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
router = Router()
router.register('/',indexhandler)
router.register('/python',pythonhandler)
404处理

注册函数的改造
将注册函数改造成装饰器
class Router:
ROUTETABLE = {}
@classmethod #注册路由,装饰器
def register(cls,path):
def wrapper(handler):
cls.ROUTETABLE[path] = handler
return handler
return wrapper
@Router.register('/') #indexhandler = Router.register('/')(indexhandler)
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>'
@Router.register('/python')
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
将路由功能合并到App类中
from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
class Router:
ROUTETABLE = {}
@classmethod #注册路由,装饰器
def register(cls,path):
def wrapper(handler):
cls.ROUTETABLE[path] = handler
return handler
return wrapper
@Router.register('/') #indexhandler = Router.register('/')(indexhandler)
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>'
@Router.register('/python')
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
class App:
_Router = Router
@wsgify
def __call__(self, request:Request):
try:
return self._Router.ROUTETABLE[request.path](request)
except:
raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')
if __name__ == '__main__':
ip = '127.0.0.1'
port = 9999
server = make_server(ip,port,App())
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.server_close()

路由正则匹配



from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re
class Router:
ROUTETABLE = []
@classmethod #注册路由,装饰器
def register(cls,pattern):
def wrapper(handler):
cls.ROUTETABLE.append((re.compile(pattern),handler))
return handler
return wrapper
@Router.register('^/$') #indexhandler = Router.register('/')(indexhandler)
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>'
@Router.register('^/python$')
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
class App:
_Router = Router
@wsgify
def __call__(self, request:Request):
for pattern,handler in self._Router.ROUTETABLE:
if pattern.match(request.path): #正则匹配
return handler(request)
raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')
if __name__ == '__main__':
ip = '127.0.0.1'
port = 9999
server = make_server(ip,port,App())
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.server_close()
正则表达式分组捕获


from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re
class Router:
ROUTETABLE = []
@classmethod #注册路由,装饰器
def register(cls,pattern):
def wrapper(handler):
cls.ROUTETABLE.append((re.compile(pattern),handler))
return handler
return wrapper
@Router.register(r'^/$')
@Router.register(r'^/(?P<id>\d+)$')
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))
@Router.register('^/python$')
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
class App:
_Router = Router
@wsgify
def __call__(self, request:Request):
for pattern,handler in self._Router.ROUTETABLE:
matcher = pattern.match(request.path) #正则匹配
if matcher:
#动态为request增加属性
request.groups = matcher.groups() #所有分组组成的元祖,包括命名分组
request.groupdict = matcher.groupdict() #命名分组组成的字典
return handler(request)
raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')
if __name__ == '__main__':
ip = '127.0.0.1'
port = 9999
server = make_server(ip,port,App())
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.server_close()
Request Method过滤


![]()
1、在register装饰器中增加函参数
class Router:
ROUTETABLE = []
@classmethod #注册路由,装饰器
def register(cls,method,pattern):
def wrapper(handler):
cls.ROUTETABLE.append((method.upper(),re.compile(pattern),handler))
return handler
return wrapper
@Router.register('GET',r'^/$')
@Router.register('GET',r'^/(?P<id>\d+)$')
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))
2、将register分解成不同方法的装饰器
class Router:
ROUTETABLE = []
@classmethod #注册路由,装饰器
def register(cls,method,pattern):
def wrapper(handler):
cls.ROUTETABLE.append((method.upper(),re.compile(pattern),handler))
return handler
return wrapper
@classmethod
def get(cls,pattern):
return cls.register('GET',pattern)

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re
class Router:
ROUTETABLE = [] #列表,有序
@classmethod #注册路由,装饰器
def router(cls,method,pattern):
def wrapper(handler):
cls.ROUTETABLE.append((method.upper(),re.compile(pattern),handler))
return handler
return wrapper
@classmethod
def get(cls,pattern):
return cls.router('GET',pattern)
@classmethod
def post(cls,pattern):
return cls.router('POST',pattern)
@classmethod
def head(cls,pattern):
return cls.router('HEAD',pattern)
@Router.get(r'^/$')
@Router.router('GET',r'^/(?P<id>\d+)$')
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))
@Router.get(r'/python/\d+')
@Router.router('GET','^/python$')
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
class App:
_Router = Router
@wsgify
def __call__(self, request:Request):
for method,pattern,handler in self._Router.ROUTETABLE:
if request.method in method or not method:
matcher = pattern.match(request.path) #正则匹配
if matcher:
#动态为request增加属性
request.groups = matcher.groups() #所有分组组成的元祖,包括命名分组
request.groupdict = matcher.groupdict() #命名分组组成的字典
return handler(request)
raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')
if __name__ == '__main__':
ip = '127.0.0.1'
port = 9999
server = make_server(ip,port,App())
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.server_close()
改进
![]()

from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re
class Router:
ROUTETABLE = [] #列表,有序
@classmethod #注册路由,装饰器
def router(cls,pattern,*methods):
def wrapper(handler):
cls.ROUTETABLE.append(
(tuple(map(lambda x:x.upper(),methods)),
re.compile(pattern),
handler)
)
return handler
return wrapper
@classmethod
def get(cls,pattern):
return cls.router(pattern,'GET')
@classmethod
def post(cls,pattern):
return cls.router(pattern,'POST')
@classmethod
def head(cls,pattern):
return cls.router(pattern,'HEAD')
@Router.router(r'^/(?P<id>\d+)$') #支持所有方法
@Router.get(r'^/$')
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))
@Router.get(r'/python/\d+')
@Router.router('^/python$','GET')
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
class App:
_Router = Router
@wsgify
def __call__(self, request:Request):
for method,pattern,handler in self._Router.ROUTETABLE:
if request.method in method or not method:
matcher = pattern.match(request.path) #正则匹配
if matcher:
#动态为request增加属性
request.groups = matcher.groups() #所有分组组成的元祖,包括命名分组
request.groupdict = matcher.groupdict() #命名分组组成的字典
return handler(request)
raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')
if __name__ == '__main__':
ip = '127.0.0.1'
port = 9999
server = make_server(ip,port,App())
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.server_close()
![]()
路由分组***



![]()


from webob import Request,Response
from webob.dec import wsgify
from wsgiref.simple_server import make_server
from webob.exc import HTTPNotFound
import re
class Router:
def __init__(self,prefix:str=''):
self._prefix = prefix
self._routertable = []
# ROUTETABLE = [] #列表,有序
#注册路由,装饰器
def router(self,pattern,*methods):
def wrapper(handler):
self._routertable.append(
(tuple(map(lambda x:x.upper(),methods)),
re.compile(pattern),
handler)
)
return handler
return wrapper
def get(self,pattern):
return self.router(pattern,'GET')
def post(self,pattern):
return self.router(pattern,'POST')
def head(self,pattern):
return self.router(pattern,'HEAD')
def match(self,request:Request):
#必须先匹配前缀
if not request.path.startswith(self._prefix):
return None
#前缀匹配,说明必须由这个Router实例处理
for method,pattern,handler in self._routertable:
if request.method in method or not method:
#前缀已经是以_prefix开头了,利用replace去掉前缀,且只需要替换一次
matcher = pattern.match(request.path.replace(self._prefix,'',1))
if matcher:
#动态为request增加属性
request.groups = matcher.groups() #所有分组组成的元祖,包括命名分组
request.groupdict = matcher.groupdict() #命名分组组成的字典
return handler(request)
class App:
_Routers = [] #存储所有一级Router对象
#注册
@classmethod
def register(cls,*routers:Router):
for router in routers:
cls._Routers.append(router)
@wsgify
def __call__(self, request:Request):
for router in self._Routers:
response = router.match(request)
if response:
return response
raise HTTPNotFound('<h1>你访问的网页被外星人劫持了</h1>')
#创建Router对象
python = Router('/python')
index = Router('')
#注册
App.register(index,python)
@index.router(r'^/(?P<id>\d+)$') #支持所有方法 http://127.0.0.1:9999/2134
@index.get(r'^/$') #http://127.0.0.1:9999/
def indexhandler(request):
return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))
@python.router(r'^\d+$') #支持所有方法 http://127.0.0.1:9999/python1234
@python.get(r'/python$') #http://127.0.0.1:9999/python/python
def pythonhandler(request):
return "<h1>欢迎来到python.html</h1>"
if __name__ == '__main__':
ip = '127.0.0.1'
port = 9999
server = make_server(ip,port,App())
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.server_close()
字典访问属性化

class AttriDict:
def __init__(self,d:dict):
self.__dict__.update(d if isinstance(d,dict) else {})
def __setattr__(self, key, value):
raise NotImplementedError
def __repr__(self):
return "<Attrdict {}>".format(self.__dict__)
d = {'a':1,'b':2}
do = AttriDict(d)
print(do.__dict__)
print(do.a)
print(do.b)
![]()
#1
class AttriDict:
def __init__(self,d:dict):
self.__dict__.update(d if isinstance(d,dict) else {})
def __setattr__(self, key, value):
raise NotImplementedError #不允许修改属性
def __repr__(self):
return "<Attrdict {}>".format(self.__dict__)
def __len__(self):
return len(self.__dict__)
#2
class Router:
def match(self,request:Request):
#必须先匹配前缀
if not request.path.startswith(self._prefix):
return None
#前缀匹配,说明必须由这个Router实例处理
for method,pattern,handler in self._routertable:
if request.method in method or not method:
#前缀已经是以_prefix开头了,利用replace去掉前缀,且只需要替换一次
matcher = pattern.match(request.path.replace(self._prefix,'',1))
if matcher:
#动态为request增加属性
request.groups = matcher.groups() #所有分组组成的元祖,包括命名分组
request.groupdict = AttriDict(matcher.groupdict()) #命名分组组成的字典
return handler(request)
#3
@index.router(r'^/(?P<id>\d+)$') #支持所有方法 http://127.0.0.1:9999/2134
@index.get(r'^/$') #http://127.0.0.1:9999/
def indexhandler(request):
# return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.get('id'))
return '<h1>欢迎来到index.html</h1>{}'.format(request.groupdict.id)
正则表达式的化简***



![]()
#类型字符串映射到正则表达式
TYPEPATTERNS = {
'str':r'[^/]+',
'word':r'\w+',
'int':r'[+-]?\d+',
'float':r'[+-]?\d+\.\d+',
'any':r'.+'
}
#类型字符串到python类型的映射
TYPECAST = {
'str':str,
'word':str,
'int':int,
'float':float,
'any':str
}

import re
#1
pattern = r'\d+'
repl = ''
src = 'welcome 123 to 456'
regex = re.compile(pattern)
dest = regex.sub(repl,src)
print(dest)#welcome to
#2
pattern = r'/{([^{}:]+):?([^{}:]*)}'
src = '/student/{name}/xxx/{id:int}'
print(src)
def repl(matcher):
print(matcher.group(0))
print(matcher.group(1))
print(matcher.group(2)) #{name}或{name:}这个分组都匹配为''
return '/(?P<{}>{})'.format(
matcher.group(1),
'T' if matcher.group(2) else 'F'
)
regex = re.compile(pattern)
dest = regex.sub(repl,src)
print(dest) #/student/(?P<name>F)/xxx/(?P<id>T)
![]()
import re
regex = re.compile(r'/{([^{}:]+):?([^{}:]*)}')
s = [
'/student/{name:str}/xxx/{id:int}',
'/student/xxx/{id:int}/yyy',
'/student/xxx/6454654',
'/student/{name:}/xxx/{id:aaa}',
'/student/{name:}/xxx/{id:aaa}'
]
TYPEPATTERNS = {
'str': r'[^/]+',
'word': r'\w+',
'int': r'[+-]?\d+',
'float': r'[+-]?\d+\.\d+',
'any': r'.+'
}
def repl(matcher):
return '/(?P<{}>{})'.format(
matcher.group(1),
TYPEPATTERNS.get(matcher.group(2),TYPEPATTERNS['str'])
)
def parse(src:str):
return regex.sub(repl,src)
for x in s:
print(parse(x))
#运行结果如下:
# /student/(?P<name>[^/]+)/xxx/(?P<id>[+-]?\d+)
# /student/xxx/(?P<id>[+-]?\d+)/yyy
# /student/xxx/6454654
# /student/(?P<name>[^/]+)/xxx/(?P<id>[^/]+)
# /student/(?P<name>[^/]+)/xxx/(?P<id>[^/]+)
将上面的代码合入Router类中
from webob import Request,Response
from webob.exc import HTTPNotFound
from webob.dec import wsgify
from wsgiref.simple_server import make_server
import re
class AttrDict:
def __init__(self,d:dict):
self.__dict__.update(d if isinstance(d,dict) else {})
def __setattr__(self, key, value):
#不允许修改属性
raise NotImplementedError
def __repr__(self):
return "<AttrDict {}>".format(self.__dict__)
def __len__(self):
return len(self.__dict__)
class Router:
__regex = re.compile(r'/{([^{}:]+):?([^{}:]*)}')
TYPEPATTERNS = {
'str':r'[^/]+',
'word':r'\w+',
'int':r'[+-]?\d+',
'float':r'[+-]?\d+\.\d+',
'any':r'.+'
}
def __repl(self,matcher):
return '/(?P<{}>{})'.format(
matcher.group(1),
self.TYPEPATTERNS.get(matcher.group(2),self.TYPEPATTERNS['str'])
)
def __parse(self,src:str):
return self.__regex.sub(self.__repl,src)
#####实例
def __init__(self,prefix:str=''):
self.__prefix = prefix.rstrip('/\\') #前缀,例如/product
self.__routetable = [] #存三元组,列表,有序的
def route(self,pattern,*methods): #注册路由
def wrapper(handler):
#/student/{name:str}/xxx/{id:int} ==> '/student/(?P<name>[^/]+/xxx/(?P<id>[+-]\\d+))'
self.__routetable.append(
(tuple(map(lambda x:x.upper(),methods)),
re.compile(self.__parse(pattern)),
handler
)
)
return handler
return wrapper
def get(self,pattern):
return self.route(pattern,'GET')
def post(self,pattern):
return self.route(pattern,'POST')
def head(self,pattern):
return self.route(pattern,'HEAD')
def match(self,request:Request):
#必须先匹配前缀
if not request.path.startswith(self.__prefix):
return None
#前缀匹配,说明就必须这个Router实例处理,后续匹配不上,依然返回None
for methods,pattern,handler in self.__routetable:
# not methods表示一个方法都没有定义,就是支持全部方法
if not methods or request.method.upper() in methods:
#前提是以__prefix开头了,可以replace,去掉prefix剩下的才是正则表达式需要匹配的路径
matcher = pattern.match(request.path.replace(self.__prefix,'',1))
if matcher:#正则匹配
#动态增加属性
request.groups = matcher.groups()#所有分组组成的元组,包括命名分组
request.groupdict =AttrDict(matcher.groupdict())#命名分组组成的字典被属性化
return handler(request)
class App:
_ROUTERS = [] #存储所有一级对象
#注册
@classmethod
def register(cls,*routers:Router):
for router in routers:
cls._ROUTERS.append(router)
@wsgify
def __call__(self, request:Request):
#遍历_ROUTERS,调用Router实例的match方法,进行匹配
for router in self._ROUTERS:
response = router.match(request)
if response: #匹配返回非None的Router对象
return response
raise HTTPNotFound
#创建Router对象
idx = Router()
py = Router('/python')
#注册
App.register(idx,py)
@idx.get(r'^/$')
@idx.route(r'^/{id:int}$') #支持所有方法
def indexhandler(request):
id = ''
if request.groupdict:
id = request.groupdict.id
return '<h1>magedu.com{}欢迎你</h1>'.format(id)
@py.get(r'^/{id}$')
def pythonhandler(request):
res = Response()
res.charset = 'utf-8'
res.body = '<h1>welcome to Python</h1>'.encode()
return res
if __name__ == '__main__':
ip = '127.0.0.1'
port= 9999
server = make_server(ip,port,App)
try:
server.serve_forever() # server.handle_request() 一次
except KeyboardInterrupt:
server.shutdown()
server.server_close()
![]()
from webob import Request,Response
from webob.exc import HTTPNotFound
from webob.dec import wsgify
from wsgiref.simple_server import make_server
import re
class AttrDict:
def __init__(self,d:dict):
self.__dict__.update(d if isinstance(d,dict) else {})
def __setattr__(self, key, value):
#不允许修改属性
raise NotImplementedError
def __repr__(self):
return "<AttrDict {}>".format(self.__dict__)
def __len__(self):
return len(self.__dict__)
class Router:
__regex = re.compile(r'/{([^{}:]+):?([^{}:]*)}')
TYPEPATTERNS = {
'str':r'[^/]+',
'word':r'\w+',
'int':r'[+-]?\d+',
'float':r'[+-]?\d+\.\d+',
'any':r'.+'
}
TYPECAST = {
'str':str,
'word':str,
'int':int,
'float':float,
'any':str
}
def __parse(self,src: str):
start = 0
repl = ''
types = {}
matchers = self.__regex.finditer(src)
for i, matcher in enumerate(matchers):
name = matcher.group(1)
t = matcher.group(2)
types[name] = self.TYPECAST.get(t, str)
repl += src[start:matcher.start()] #拼接分组前
tmp = '/(?P<{}>{})'.format(
matcher.group(1),
self.TYPEPATTERNS.get(matcher.group(2), self.TYPEPATTERNS['str'])
)
repl += tmp # 替换
start = matcher.end() #移动
else:
repl += src[start:] # 拼接分组后的内容
return repl, types
#####实例
def __init__(self,prefix:str=''):
self.__prefix = prefix.rstrip('/\\') #前缀,例如/product
self.__routetable = [] #存四元组,列表,有序的
def route(self,rule,*methods): #注册路由
def wrapper(handler):
#/student/{name:str}/xxx/{id:int} ==> '/student/(?P<name>[^/]+/xxx/(?P<id>[+-]\\d+))'
pattern,trans = self.__parse(rule) # 用户输入规则转换为正则表达式
self.__routetable.append(
(tuple(map(lambda x:x.upper(),methods)),
re.compile(pattern),
trans,
handler
)#(方法元组,预编译正则对象,类型转换,处理函数)
)
return handler
return wrapper
def get(self,pattern):
return self.route(pattern,'GET')
def post(self,pattern):
return self.route(pattern,'POST')
def head(self,pattern):
return self.route(pattern,'HEAD')
def match(self,request:Request):
#必须先匹配前缀
if not request.path.startswith(self.__prefix):
return None
#前缀匹配,说明就必须这个Router实例处理,后续匹配不上,依然返回None
for methods,pattern,trans,handler in self.__routetable:
# not methods表示一个方法都没有定义,就是支持全部方法
if not methods or request.method.upper() in methods:
#前提是以__prefix开头了,可以replace,去掉prefix剩下的才是正则表达式需要匹配的路径
matcher = pattern.match(request.path.replace(self.__prefix,'',1))
if matcher:#正则匹配
newdict = {}
for k,v in matcher.groupdict().items():
newdict[k] = trans[k](v)
#动态增加属性
request.groupdict =AttrDict(newdict)#命名分组组成的字典被属性化
return handler(request)
class App:
_ROUTERS = [] #存储所有一级对象
#注册
@classmethod
def register(cls,*routers:Router):
for router in routers:
cls._ROUTERS.append(router)
@wsgify
def __call__(self, request:Request):
#遍历_ROUTERS,调用Router实例的match方法,进行匹配
for router in self._ROUTERS:
response = router.match(request)
if response: #匹配返回非None的Router对象
return response
raise HTTPNotFound('<h1>你访问的页面不存在!</h1>')
#创建Router对象
idx = Router()
py = Router('/python')
#注册
App.register(idx,py)
@idx.get(r'^/$')
@idx.route(r'^/{id:int}$') #支持所有方法
def indexhandler(request):
id = ''
if request.groupdict:
id = request.groupdict.id
return '<h1>magedu.com{}欢迎你</h1>'.format(id)
@py.get(r'^/{id}$')
def pythonhandler(request):
if request.groupdict:
print(type(request.groupdict.id))
res = Response()
res.charset = 'utf-8'
res.body = '<h1>welcome to Python</h1>'.encode()
return res
if __name__ == '__main__':
ip = '127.0.0.1'
port= 9999
server = make_server(ip,port,App())
try:
server.serve_forever() # server.handle_request() 一次
except KeyboardInterrupt:
server.shutdown()
server.server_close()

框架处理流程

来源:https://www.cnblogs.com/xiaoshayu520ly/p/11232233.html