美文网首页
通过源码看 Flask redirect 返回响应时为响应头的L

通过源码看 Flask redirect 返回响应时为响应头的L

作者: u14e | 来源:发表于2018-05-19 16:33 被阅读164次

背景


使用redirect,让用户登录之后重定向到首页

@bp.route('/login', methods=['GET', 'POST'])
def login():
    ......
    return redirect('/')
    ......

源码执行过程中的关键代码


  1. 首先执行redirect函数,为响应头添加Location属性,并返回响应对象response
def redirect(location, code=302, Response=None):
    ......
    response.headers['Location'] = location  # '/'
    return response
  1. 路由函数返回响应对象responseBaseResponse对象被当作函数调用,并调用__call__方法:
class BaseResponse(object):
    ......
        def __call__(self, environ, start_response):
            app_iter, status, headers = self.get_wsgi_response(environ)
            start_response(status, headers)
            return app_iter
  1. __call__方法调用get_wsgi_response实例方法,处理相关的响应,这里的environ是接收到的请求的一系列数据,包括后面要用到的协议(wsgi.url_scheme):
class BaseResponse(object):
    def get_wsgi_response(self, environ):
        headers = self.get_wsgi_headers(environ)
        app_iter = self.get_app_iter(environ)
        return app_iter, self.status, headers.to_wsgi_list()
  1. get_wsgi_headers方法,处理响应头部信息,调用get_current_url获取当前的绝对路径
class BaseResponse(object):
    def get_wsgi_headers(self, environ):
        headers = Headers(self.headers)
        location = None

        for key, value in headers:
            ikey = key.lower()
            if ikey == u'location':
                location = value  # 首页的话,就是'/'

        if location is not None:
            old_location = location
            if self.autocorrect_location_header:  # 默认为True
                current_url = get_current_url(environ, root_only=True)  # 得到`http://localhost:3000/`
                location = url_join(current_url, location) # 连接后就是`http://localhost:3000/`
            if location != old_location:
                headers['Location'] = location

        return headers
  1. get_current_url函数根据environ['wsgi.url_scheme']获取协议,并返回根路径的绝对路径:
def get_current_url(environ, root_only=False, strip_querystring=False,
                    host_only=False, trusted_hosts=None):
    tmp = [environ['wsgi.url_scheme'], '://', get_host(environ, trusted_hosts)]
    # ['http', '://', 'localhost:3000', '', '/']
    ......
    return uri_to_iri(''.join(tmp)) # 'http://localhost:3000/'
  1. 最后BaseResponse返回给wsgi_app返回给wsgi接口:
class Flask(_PackageBoundObject):
    def wsgi_app(self, environ, start_response):
        return response(environ, start_response)
        
    def __call__(self, environ, start_response):
        return self.wsgi_app(environ, start_response)

结论


所以此时浏览器接收到的响应头部里面的Locationhttp://localhost:3000/,如果使用Nginx反向代理https到本机的http的话,记得设置反向代理头部的协议proxy_set_header X-Forwarded-Proto $scheme;

不然redirect的时候,environ['wsgi.url_scheme']获得的是http,会重定向到http://localhost:3000/,而不是https://localhost:3000/

相关文章

网友评论

      本文标题:通过源码看 Flask redirect 返回响应时为响应头的L

      本文链接:https://www.haomeiwen.com/subject/yffadftx.html