Flask source code interpretation 01: behind app.run() (continued)

As mentioned earlier, processing requests by creating a new Handler class

By default the Handler class is WSGIRequestHandler

class WSGIRequestHandler(BaseHTTPRequestHandler):

    server_version = "WSGIServer/" + __version__

    def get_environ(self):
        env = self.server.base_environ.copy()
        env['SERVER_PROTOCOL'] = self.request_version
        env['REQUEST_METHOD'] = self.command
        if '?' in self.path:
            path,query = self.path.split('?',1)
        else:
            path,query = self.path,''

        env['PATH_INFO'] = urllib.unquote(path)
        env['QUERY_STRING'] = query

        host = self.address_string()
        if host != self.client_address[0]:
            env['REMOTE_HOST'] = host
        env['REMOTE_ADDR'] = self.client_address[0]

        if self.headers.typeheader is None:
            env['CONTENT_TYPE'] = self.headers.type
        else:
            env['CONTENT_TYPE'] = self.headers.typeheader

        length = self.headers.getheader('content-length')
        if length:
            env['CONTENT_LENGTH'] = length

        for h in self.headers.headers:
            k, v = h.split ( ' : ' , 1 )
            k=k.replace('-','_').upper(); v=v.strip()
            if k in env:
                continue                    # skip content length, type,etc.
            if 'HTTP_'+k in env:
                env['HTTP_'+k] += ','+v     # comma-separate multiple headers
            else:
                env['HTTP_'+k] = v
        return env

    def get_stderr(self):
        return sys.stderr

    def handle(self):
        """Handle a single HTTP request"""

        self.raw_requestline = self.rfile.readline()
        if not self.parse_request(): # An error code has been sent, just exit
            return

        handler = ServerHandler(
            self.rfile, self.wfile, self.get_stderr(), self.get_environ()
        )
        handler.request_handler = self      # backpointer for logging
        handler.run(self.server.get_app())

 

WSGIRequestHandler inherits from BaseHTTPRequestHandler of BaseHTTPServer module

BaseHTTPRequestHandler inherits from StreamRequestHandler of SocketServer module  

StreamRequestHandler inherits from BaseRequestHandler of the same module

class BaseRequestHandler:

    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server
        self.setup()
        try:
            self.handle()
        finally:
            self.finish()

    def setup(self):
        pass

    def handle(self):
        pass

    def finish(self):
        pass

In the __init__ method of BaseRequestHandler, when a new Handler object is found, self.handler will be called to process the request, and self.finish will be called after processing.

Along the inheritance chain, it is found that both WSGIRequestHandler and BaseHTTPRequestHandler define the hanlder method, and the definition in WSGIRequestHandler takes precedence

 

class WSGIRequestHandler(BaseHTTPRequestHandler):

    server_version = "WSGIServer/" + __version__

    def handle(self):
        """Handle a single HTTP request"""

        self.raw_requestline = self.rfile.readline()
        if not self.parse_request(): # An error code has been sent, just exit
            return

        handler = ServerHandler(
            self.rfile, self.wfile, self.get_stderr(), self.get_environ()
        )
        handler.request_handler = self      # backpointer for logging
        handler.run(self.server.get_app())

In the handler method, a new instance of the ServerHandler class is created, and then the run method of the instance is called

The reason for creating an instance of the ServerHandler class again is to conform to the WSGI interface. The function of the previous program is to establish a server, the server listens on the specified port, receives the connection from the client, and reads the client's request. Now start processing the client's request, but There are many ways of processing, you can also write a program yourself to parse the client's request, generate a response and return it to the client. 

However, the processing method that conforms to the WSGI interface is: the underlying program parses the client's request and generates an environ dictionary, which represents various information requested by the client. In addition, the start_response function is defined, which is used to send the response start line and Response header. The underlying program passes environ, start_response to the written app, and the app runs to generate a response. This is the response method that conforms to the WSGI interface, and the following program can clearly display it.

    def run(self, application):
        """Invoke the application"""
        # Note to self: don't move the close()!  Asynchronous servers shouldn't
        # call close() from finish_response(), so if you close() anywhere but
        # the double-error branch here, you'll break asynchronous servers by
        # prematurely closing.  Async servers must return from 'run()' without
        # closing if there might still be output to iterate over.
        try:
            self.setup_environ()
            self.result = application(self.environ, self.start_response)
            self.finish_response()
        except:
            try:
                self.handle_error()
            except:
                # If we get an error handling an error, just give up already!
                self.close()
                raise

In the handler's run method, first call setup_environ to create self.environ.

The following statement: self.result = application(self.environ, self.start_response) indicates that the defined app must be a callable object. When calling the app, two parameters, self.environ and self.start_response, are passed in. The result returned by calling the app is stored in self.result. In the finish_response call, self.result is returned to the user. So far, the user's request has been responded to.

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324870017&siteId=291194637