Http request from Chrome hangs python webserver
Asked Answered
T

3

7

I have a very basic python (2.7.12) web server (I've stripped it down as much as possible), code given below

import time
import ssl
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

class Management(SimpleHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        SimpleHTTPRequestHandler.end_headers(self)
        self.wfile.write(time.asctime() + "\n")

httpd = HTTPServer(('', 4443), Management)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True)
httpd.serve_forever()

All it does is return the time. It works fine when I access it via https, but when I access it via http using (the latest version of) chrome on a different computer, it frequently (but not always) causes the entire server to hang in the python code, specifically ssl.py in the do_handshake function in the line

self._sslobj.do_handshake()

I was expecting the connection to fail and get dropped because I am trying to access an https page via http, but I don't expect it to cause the entire process to hang. It only happens with chrome (not firefox or microsoft edge), and only when chrome is run on a different computer than the computer the server is running on.

I've also tried creating a python3 version of the code, and I see the same issue. I've tried running it in both Cygwin on windows 10, and the terminal in Ubuntu 14.04, and I get the same problem.

Tallbott answered 31/3, 2017 at 17:15 Comment(3)
I have this problem with Chrome when using https: together with an app manifest. Seems it hangs trying to access the logo file. Sadly, there are no answers here.Y
@Y In case anyone is interested, I ended up having to use a more heavy duty server (such as Apache or Nginx) as a reverse proxy.Tallbott
Anyone found a workaround yet?Prostyle
P
9

Just finished wrestling around with this for 2 days :(

Turns out user Ami Bar was exactly right in his/her answer. Google Chrome holds open the connection and causes the multiplexing in the selector library to register the connection as readable. Essentially it forces multiplexing to fail and thus you have to thread the server to handle requests separately.

You can thread your HTTP server by implementing socketserver.ThreadingMixIn. However if it's easier (this is what I did) you can simply upgrade python to 3.7+ and have your server inherit from http.server.ThreadingHTTPServer, which natively implements ThreadingMixIn

Hope this saves some poor soul two days...

Prostyle answered 28/8, 2018 at 23:16 Comment(0)
U
3

I don't have a solution but I think I have the reason.

The Chrome causes the httpd.serve_forever() to hang, because it keeps a request stream open.

The httpd.serve_forever() looks like this:

while not self.__shutdown_request:
    ready = selector.select(poll_interval)
    if ready:
        self._handle_request_noblock()

Chrome sends a request, gets a response, and then sends another request but keeps the stream open and doesn't send anything. The selector.select() is fulfilled and pass control to self._handle_request_noblock(), but since the stream is empty the request handler can't complete it and it gets blocked.

I guess Chrome does it for speeding up requests.

With Firefox, Internet Explorer, and wget it doesn't happen.

Utham answered 7/7, 2018 at 12:6 Comment(0)
P
1

I've got the same problem in python2.7. However, I've found sending correct headers, prevent Chrome to keeping a request stream open by sending the correct header.

For instance:

self.send_response(200)
self.send_header('Content-type','text/plain')
self.end_headers()  
Puzzle answered 4/3, 2020 at 13:58 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.