2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
start_response
Method AnalysisIn this article, we will take a closer look at a WSGI server. start_response
Method. This method is responsible for processing the HTTP response status code and response header, and returns awrite
Function to send the response data. We will explain line by line how this method works and provide some background to help understand its functionality.
WSGI (Web Server Gateway Interface) is a standard interface for connecting a web server to a web application or framework. Through WSGI, the server and the application can communicate and process HTTP requests and responses.
When implementing a WSGI server,start_response
The method is a key part, which is called by the WSGI application to set the HTTP response status and response headers and return a function for writing the response data.
start_response
Method ImplementationThe following is a typical start_response
Method implementation:
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
reraise(*exc_info)
finally:
exc_info = None
elif headers_set:
raise AssertionError("Headers already set")
headers_set[:] = [status, response_headers]
return write
exc_info
parameterif exc_info:
try:
if headers_sent:
reraise(*exc_info)
finally:
exc_info = None
exc_info
The argument usually contains an exception tuple of the form(type, value, traceback)
, used for exception handling. If exc_info
Not forNone
, it means there is an exception that needs to be handled.try
In-block inspectionheaders_sent
Whether the response header has been sent. If the response header has been sent, callreraise(*exc_info)
Re-raise the exception.finally
The block ensures that after handling the exception,exc_info
Set asNone
to avoid duplicate processing.elif headers_set:
raise AssertionError("Headers already set")
headers_set
The list already contains a value (that is, the response header has been set), triggeringAssertionError
This check ensures thatstart_response
Can only be called once to set the response header.headers_set[:] = [status, response_headers]
status
andresponse_headers
Assign toheaders_set
The purpose of this is to preserveheaders_set
, but update its content.status
Is a string representing the HTTP response status code and message, for example"200 OK"
。response_headers
is a list of tuples, each tuple represents a key-value pair of a response header, for example[("Content-Type", "text/html"), ("Content-Length", "123")]
。write
functionreturn write
start_response
The method returns awrite
Function. This function is called by the WSGI application to send response data.The following is a complete example showing how to use start_response
Method to handle WSGI response:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.headers_set = []
self.headers_sent = []
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if self.headers_sent:
raise exc_info[1]
finally:
exc_info = None
elif self.headers_set:
raise AssertionError("Headers already set")
self.headers_set[:] = [status, response_headers]
return self.write
def write(data):
assert self.headers_set, "write() before start_response"
if not self.headers_sent:
status, response_headers = self.headers_sent[:] = self.headers_set
try:
code, msg = status.split(None, 1)
except ValueError:
code, msg = status, ""
code = int(code)
self.send_response(code, msg)
header_keys = set()
for key, value in response_headers:
self.send_header(key, value)
key = key.lower()
header_keys.add(key)
if not (
"content-length" in header_keys
or self.environ["REQUEST_METHOD"] == "HEAD"
or code < 200
or code in (204, 304)
):
self.close_connection = True
self.send_header("Connection", "close")
if "server" not in header_keys:
self.send_header("Server", self.version_string())
if "date" not in header_keys:
self.send_header("Date", self.date_time_string())
self.end_headers()
assert isinstance(data, bytes), "applications must write bytes"
self.wfile.write(data)
self.wfile.flush()
self.write = write
self.environ = self.make_environ()
try:
result = self.server.app(self.environ, start_response)
try:
for data in result:
write(data)
if not self.headers_sent:
write(b"")
finally:
if hasattr(result, "close"):
result.close()
except Exception as e:
self.send_error(500, str(e))
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
print("Server started at {}:{}".format(HOST, PORT))
server.serve_forever()
Through this tutorial, we have analyzed in detail a WSGI server start_response
method, explains how it handles the status code and response header of the HTTP response, and returns a function for writing the response data. Understanding these contents will help you better grasp the WSGI specification and implement a custom WSGI server. I hope this tutorial is helpful to you. For more detailed information and examples, please refer toOfficial Documentation。