python web development network programming HTTP protocol, Web server, WSGI interface

Posted by ajaybuilder on Fri, 07 Jan 2022 04:58:43 +0100

Article catalog

learning from python web development from introduction to mastery

1. HTTP protocol

  • The most important protocol in the application layer: HTTP (HyperText Transfer Protocol)
  • When users visit the website, the user browser is the client (send a request to the server), and the website is called the server (after receiving the request, the processed response is transmitted to the client). This process is realized through HTTP protocol
  • TCP is used to transmit information between two computers (such as web server and client). The client uses the web browser to send HTTP request to the web server, and the server sends response to the client

2. Web server

After entering the url in the browser:

  1. The browser requests the DNS server to interpret the domain name and obtain the site IP address
  2. Send an HTTP Request to the host that owns the IP
  3. After receiving the HTTP Response response returned by the server, the browser renders the effect and presents it to the user

How the Web server works:

  • Establish connection: the client establishes a TCP connection to the server through TCP/IP protocol
  • Request process: the client sends an HTTP protocol request package to the server to request resources
  • Response process: the server sends an HTTP protocol response package to the client. If the resource contains dynamic language content, it will be processed first, and the obtained data will be returned to the client. The client interprets the HTML rendering on the screen
  • Close connection: disconnect client and server

Common request methods:

  • GET: requests the specified page
  • POST: submit data (form or file, etc.)
  • HEAD: similar to GET, but only GET the header
  • PUT: replaces the specified document content on the server
  • DELETE: the server deletes the specified page
  • OPTIONS: allows clients to view server performance

Return status code:

  • 1 * *: request received, continue processing
  • 2 * *: response returned successfully
  • 3 * *: redirection, an action that must be further executed in order to complete the request
  • 4 * *: client error, such as syntax error, or the request cannot be implemented
  • 5 * *: server error. The server cannot implement an obviously invalid request

Browser press F12 to view relevant information

3. Static server

  • Pure HTML pages are called static pages

Example: create a static server through which you can access a website containing two static pages

  • Navigation bar page simple_navbar.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>use bootstrap Frame making navigation bar</title>

    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/popper.js/2.9.2/cjs/popper-base.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.js"></script>

</head>
<body>

<nav class="navbar navbar-expand-sm navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="https://michael. blog. csdn. Net / "> My navigation</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="https://michael. blog. csdn. Net / "> Home Page</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#"> link</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                       data-bs-toggle="dropdown" aria-expanded="false">
                        About the author
                    </a>
                    <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <li><a class="dropdown-item" href="#"> resume</a></li>
                        <li><a class="dropdown-item" href="#"> Project</a></li>
                        <li>
                            <hr class="dropdown-divider">
                        </li>
                        <li><a class="dropdown-item" href="contact.html">contact information</a></li>
                    </ul>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled">Shopping Mall</a>
                </li>
            </ul>
            <form class="d-flex">
                <input class="form-control me-2" type="search" placeholder="Enter your keywords" aria-label="Search">
                <button class="btn btn-outline-success" type="submit">Station search</button>
            </form>
        </div>
    </div>
</nav>

</body>
</html>
  • contact.html, based on the above, add some additional contact information
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>contact michael</title>

    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/popper.js/2.9.2/cjs/popper-base.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.js"></script>

</head>
<body>

<nav class="navbar navbar-expand-sm navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="https://michael. blog. csdn. Net / "> My navigation</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="https://michael. blog. csdn. Net / "> Home Page</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#"> link</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                       data-bs-toggle="dropdown" aria-expanded="false">
                        About the author
                    </a>
                    <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <li><a class="dropdown-item" href="#"> resume</a></li>
                        <li><a class="dropdown-item" href="#"> Project</a></li>
                        <li>
                            <hr class="dropdown-divider">
                        </li>
                        <li><a class="dropdown-item" href="contact.html">contact information</a></li>
                    </ul>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled">Shopping Mall</a>
                </li>
            </ul>
            <form class="d-flex">
                <input class="form-control me-2" type="search" placeholder="Enter your keywords" aria-label="Search">
                <button class="btn btn-outline-success" type="submit">Station search</button>
            </form>
        </div>
    </div>
</nav>

<div class="bs-docs-header" id="content" tabindex="-1">
    <div class="container">
        <h1> contact michael </h1>
        <div class="lead">
            <address>
                E-mail:<strong>michael@xxx.com</strong>
                <br>Address: No. 86, global village
                <br>Postal Code:<strong>xxxxxx</strong>
                <br><abbr title="Phone">contact number:</abbr> 1234567890
            </address>
        </div>
    </div>
</div>

</body>
</html>

Create web_server.py

Realize HTTP communication between client and server

Note: because many downloaded css file addresses are written in HTML, the path always reports an error. Finally, it is recommended to quote the CDN writing method and query the addresses of relevant libraries https://www.bootcdn.cn/

<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/popper.js/2.9.2/cjs/popper-base.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.js"></script>
import socket
import re
from multiprocessing import Process  # Multithreading

HTML_ROOT_DIR = './'  # Set the root directory of the static page


class HTTPServer:
    def __init__(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def start(self):
        self.server_socket.listen(128)  # Maximum connections 128
        print("The server is waiting for the client to connect...")
        while True:
            client_socket, client_addr = self.server_socket.accept()  # Establish client connection
            print("[%s, %s]The user is connected" % client_addr)
            handle_client_process = Process(target=self.handle_client, args=(client_socket,))
            # Instantiate the thread, the first parameter calls the function, and the second parameter is passed to the former parameter in tuple form
            handle_client_process.start()  # Open thread
            client_socket.close()  # Close the client socket

    def handle_client(self, client_socket):
        # Processing client requests
        request_data = client_socket.recv(1024)  # Receive client requests
        print("request data:", request_data)
        request_lines = request_data.splitlines()  # Split by line
        for line in request_lines:
            print(line)  # Output information
        request_start_line = request_lines[0]  # Get request message
        print("*" * 10)
        print(request_start_line.decode("utf-8"))
        file_name = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
        # Using a regular expression, extract the requested file name, and group(1) lists the first bracket matching part
        if file_name == "/":
            file_name = "/simple_navbar.html"
        try:
            # Attempt to open file
            file = open(HTML_ROOT_DIR + file_name, "rb")
        except IOError:
            # Failed to read file, return 404
            response_start_line = "HTTP/1.1 404 Not Found\r\n"
            response_headers = "Server: Michael server\r\n"
            response_body = "The file %s is not found! please check again!" % (HTML_ROOT_DIR + file_name)
        else:
            file_data = file.read()
            file.close()
            # Construct response data
            response_start_line = "HTTP/1.1 200 OK\r\n"
            response_headers = "Server: Michael server\r\n"
            response_body = file_data.decode("utf-8")
        # Splice return data
        response = response_start_line + response_headers + "\r\n" + response_body
        print("response data:", response)
        client_socket.send(bytes(response, "utf-8"))  # Send response data to the client
        client_socket.close()  # Close client connection

    def bind(self, port):
        self.server_socket.bind(("127.0.0.1", port))


def main():
    http_server = HTTPServer()
    http_server.bind(8000)
    http_server.start()


if __name__ == "__main__":
    main()

4. WSGI interface

The above implements a static server, but it is rarely used now. It uses more dynamic pages to achieve interactivity

  • For example, when registering and logging in to a website, users enter data, the web server does not process user data (it is not its responsibility), and CGI is born

4.1 CGI general Gateway Interface

  • The Common Gateway Interface is a program that runs on the server
  • The web server sends the request to the CGI application, and then sends the HTML page dynamically generated by CGI back to the client

Limitations of CGI: after the interpreter process is created, it is discarded when it is used up. A large number of requests lead to server downtime

  • CGI enhanced FastCGI appeared, which uses process / thread pool to process a series of requests It reduces the overhead of interaction between web server and CGI program

4.2 WSGI

  • It is not convenient to write asynchronous web services under the FastCGI standard. WSGI (Web Server Gateway Interface) appears

The following figure is from https://www.cnblogs.com/wilber2013/p/4763067.html

4.3 define WSGI interface

The simplest web version hello world

def applications(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, Michael!</h1>']

The above function is an HTTP processing function conforming to the WSGI standard

  • environ: a dictionary object for all HTTP request information
  • start_response: a function that sends an HTTP response

Benefits: web parsing and application logic are separated, and you can do what you are good at

python has built-in WSGI: wsgiref module (it does not consider running efficiency and is only for development and testing)

4.4 running WSGI services

  • wsgi_app.py
# wsgi application
def app(environ, start_response):
    # Response information
    start_response('200 OK', [('Content-Type', 'text/html')])
    file_name = environ['PATH_INFO'][1:] or 'simple_navbar.html'
    HTML_ROOT_DIR = './'
    try:
        # Open file
        file = open(HTML_ROOT_DIR + file_name, 'rb')
    except IOError:
        # Abnormal response
        response_body = "{} not found".format(HTML_ROOT_DIR + file_name)
    else:
        # read file
        file_data = file.read()
        file.close()
        # Construct response data
        response_body = file_data.decode('utf-8')
    return [response_body.encode('utf-8')]  # Return data
  • wsgi_server.py
# WSGI server
from wsgiref.simple_server import make_server
from wsgi_app import app

# Create a server. The IP address is empty, the port number is 8000, and the processing function is app
httpd = make_server('', 8000, app)
print('Serving HTTP on port 8000...')
httpd.serve_forever()  # Start listening for HTTP requests

Run wsgi_server.py, enter in the browser http://127.0.0.1:8000/ You can visit the web page