How can I code an HTTP server where the responses are not sent synchronously?
I would like to enable:
- Request 1 arrives
- A synchronous service deals with request 1, but doesn't block the main thread
- During that, request 2 arrives, and is dealt with in its own unique way
- Request 1 returns to the client
- ... etc.
But it looks like as soon as the do_GET
or similar methods reach their end, the server is sending a response to the client. It is too late for me to send my own response later.
For example
import time
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from threading import Thread
class HTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
# I have some code that MUST run on the main thread during do_GET
run_something_on_main_thread()
# and some code that I really don't want to
responder_thread = Thread(target=self._respond_later, args=(self.wfile,))
def _respond_later(self, wfile):
u""" Query some blocking service, then respond to the request """
time.sleep(2)
wfile.write('HTTP/1.0 204 No Content\n\n')
wfile.close()
if __name__ == '__main__':
server_address = (u'0.0.0.0', 8000)
http_server = HTTPServer(server_address, HTTPRequestHandler)
print u'Starting httpd server on {}:{}'.format(*server_address)
http_server.serve_forever()
Querying this server always results in empty replies.
Ideally I would love a way to do this that allows me to use send_response
, end_headers
etc. — all the convenience methods from BaseHTTPRequestHandler
. Above, I pass the wfile
because I was wondering if it would be "frozen" in the new thread, I really don't expect passing self
to work (because I think all its methods would be pointed at the new request, not the request relevant at the time of the creation of the thread).
So how do I delay the response to the client without blocking the main thread?