Python Study Notes 20: Server advanced

Source: Internet
Author: User

Python Study Notes 20: Server advanced
In the previous article, we used only the socket interface without relying on the framework and CGI to complete a Python server that can process HTTP requests.
Based on this, any computer with an operating system (Linux recommended) and Python can be used as an HTTP server to set up your website.

Here we will constantly rewrite the program in the previous article and introduce more advanced Python packages to write more mature Python servers.


Once POST is supported, we first rewrite the HTTP server in the original article to allow the server to support richer HTTP requests.
Compared with the original program, table operations and operations corresponding to the "POST" method are added here. If you have read and written a Python server using socket, you will find that there is only a small amount of content added here.
Original program:

# A messy HTTP server based on TCP socket  import socket # AddressHOST = ''PORT = 8000 text_content = '''HTTP/1.x 200 OK  Content-Type: text/html WOW

Wow, Python Server

''' f = open('http://www.bkjia.com/uploads/allimg/141024/04215U210-0.jpg','rb')pic_content = '''HTTP/1.x 200 OK Content-Type: image/jpg '''pic_content = pic_content + f.read() # Configure sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.bind((HOST, PORT)) # Serve foreverwhile True: s.listen(3) conn, addr = s.accept() request = conn.recv(1024) # 1024 is the receiving buffer size method = request.split(' ')[0] src = request.split(' ')[1] print 'Connected by', addr print 'Request is:', request # if GET method request if method == 'GET': # if ULR is /http://www.bkjia.com/uploads/allimg/141024/04215U210-0.jpg if src == '/http://www.bkjia.com/uploads/allimg/141024/04215U210-0.jpg': content = pic_content else: content = text_content # send message conn.sendall(content) # if POST method request if method == 'POST': form = request.split('rn') idx = form.index('') # Find the empty line entry = form[idx:] # Main content of the request value = entry[-1].split('=')[-1] conn.sendall(text_content + 'n

' + value + '

') ###### # More operations, such as put the form into database # ... ###### # close connection conn.close()


Run the Python server above and use a browser as the client as shown in the previous article.
We can see the new table and the submit button. Enter aa in the table and submit the table. The Python server returns the above result.

2. Using SocketServer we first use the SocketServer package to simplify the server setup process.
In the process of using socket above, we first set the socket type, and then call bind (), listen (), accept (), the while loop is used to allow the server to continuously accept requests.
The above steps can be simplified by using the SocketServer package.

SocketServer:# use TCPServer import SocketServer HOST = ''PORT = 8000 text_content = '''HTTP/1.x 200 OK  Content-Type: text/html WOW

Wow, Python Server

