Understanding WSGI

黄舟
Release: 2016-12-16 11:43:54
Original
1411 people have browsed it

In Python web development, the server program can be divided into 2 parts:

Server program (used to receive and organize requests sent by the client)

Application program (processing requests passed by the server program)
In developing applications When programming, we encapsulate commonly used functions into various frameworks, such as Flask, Django, and Tornado (using a certain framework for web development is equivalent to developing server-side applications and processing background logic)
However, server programs and Only applications that work together can provide services to users, and different applications (different frameworks) will have different functions and functions. At this time, we need a standard so that both server programs and applications can support this standard. Then, the two can cooperate well. WSGI: wsgi is a standard for python web development, similar to a protocol. It is a convention between the server program and the application program, which stipulates the interfaces and functions used by each so that the two can cooperate with each other

Part of the provisions of the WSGI application

The application is a callable object

There are three types of callable objects :


A function


A class must implement the __call__() method


An instance of a class


This object receives two parameters

From the source code, we can see that these two parameters are environ , start_response. Taking the callable object as a class as an example:


class application:

def __call__(self, environ, start_response):

pass


The callable object needs to return an iterable value. Take the callable object as a class as an example:

class application:

def __call__(self, environ, start_response):

return [xxx]


Part of the provisions of the WSGI server program

The server program needs to call the application

DEF RUN (Application): #d

environment

Environment = {} #Set parameter

DEF Start_response (xxx): #Set parameter
Pass
Result = Application (ENVIRON, Start_response) # Call the application _ _call__ function (here the application is a class)
  def write(data):
              pass
    def data in result:           #Iterative access
                                                        ’s  ‐    ‐  ‐ ‐                                                                                                                                  Parameters required by the program
2. Call the application
3. Iteratively access the return result of the application and pass it to the client


Middleware

Middleware is the part between the server program and the application. Middleware is very important to the server program. and applications are transparent.

For the server program, the middleware is the application program. The middleware needs to be disguised as the application program and passed to the server program.

For the application program, the middleware is the server program. The middleware needs to be disguised as the server program, accept and call the application program


The server program obtains the URL requested by the client and needs to hand the URL to different functions for processing. This function can be implemented using middleware:

# URL Routing middleware

def urlrouting(url_app_mapping):

def midware_app(environ, start_response): #The function is callable, contains 2 parameters, and returns an iterable value

      url = environ['PATH_INFO']        
                                                            use using url ’s ’           through through through through ’s ’’s ’ through ’ s through ‐ to ‐‐‐ ‐‐‐‐ and
to return an iterable value. #Call application Program u Return Result
Return Midware_app


function Midware_app is Middleware:
On the one hand, the MidWare_app function sets the variables required by the application and calls the application. So for the application, it is a server program
On the other hand, the midware_app function is a callable object that receives two parameters, and the callable object returns an iterable value. So for the server program, it is an application

The logic of writing middleware (middleware):
1. Middleware needs to be disguised as an application—> Requirements for WSGI applications—> 1. Callable 2. Two Parameters 3. Return an iterable value
2. The middleware needs to disguise itself as a server program—> WSGI server program requirements—> Call the application

We need to understand the variable environ. In WSGI, the application requires two parameters: environ and start_response. These two parameters need to be set before the server program calls the application. Among them, start_response is usually a callable method, and environ is a dictionary, which is defined in CGI. Check the CGI document The Common Gateway Interface Specification to find the definition of environ.
The following are the parameters in environ:

AUTH_TYPE
CONTENT_LENGTH #The Content-Length part of the HTTP request
CONTENT_TYPE #The Content-Tpye part of the HTTP request
GATEWAY_INTERFACE
HTTP_* #Contains a series of variables, such as HTTP_HOST, HTTP_ACCEPT, etc.
PATH_INFO #The remaining part of the URL path except the initial part is used to find the corresponding application object. If the requested path is the root path, this value is an empty string
PATH_TRANSLATED
QUERY_STRING #In the URL path? The following part
REMOTE_ADDR
REMOTE_HOST
REMOTE_IDENT
REMOTE_USER
REQUEST_METHOD #HTTP request method, such as "GET", "POST"
SCRipT_NAME #The application object corresponding to the starting part of the URL path, if the application object corresponds to the root of the server, Then this value can be an empty string
SERVER_NAME
SERVER_PORT
SERVER_PROTOCOL #Protocol requested by the client (HTTP/1.1 HTTP/1.0)
SERVER_SOFTWARE

Example: http://localhost:5000/aaa?666, the variable value is :

REQUEST_METHOD='GET'
SCRIPT_NAME=''
SERVER_NAME='localhost'
SERVER_PORT='5000'
PATH_INFO='/aaa'
QUERY_STRING='666'
SERVER_PROTOCOL='HTTP/1.1'
CONTENT_TYPE=' text/plain'
CONTEN_LENGTH=''

