JDM
JDM

Reputation: 1804

Can you instantiate a Python HTTP server without it listening?

My environment is Python 3.7 on Windows 10. I'm working on (very) lightweight HTTP server app, whose main purpose is to test mobile-computer applications that perform HTTP POST requests. I've found the Python docs and several other sources that explain the basics of using the http.server module, so it's no sweat to get a functioning server.

There's one detail though I'm having difficulty with. I've found by experiment that an HTTPServer instance doesn't wait until you call the serve_forever() method to start listening. Instead, it begins listening on the specified port as soon as you instantiate it. If you try (e.g.) this small script:

import time
from http.server import BaseHTTPRequestHandler,HTTPServer

class MyHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        pass

h1 = HTTPServer(('', 10123), MyHandler)
print('Server instantiated')

while (True):
    time.sleep(0.1)
    pass

It does nothing but instantiate the server, but a check on the local machine shows that the script results in port 10123 being bound and listened on:

C:\Dev_Python\HTTPServer>netstat -anp tcp

Active Connections

Proto  Local Address          Foreign Address        State
TCP    0.0.0.0:10123          0.0.0.0:0              LISTENING

I've found on further searching of the docs that I can 'undo' this listen by accessing the class's socket object:

h1.socket.close()

...but I'd rather the server just didn't start listening in the first place, until I want it to actually start doing so.

So the question is: Is there a way to override this behavior, and instantiate the server while delaying it from listening on the port?

Upvotes: 0

Views: 190

Answers (1)

Maksym Polshcha
Maksym Polshcha

Reputation: 18358

There is bind_and_activate keyword argument, with the value of True by default, which allows you to control newly created socket binding and activation.

Try:

...
h1 = HTTPServer(('', 10123), MyHandler, bind_and_activate=False)
...

you can bind and activate it later:

...
try:
    h1.server_bind()
    h1.server_activate()
except:
    h1.server_close()
    raise
...

Upvotes: 2

Related Questions