''' f = open('http://www.bkjia.com/uploads/allimg/141024/04215U210-0.jpg','rb')pic_content = '''HTTP/1.x 200 OK Content-Type: image/jpg '''pic_content = pic_content + f.read() # This class defines response to each requestclass MyTCPHandler(SocketServer.BaseRequestHandler): def handle(self): # self.request is the TCP socket connected to the client request = self.request.recv(1024) print 'Connected by',self.client_address[0] print 'Request is', request method = request.split(' ')[0] src = request.split(' ')[1] if method == 'GET': if src == '/http://www.bkjia.com/uploads/allimg/141024/04215U210-0.jpg': content = pic_content else: content = text_content self.request.sendall(content) if method == 'POST': form = request.split('rn') idx = form.index('') # Find the empty line entry = form[idx:] # Main content of the request value = entry[-1].split('=')[-1] self.request.sendall(text_content + 'n

' + value + '

') ###### # More operations, such as put the form into database # ... ###### # Create the serverserver = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)# Start the server, and work foreverserver.serve_forever()

We have created a TCPServer object to create a TCP socket server and set the IP address and port at the same time.
Then the server_forever () method is used to keep the server working (just like the while loop in the original program ).
We pass a MyTCPHandler class to the TCPServer and use it to operate on the socket.
Note: MyTCPHandler inherits from BaseRequestHandler. We can modify the handler () method to personalize our operations.
In handler (), you can use self. request to reference the socket (as we perform recv () and sendall () operations on the socket in handler ),
You can also use self. address to reference the client address of the socket.
Iii. SimpleHTTPServer: using static files to respond to requests after the transformation of SocketServer, Our handler (), that is, the part that processes the requests, is still a mess.
This may be a problem for large servers.
Why? For an HTTP request, its starting line contains two important information: the request method and URL.
Previously, we used the if structure to differentiate different request methods and URLs and perform different operations for different situations:


Request method URL operation


GET/send text_content


GET/text.jpg send pic_content


POST/analyze the value contained in the request body (in fact we fill in the content of the table); send text_content and value

Depending on the Request Method and URL, a large HTTP server may have to handle thousands of different requests.
If you write different operations for each request in the program, it requires a lot of time and effort, and brings great difficulties to operation and maintenance.
We need a more standardized and easier way to process these requests.
In Python, we can use the SimpleHTTPServer package and CGIHTTPServer package to reduce the above burden.
SimpleHTTPServer can be used to process requests of the GET and HEAD methods.
It reads the URL address in the request, finds the corresponding static file in the current directory, and sends the file content to the client.
In response to our situation, the text_contentis placed in index.html, And the text.jpg file is read.
When an HTTP request arrives, its URL points to a file. SimpleHTTPServer reads the file, analyzes the file type, automatically generates a response, and replies to the client.
If urlindicates a folder, simplehttpserverwill read the index.html or index. hml file under the folder.
First, we will generate an index.html file under the current directory:

WOW

Wow, Python Server


Then, rewrite our Python server program.
In fact, we just replaced the TCPServer Handler: Use the unique SimpleHTTPRequestHandler class in the SimpleHTTPServer package, instead of the MyTCPHandler we previously defined.

SimpleHTTPServer:# Simple HTTPsERVER import SocketServerimport SimpleHTTPServer HOST = ''PORT = 8000 # Create the server, SimpleHTTPRequestHander is pre-defined handler in SimpleHTTPServer packageserver = SocketServer.TCPServer((HOST, PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)# Start the serverserver.serve_forever()


Note that the program here cannot be equivalent to the previous program because it cannot process POST requests. We will use CGI later to make up for this defect.
But the point is that our Python server program has become very simple.
We store the content in a static file and provide the content to the client based on the static file pointed to by the URL, so that the content is separated from the Python server.
In this way, we can only modify static files each time we update the content, instead of stopping the entire Python server.
We should also pay attention to the cost of using these improvements. For example, for the original program, the URL in the request is only instructive, and we can specify the corresponding operation as needed.
In the improvement of SimpleHTTPServer, response becomes: Read the file corresponding to the URL and present its content to the customer. This greatly limits our degree of freedom.
Even if we use CGI later, we increase the degree of freedom, but compared with the original program, we still add our own restrictions.
Sometimes, the convenience of a program conflicts with the degree of freedom of the program, and programmers need to choose between them.
For a small project, we can follow the established standards (for example, SimpleHTTPServer or a framework). Using these new standards can make development very convenient.
However, for a large project, we often need to get back to our own degrees of freedom and revise them into the standards required by the project.

4. CGIHTTPServer: The CGIHTTPRequestHandler class in the request CGIHTTPServer package is inherited from SimpleHTTPRequestHandler class, so it can be used to provide the static file service instead of the above example.
In addition, the CGIHTTPRequestHandler class can be used to run CGI scripts.

First, let's first look at what is CGI (Common Gateway Interface ). CGI is a set of interface standards between servers and application scripts. It aims to allow the server to run the script program and send the program output as response to the customer.
Generally, after receiving a request from a customer, the server that supports CGI runs the corresponding script file according to the URL in the request.
The server will input the HTTP request and socket information to the script file, collect the Script output, and assemble the information into a valid HTTP response.
With CGI, we can make full use of the server's programmability to dynamically generate response, instead of being limited to static files.
The CGI standard interface is used between the server and the CGI script. In this way, the server can work with CGI scripts written in different languages, such as using CGI scripts written by the Apache server and Perl, or using CGI scripts written by the Python server and shell.
So far, we have been using TCPServer to build servers. To use CGI, we need to use the HTTPServer class in the BaseHTTPServer package to build the server.
HTTPServer is a subclass of TCPServer, and its usage is the same as that of TCPServer. It only adds the server_name and server_port attributes.
Unfortunately, our CGIHTTPRequestHandler needs to call these two attributes...
The Python server is easy to modify.

CGIHTTPServer:# A messy HTTP server based on TCP socket  import BaseHTTPServerimport CGIHTTPServer HOST = ''PORT = 8000 # Create the server, CGIHTTPRequestHandler is pre-defined handlerserver = BaseHTTPServer.HTTPServer((HOST, PORT), CGIHTTPServer.CGIHTTPRequestHandler)# Start the serverserver.serve_forever()

By default, CGIHTTPRequestHandler uses cgi scripts as the files in the CGI-bin and ht-bin folders in the current directory. files stored elsewhere are considered static files.
For this reason, modify the role index.html and change the action that the form Element points to cgi-bin/post. py.


WOW

Wow, Python Server


Create a cgi-bin folder and put the following post. py file in cgi-bin, that is, our CGI script:


#!/usr/bin/env python # Written by Vameiimport cgiform = cgi.FieldStorage() # Output to stdout, CGIHttpServer will take this as response to the clientprint "Content-Type: text/html"     # HTML is followingprint                               # blank line, end of headersprint "

Hello world!

" # Start of contentprint "

" + repr(form['firstname']) + "

"


The first line must be available to tell the Python server the language in which the script is used (the CGI here is Python, and of course it can be another language, such as bash ).

The cgi package is used to extract the table information submitted in the request (we will not go deep into the cgi package for the time being ). The script is only responsible for outputting all the results to the standard output (using print ).
While CGIHTTPRequestHandler will collect these outputs and assemble them into response and send them to the client.
If a request is a POST method, its URL must point to a CGI script (that is, a file in cgi-bin or ht-bin ).
CGIHTTPRequestHandler inherits from SimpleHTTPRequestHandler, so it can also process requests from GET and HEAD methods.
If the URL points to the CGI script, the server sends the script running result to the client. When the URL points to the static file, the server sends the file content to the client.
We can allow CGI scripts to perform database operations, such as placing received data into the database and richer program operations.
CGI scripts provide the function of PHP in LAMP architecture (Our Python server is equivalent to Apache in LAMP ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.