51web开发3_路由功能_exc_路由正则匹配

 

专注于为中小企业提供网站设计制作、成都网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业西和免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上1000+企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

 

目录

ver1:...1

ver2,路由字典实现...2

ver3,将路由功能封装成类:...4

ver4,404处理,webob.exc异常:...5

ver5,注册函数改造:...7

路由正则匹配:...10

 

 

 

 

web框架开发:

route路由:

简单说,就是路怎么走,按不同的路径分发数据;

url就是不同资源的路径,不同的路径应对应不同的应用程序来处理;

所以,代码中应增加对路径的分析处理;

 

不管是静态web服务器,还是动态web服务器,都需要路径和资源(或处理程序)的映射,最终返回html的文本;

静态web server,解决路径和文件之间的映射;

动态web server,解决路径和应用程序之间的映射;

所有的web框架都是如此,都有路径配置;

 

 

路由功能实现:

例:

增加路由:

/   #返回欢迎内容

/python   #返回hello python

其它   #404

 

 

ver1:

例:

@dec.wsgify

def app(request):

    res = Response()

    if request.path == '/':

        res.body = '

welcome

'.encode()

    elif request.path == '/python':

        res.body = '

hello python

'.encode()

    else:

        res.status_code = 404

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

    return res

 

 

ver2,路由字典实现

 

例:

def index(request):

    res = Response()

    res.body = '

welcome

'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '

hello python

'.encode()

    return res

 

def notfound(request):

    res = Response()

    res.body = '

Not Found

'.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 = '

welcome

'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '

hello python

'.encode()

    return res

 

def notfound(request):

    res = Response()

    res.body = '

Not Found

'.encode()

    return res

 

route_table = {

    '/': index,

    '/python': showpython

}

 

@dec.wsgify

def app(request):

    return route_table.get(request.path, notfound)(request)

 

例:

增加注册功能;

def index(request):

    res = Response()

    res.body = '

welcome

'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '

hello python

'.encode()

    return res

 

def notfound(request):

    res = Response()

    res.body = '

Not Found

'.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,将路由功能封装成类:

思考如何把哪些函数放到外面;

好处,封装在类里的,随着类中代码越来越多,方便之后移走,模块化;

 

例:

from webob import Request, Response, dec

from wsgiref.simple_server import make_server

 

def index(request):

    res = Response()

    res.body = '

welcome

'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '

hello python

'.encode()

    return res

 

class Application:

    def notfound(self, request):

        res = Response()

        res.body = '

Not Found

'.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)   #实例也可注册,但这样不好

    # 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,页面展示先是这三个,再是自定义的body内容;

若要覆盖body,要在Response的__init__()中设置;

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 = '

Not Found

'.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,即便是内部定义的函数有问题也这样,没必要抛5XX之类的错误,防止别人拿到相关信息反推服务器版本之类的,b端不能看到服务器这边的异常

51web开发3_路由功能_exc_路由正则匹配

 

例:

class MyHTTPNotFound(exc.HTTPNotFound):

    code = 404

    title = 'nimei'

    explanation = 'nimeide'

 

class Application:

    # def notfound(self, request):

    #     res = Response()

    #     res.body = '

Not Found

'.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开发3_路由功能_exc_路由正则匹配

 

 

ver5,注册函数改造:

到此步,一个框架的雏形基本完成;

Application()是wsgi app,这个应用程序已变成了一个路由程序,处理逻辑已移到外面,外面的这部分就是留给程序员要完成的;

 

例:

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 = '

welcome

'.encode()

    return res

 

@Application.register('/python')

def showpython(request):

    res = Response()

    res.body = '

hello python

'.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 = '

welcome

'.encode()

    return res

 

@Application.register('/python')

def showpython(request):

    res = Response()

    res.body = '

hello python

'.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()

 

 

路由正则匹配:

以上的路由实现,非常死板,用re改造;

注册的时候,存入不再是路径字符串,而是pattern;

__call__()实现模式和传入路径的比较;

 

注:

httpd编译安装前要装pcre;

nginx自身已打包好相关的正则,所以不依赖第三方库;

 

regex=re.compile(r'PATTERN')   #编译正则表达式;url只一行单选模式即可

regex.match(STRING)   #必须从头开始匹配,只匹配一次

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

regex.fullmatch(STRING)   #完全匹配

regex.findall(STRING)   #从头开始找,找到所有匹配

 

py中分组捕获:

/(?P.*)/(?P.*)   #贪婪

/(?P.*?)/(?P.*?)   #非贪婪

 

例:

@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是路径模式,不能保证其顺序,匹配的时候应是有序的

 

    @classmethod

    def register(cls, pattern):

        def wrapper(handler):

            cls.ROUTE_TABLE.append((re.compile(pattern), handler))  #注册的时候编译正则表达式

            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 = '

hello python

'.encode()

    return res

 

@Application.register('^/$')

def index(request):

    res = Response()

    res.body = '

welcome

'.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()

 

 

 

 

 

 

 

 

 

 

 


名称栏目:51web开发3_路由功能_exc_路由正则匹配
文章源于:http://scyanting.com/article/jsjppd.html