Do-it-yourself Python framework: 1. Introduction to WSGI

In this series, we learn to manually build a web framework by ourselves, and refer to the implementation of the lightweight framework web.py to simplify and realize the most basic functions. Learn about various features of Python in the process of implementation.

This article is also a process of self-learning. Before starting, let me introduce what is WSGI (Web Server Gateway Interface), that is, the Web Server Gateway Interface. WSGI is essentially a specification that defines how web servers interact with Python applications, so that web applications written in Python can be connected to web servers. Those interested in the specification details can check out PEP3333 .

Why is WSGI needed?

Web deployment generally adopts the following solutions:

  1. Deploy a web server dedicated to handling various related tasks at the HTTP protocol level
  2. Deploy an application program developed by a certain language (Java, PHP, Python...), this program receives client requests from the web server, after processing, returns the response information to the web server, and finally returns to the client through the web server end.

This solution needs to solve a problem, how to interact between the Web server and the application server. In order to standardize the interaction between the Web server and the application program, the CGI standard first appeared. WSGI is a standard dedicated to Python. The purpose of these specifications is to unify the interaction specifications and improve the portability of programs.

How does WSGI work?

Before we start playing with our own framework, let's understand how WSGI works. WSGI specifies how to build a bridge between a Web server and a Python application. This bridge solves the following two problems:

1. Let the web server know how to call the Python application, and tell the application the user's request.
2. Let the Python application know what the user's specific request is, and how to return the result to the Web server.

WSGI defines two roles, the Web server side is called server or gateway, and the application side is called application or framework. Below we use the terms server and application uniformly. The general calling process is as follows: the server side will first receive the user's request, and then call the application side according to the requirements of the specification. The result of the call will be encapsulated into an HTTP response and then sent to the client. Refer to the diagram below:

 example analysis

Let's first look at a very simple piece of code, Python3 provides a simple server implementation:

from wsgiref.simple_server import make_server

def application(env, start_response):
    response_body = ['%s: %s' % (k, v) for k, v in sorted(env.items())]
    response_body = '\n'.join(response_body).encode('utf-8')
    status = '200 OK'
    headers = [('Content-Type', 'text/plain'), 
               ('Content-Length', str(len(response_body)))]
    start_response(status, headers)
    return [response_body]
    
if __name__ == '__main__':
    server = make_server('localhost', 8080, application)
    server.serve_forever()
  1. make_server creates a WSGI-compliant server that handles requests using the application function.
  2. The application function has two parameters, env encapsulates the client request information, various system parameters and environment variables of the server. start_response is responsible for telling the server created by make_server the status code and header information of the response.
  3. server.serve_forever() starts the server, processing responses forever.
  4. Note: The returned content must be of bytes type, so the string must be encoded in utf-8 format.

After starting the program, enter http://localhost:8080/xxx/yyy in the browser , we can see the following response:

...
HTTP_HOST: localhost:8080
...
PATH_INFO: /xxx/yyy
...
wsgi.errors: <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>
wsgi.file_wrapper: <class 'wsgiref.util.FileWrapper'>
wsgi.input: <_io.BufferedReader name=624>
wsgi.multiprocess: False
wsgi.multithread: False
wsgi.run_once: False
wsgi.url_scheme: http
wsgi.version: (1, 0)

Guess you like

Origin blog.csdn.net/panda_lin/article/details/121602514