温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2020-06-15 02:14:04 来源:网络 阅读:165 作者:chaijowin 栏目:编程语言

 

 

目录

ver1... 1

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

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

ver4404处理,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 = '<h2>welcome</h2>'.encode()

    elif request.path == '/python':

        res.body = '<h2>hello python</h2>'.encode()

    else:

        res.status_code = 404

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

    return res

 

 

ver2,路由字典实现

 

例:

def index(request):

    res = Response()

    res.body = '<h2>welcome</h2>'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '<h2>hello python</h2>'.encode()

    return res

 

def notfound(request):

    res = Response()

    res.body = '<h2>Not Found</h2>'.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 = '<h2>welcome</h2>'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '<h2>hello python</h2>'.encode()

    return res

 

def notfound(request):

    res = Response()

    res.body = '<h2>Not Found</h2>'.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 = '<h2>welcome</h2>'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '<h2>hello python</h2>'.encode()

    return res

 

def notfound(request):

    res = Response()

    res.body = '<h2>Not Found</h2>'.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 = '<h2>welcome</h2>'.encode()

    return res

 

def showpython(request):

    res = Response()

    res.body = '<h2>hello python</h2>'.encode()

    return res

 

class Application:

    def notfound(self, request):

        res = Response()

        res.body = '<h2>Not Found</h2>'.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()

 

 

ver4404处理,webob.exc异常:

查看源码:

class HTTPNotFound(HTTPClientError):   #继承顺序HTTPClientError-->HTTPError-->WSGIHTTPException-->Response

    code = 404

    title = 'Not Found'

    explanation = ('The resource could not be found.')

 

注:

codetitleexplanation,页面展示先是这三个,再是自定义的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 = '<h2>Not Found</h2>'.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 = '<h2>Not Found</h2>'.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 = '<h2>welcome</h2>'.encode()

    return res

 

@Application.register('/python')

def showpython(request):

    res = Response()

    res.body = '<h2>hello python</h2>'.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 = '<h2>welcome</h2>'.encode()

    return res

 

@Application.register('/python')

def showpython(request):

    res = Response()

    res.body = '<h2>hello python</h2>'.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<biz>.*)/(?P<url>.*)   #贪婪

/(?P<biz>.*?)/(?P<url>.*?)   #非贪婪

 

例:

@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 = '<h2>hello python</h2>'.encode()

    return res

 

@Application.register('^/$')

def index(request):

    res = Response()

    res.body = '<h2>welcome</h2>'.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()

 

 

 

 

 

 

 

 

 

 

 


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI