美文网首页
Flask中的响应(response)

Flask中的响应(response)

作者: 黄智勇atTAFinder | 来源:发表于2016-09-05 22:13 被阅读0次

目录

  • Flask中的Response.
  • 一些特殊的响应.

Part1: Flask中的Response


示例程序1
from flask import Flask 

app = Flask(__name__)

@app.route('/')
def index():
    return '***Saltriver***'

if __name__ == '__main__':
    app.run()

仍然从Flask.wsgi_app()开始分析. 我们假设整个过程没有异常发生.

    def wsgi_app(self, environ, start_response):
            ...
            try:
               # 此处获得response.
                response = self.full_dispatch_request()
            ...
            # 返回response调用后的结果.
            return response(environ, start_response)
            ...

在full_dispatch_request()中:

    def full_dispatch_request(self):
        ...
            if rv is None:
                rv = self.dispatch_request()
                # 设置print语句,用于查看rv的值.
                # 对于示例程序,rv的值为'***Saltriver***'
                print('rv--->', rv)
        ...
        response = self.make_response(rv)
        response = self.process_response(response)
        ...
        return response

下面我们看self.make_response(rv), make_response文的档说道,rv值可以有4种类型,其中就包括str类型的字符串,其他暂时忽略不管,先分析示例程序中rv为字符串的类型.

    def make_response(self, rv):

        status_or_headers = headers = None
        ...

        if not isinstance(rv, self.response_class):
            # 如果rv为text_type类型.
            if isinstance(rv, (text_type, bytes, bytearray)):
                # 用response_class对rv进行包装(wrap).
                rv = self.response_class(rv, headers=headers,
                                         status=status_or_headers)
                headers = status_or_headers = None
            ...
        ...
        return rv

response_class是如何对rv进行包装的呢?可查看werkzeug官方文档5.4节Response. 文档说, In reality, response objects are nothing more than glorified WSGI applications. 实际上,response对象不过是一个遵循WSGI标准的应用而已. 也就是说,我们甚至可以调用它.调用它时,传入什么参数呢? environ和start_response.
回到full_dispatch_request()中,对于process_response(response),主要做两件事情,调用after_request_functions和设置Cookies, 以此对response做最后的处理.示例程序没有实质性process-response. 最后,返回response(environ, start_response)! 下面来仔细研究研究.

    def run(self, host=None, port=None, debug=None, **options):
        ...
        try:
            # self为一个Flask实例.
            run_simple(host, port, self, **options)
        finally:
            ...

在app.run()里,会调用run_simple函数.我们可以在werkzeug.serving中查看.

    def inner():
        make_server(hostname, port, application, threaded,
                    processes, request_handler,
                    passthrough_errors, ssl_context).serve_forever()

在run_simple()中, 我们会调用make_server(...).serve_forever(), 假设make_server返回的是BaseWSGIServer. 在WSGIRequestHandler中,重点分析run_wsgi()函数.下面看其中的execute函数,因为app(environ, start_response)就在其中执行.

        def execute(app):
            application_iter = app(environ, start_response)
            try:
                for data in application_iter:
                    write(data)
                if not headers_sent:
                    write(b'')
            finally:
                if hasattr(application_iter, 'close'):
                    application_iter.close()
                application_iter = None

由于我们在Flask.wsgi_app(...)返回一个是一个response对象,传入execute函数的app,也就是response对象.

    # Werkzeug/wrappers.py/Class.BaseResponse
    def __call__(self, environ, start_response):
     
        app_iter, status, headers = self.get_wsgi_response(environ)
        start_response(status, headers)
        return app_iter

start_response的任务就是设置了WSGIRequestHandler中run_wsgi中的headers_set变量:

headers_set[:] = [status, response_headers]

而在run_wsgi中的write(data)函数中, 在向wfile写入data之前,会先写入status和response_headers.

        def write(data):
            assert headers_set, 'write() before start_response'
            if not headers_sent:  # <---注意此处.
                status, response_headers = headers_sent[:] = headers_set
                try:
                    code, msg = status.split(None, 1)
                except ValueError:
                    code, msg = status, ""
                self.send_response(int(code), msg)  # <---注意此处.
                header_keys = set()
                for key, value in response_headers:
                    self.send_header(key, value)
                    key = key.lower()
                    header_keys.add(key)
                if 'content-length' not in header_keys:
                    self.close_connection = True
                    self.send_header('Connection', 'close')
                if 'server' not in header_keys:
                    self.send_header('Server', self.version_string())
                if 'date' not in header_keys:
                    self.send_header('Date', self.date_time_string())
                self.end_headers()  # <---注意此处.

            assert type(data) is bytes, 'applications must write bytes'
            self.wfile.write(data)  # <---注意此处.
            self.wfile.flush()

下面是一些留给我自己思考问题(但还没有解决的问题):

  • WSGI接口为什么要这样设计?
  • app_iter为什么是iterable的?
    ... ...
    准备再重新读一遍PEP333. _

Part2


相关文章

网友评论

      本文标题:Flask中的响应(response)

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