简体   繁体   中英

SimpleHTTPRequestHandler close connection before returning from do_POST method

I'm writing a simple webserver in python. here follows a simplified version of my code:

class StreamerHandler(SimpleHTTPRequestHandler):
    def do_POST(self):
        try:
            length = int(self.headers.getheader('content-length'))
            data = self.rfile.read(length)
            self.send_response(200, "OK")
            #process_data(data, self.client_address)
        except Exception as inst:
            logging.error(type(self).__name__ + "/"  + type(inst).__name__ + " (" + inst.__str__() + ")")

class Streamer(TCPServer):
    def __init__(self, overlay):
        self.allow_reuse_address = True
        TCPServer.__init__(self, ("", port), StreamerHandler)

What I would like to do is to send the response close the TCP connection and then run the process_data method which may take a long time to complete.

Is there way to achieve this? The only solution I can think is to use a dedicated thread to handle the processing.

I tried it out, you actually need both commands (in order) to close it: self.finish() self.connection.close()

So, SimpleHTTPRequestHandler inherits from BaseHTTPServer.BaseHTTPRequestHandler , which in turn inherits from SocketServer.StreamRequestHandler .

In SocketServer.StreamRequestHandler , the rfile and wfile pseudo files get created in the setup() method from the socket object (known as self.connection ):

def setup(self):
    self.connection = self.request
    if self.timeout is not None:
        self.connection.settimeout(self.timeout)
    if self.disable_nagle_algorithm:
        self.connection.setsockopt(socket.IPPROTO_TCP,
                                   socket.TCP_NODELAY, True)
    self.rfile = self.connection.makefile('rb', self.rbufsize)
    self.wfile = self.connection.makefile('wb', self.wbufsize)

The socket self.connection is still available to you, so you could call self.connection.close() to close it. However, the wfile pseudo-file might have buffered data inside it which could be lost, so you could/should instead call self.finish() , also defined in SocketServer.StreamRequestHandler :

def finish(self):
    if not self.wfile.closed:
        self.wfile.flush()
    self.wfile.close()
    self.rfile.close()

So, I think the following should work (untested):

class StreamerHandler(SimpleHTTPRequestHandler):
    def do_POST(self):
        try:
            length = int(self.headers.getheader('content-length'))
            data = self.rfile.read(length)
            self.send_response(200, "OK")
            self.finish()
            process_data(data, self.client_address)
        except Exception as exc:
            logging.error(
                "{0}/{1}({2})".format(
                    type(self).__name__, type(exc).__name__, str(exc)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM