• Tornado源码分析 --- Redirect重定向


    “重定向”简单介绍:

      “重定向”指的是HTTP重定向,是HTTP协议的一种机制。当client向server发送一个请求,要求获取一个资源时,在server接收到这个请求后发现请求的这个资源实际存放在另一个位置,于是server在返回的response中写入那个请求资源的正确的URL,并设置reponse的状态码为301(永久)或者 302(暂时),当client接受到这个response后就会根据新的URL重新发起请求。重定向有一个典型的特症,即,当一个请求被重定向以后,最终浏览器上显示的URL往往不再是开始时请求的那个URL了。这就是重定向的由来。

    下面我们先看Redirect的源码,之后分析完源码后可以更好的理解其用法。

    Tornado Redirect源码分析:

      在 web.py 中发现有俩个地方实现了重定向的机制:

      1. 基类 RequestHandler 中定义的 self.redirect:

     1 def redirect(self, url, permanent=False, status=None):
     2     if self._headers_written:
     3         raise Exception("Cannot redirect after headers have been written")
     4     if status is None:
     5         status = 301 if permanent else 302
     6     else:
     7         assert isinstance(status, int) and 300 <= status <= 399
     8     self.set_status(status)
     9     self.set_header("Location", utf8(url))
    10     self.finish()

      先看传入进来的参数:

    • url:重定向后所返回的新的URL地址
    • permanent:默认为False,表示该重定向为临时性的;如果为True,则该重定向为永久性。
    • status:当status被指定了值的话,那个该值将会作为HTTP返回给客户端的状态码;如果没有指定特定的值,那么根据上方的permanent状态,如果permanent为True,则该status返回301;如果permanent为False,则该status返回302。

      注: 默认值为302。

      分析:

    1. 通过检测 self._headers_written 的值,来判断是否该请求已经被返回给了客户端:                                                                                                                                                                                                                                                在 基类 RequestHandler 的初始化中,self._headers_written False,之后如果当前输出的缓冲区已经flush到了网络的时候,函数 def flush() 中会将 self._headers_written True。所以此时头信息headers已经别写入了请求且已经返回给了客户端,是无法进行重定向了。
    2. status状态码默认为302,除非permanent参数为True(永久重定向)才会返回301。如果status指定了特定的值的话,那么对指定的值进行数据类型判断,并且status的范围为 300~399,否则会返回异常。
    3. 写入状态信息,以及 字段“Location” (用来重定向接收方到非请求URL的位置来完成请求或标识新的资源)的值
    4. 调用 finish() ,完成该HTTP请求。

      2. 类 RedirectHandler实现的重定向: 

    1 class RedirectHandler(RequestHandler):
    2     def initialize(self, url, permanent=True):
    3          self._url = url
    4          self._permanent = permanent
    5  
    6     def get(self, *args):
    7          self.redirect(self._url.format(*args), permanent=self._permanent)

      介绍和用法:

    • 重定向客户端的GET请求到给定的URL。
    • 需要提供关键参数URL传入该处理类中,例如:
    1 application = web.Application([
    2     (r"/oldpath", web.RedirectHandler, {"url": "/newpath"}),
    3 ])

       在Application中调用该 RedirectHandlerf方法,给定参数“url”,其会将 地址’/oldpath‘ 重定向到 ’/newpath‘ 中。

    • 该类也支持对重定向URL地址进行正则表达式匹配,例如为了实现交换第一个和第二个参数部分,同事保留其余部分不变: 
    1 application = web.Application([
    2     (r"/(.*?)/(.*?)/(.*)", web.RedirectHandler, {"url": "/{1}/{0}/{2}"}),
    3 ])

       最终的URL可以使用格式化方法: str.format,子串会被捕获然后进行对应的匹配。在上面的例子中,一个 “a/b/c” 的请求能够被格式化,如下:   

    str.format("/{1}/{0}/{2}", "a", "b", "c")  # -> "/b/a/c"

      源码分析:

    1. 通过 initiaialize() 函数进行参数 URL, permanent 的初始化。permanent初始化为True,则该重定向为永久化的。
    2. 定义 get() 函数,调用 基类中定义的 self.redirect 进行重定向的处理。

    两种重定向方法的比较和思考:

      对于两种方法中的 permanent 参数,类 RedirectHandler 中默认为True(永久性重定向301);self.redirect中默认为False(临时性重定向302);

      原因:self.redirect 多数情况下被用于用户自定义的情况下进行重定向操作(例如环境变更、用户认证、以及表单提交),所以其默认为临时的重定向。类RedirectHandler 是每次匹配到该请求URL的时候就触发重定向。

      

  • 相关阅读:
    贪心:SPOJ Backup Files
    杂题 SPOJ MOBILE2
    杂题 UVAoj 10000 Longest Paths
    杂题 UVAoj 107 The Cat in the Hat
    DP(斜率优化):HDU 3507 Print Article
    搜索(DLX): POJ 3074 3076 Sudoku
    DLX模板
    PHP代码优化技巧大盘点
    盘点PHP编程常见失误
    PHP Socket 编程详解
  • 原文地址:https://www.cnblogs.com/ShaunChen/p/6652567.html
Copyright © 2020-2023  润新知