HTTP_HOST = 'localhost:8000'
HTTP_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q= 0.8'
HTTP_ACCEPT_ENCODING = 'gzip,deflate,sdch'
HTTP_ACCEPT_LANGUAGE = 'en-US,en;q=0.8,zh;q=0.6,zh-CN;q=0.4,zh-TW;q=0.2'
HTTP_CONNECTION = 'keep-alive'
HTTP_USER_AGENT = 'Mozilla/5.0 (X11; linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36'

For start_response() function:
start_response is HTTP The beginning of the response, its form is: start_response(status, response_headers, exc_info=None)
status represents the HTTP status code, such as 200 OK
response_headers is a list, and the list element is a tuple: (header_name, header_value)
exc_info is optional Parameter, when an error occurs during request processing, this parameter will be set, and start_response will be called at the same time. Let’s take an example from the official werkzeug document. I slightly improved it for analysis (it is recommended to read this paragraph after reading wsgi.py second See part of the SharedDataMiddleware class again):

class Shortly(object):


def __init__(self, config):
self.redis = redis.Redis(config['redis_host'], config['redis_port'])

def dispatch_request(self, request):
return Response('Hello World!') #Initialize the Response class

def wsgi_app(self, environ, start_response):
request = Request(environ)
res ponse = self.dispatch_request(request ) #Response type is the response class
Print ('%%%%%owventage%%%%owventage. Response's __call__ function is the application, returning the iteration object

def __call__(self, environ, start_response):
print(self.wsgi_app)
print('erghrgheoghegoierge')
return self. wsgi_app(environ, start_response)
EDef Create_app (redis_host = 'localhost', redis_port = 6379, with_Static = TRUE):
app = shortly ({
'redis_host': redis_host,
'redis_p Ort ': Redis_port
})
if with_static:
Print (' yes')
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
                                                                                                                                                                                  yes'
return app
#Start the local server
if __name__ == '__main__':
from werkzeug.serving import run_simple
app = create_app() #Create an instance of the application
run_simple('127.0.0.1', 5000, app, use_debugger =True, use_reloader=True)

We look at the source code of Response (Response inherits BaseResponse, just look at the source code of BaseResponse) and we can know: the value returned by the function dispatch_request() is the constructor of Request, that is, a Response class is returned. In the function wsgi_app(), request The value type is Response, so the return value response(environ, start_response) of wsgi_app() actually calls the __call__() function of the Response class.
After looking at the source code, we can find that __call__() is a WSGI application!

When running this program:

22222222222222222
yes
333333333333333
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
2222222 2222222222
yes
33333333333333333

Let’s not worry about why it was read twice.
When we open this web page, the output of the console is:

#Explanation wsgi_app is an instance of SharedDataMiddleware!
erghrgheoghegoierge
%%%%%%%%%%%%%%%%%%%%%%%%% #Indicates that the content in the original wsgi_app function is executed!
127.0.0.1 - - [22/May/2015 21:01:25] "GET / HTTP/1.1" 200 -

You can notice that in this example, the app.wsgi_app method has become a SharedDataMiddleware Class instance, I am very curious about why wsgi_pp still executes the content in the original wsgi_app after the server passes environ and start_response to the app?
When we access the host address, the server program accepts the user request, and then passes environ and start_response to the application app. The app will execute the __call__ function, in which the app.wsgi_app function will be executed. Then wsgi_app will execute the __call__() function of ShareDataMiddleware. Here we need to look at the source code of __call__() of the SharedDataMiddleware class. Looking at the source code, we can find that since the user did not request a static file, return self.app(environ, start_response) will be executed. In this example, we can see that in create_app(), the ShareDataMiddleware application we defined is app.wsgi_app, so what is returned here is the original wsgi_app function! So of course the original function will be executed~
At the same time, we can also put a file in the static folder, and then try accessing it: 127.0.0.1/static/filename, and you can see the file now!
Through this example, we can have a deeper understanding of the role of Middleware:

Middleware is between the server program and the application program. It will receive messages from the server (environ and

start_response), and do certain processing, and then Pass the parts that need to be processed by the application to the application for processing

In addition, the server program also needs to define WSGI-related variables:

wsgi.version                                                                                                                                                             to




-wsgi.version to be processed by the application,


                                                                                                            
Indicates the mode of the url, such as "https" or "http"                                                                                                                                                                                                                            ​                                    Â                                                                                                wsgi.erros                                                                  .multithread
If the application object can be called simultaneously by another thread in the same process, this value is True
wsgi.multiprocess
If the application object can be called simultaneously by another process, this value is True
wsgi.run_once
If The server hopes that the application object will only be called once in the process that contains it, then this value is True

The above is what WSGI understands. For more related articles, please pay attention to the PHP Chinese website (www.php.cn)!



Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template