Is it possible to run python SimpleHTTPServer on localhost only?
Asked Answered
T

3

113

I have a vpn connection and when I'm running python -m SimpleHTTPServer, it serves on 0.0.0.0:8000, which means it can be accessed via localhost and via my real ip. I don't want robots to scan me and interested that the server will be accessed only via localhost.

Is it possible?

python -m SimpleHTTPServer 127.0.0.1:8000  # doesn't work.

Any other simple http server which can be executed instantly using the command line is also welcome.

Tryma answered 4/9, 2012 at 17:50 Comment(3)
You could simply block outside connections on that port from your firewall/router.Cahra
While a good question for python2, it may be noted here that in python3 the replacement http.server allows binding right away, e.g python3 -m http.server --bind 127.0.0.1 8000 would sufficeAdaptive
Sidenote: SimpleHTTPServer is single-threading and blocking, meaning you won't be able to do another request until the previous request is over. And it has no range support e.g. for streaming/seeking a media file from a specific position. A better alternative is twisted (pip install twisted) which you can run with twistd -n web --path /. It can also do anonymous FTP with twistd -n ftp -p 2121 -r /. More http server one-liners: gist.github.com/willurd/5720255.Helgeson
M
58

If you read the source you will see that only the port can be overridden on the command line. If you want to change the host it is served on, you will need to implement the test() method of the SimpleHTTPServer and BaseHTTPServer yourself. But that should be really easy.

Here is how you can do it, pretty easily:

import sys
from SimpleHTTPServer import SimpleHTTPRequestHandler
import BaseHTTPServer


def test(HandlerClass=SimpleHTTPRequestHandler,
         ServerClass=BaseHTTPServer.HTTPServer):

    protocol = "HTTP/1.0"
    host = ''
    port = 8000
    if len(sys.argv) > 1:
        arg = sys.argv[1]
        if ':' in arg:
            host, port = arg.split(':')
            port = int(port)
        else:
            try:
                port = int(sys.argv[1])
            except:
                host = sys.argv[1]

    server_address = (host, port)

    HandlerClass.protocol_version = protocol
    httpd = ServerClass(server_address, HandlerClass)

    sa = httpd.socket.getsockname()
    print "Serving HTTP on", sa[0], "port", sa[1], "..."
    httpd.serve_forever()


if __name__ == "__main__":
    test()

And to use it:

> python server.py 127.0.0.1     
Serving HTTP on 127.0.0.1 port 8000 ...

> python server.py 127.0.0.1:9000
Serving HTTP on 127.0.0.1 port 9000 ...

> python server.py 8080          
Serving HTTP on 0.0.0.0 port 8080 ...
Mainsheet answered 4/9, 2012 at 17:56 Comment(0)
R
146

In Python versions 3.4 and higher, the http.server module accepts a bind parameter.

According to the docs:

python -m http.server 8000

By default, server binds itself to all interfaces. The option -b/--bind specifies a specific address to which it should bind. For example, the following command causes the server to bind to localhost only:

python -m http.server 8000 --bind 127.0.0.1

New in version 3.4: --bind argument was introduced.

Rash answered 27/11, 2016 at 5:50 Comment(0)
T
79

As @sberry explained, simply doing it by using the nice python -m ... method won't be possible, because the IP address is hardcoded in the implementation of the BaseHttpServer.test function.

A way of doing it from the command line without writing code to a file first would be

python -c 'import BaseHTTPServer as bhs, SimpleHTTPServer as shs; bhs.HTTPServer(("127.0.0.1", 8888), shs.SimpleHTTPRequestHandler).serve_forever()'

If that still counts as a one liner depends on your terminal width ;-) It's certainly not very easy to remember.

Trotskyism answered 4/9, 2012 at 18:18 Comment(5)
Adding this to .bash_profile. Yum. Now I can just type H. Thanks! -- gist.github.com/cmawhorter/f2a09bcf63c68b0cff10Orpah
To have this work as a simple http server on windows 10 using Python 3.5.1 I had to change it as follows: python -c "import http.server as hs; hs.HTTPServer(('127.0.0.1', 8888), hs.SimpleHTTPRequestHandler).serve_forever()" Note the change in quotation and the fact that Base and Simple HTTP Server are now in http.server.Burn
+1 on using profile alias, I called mine 'servelocal' -- there is a bit of a dance changing and escaping quotation marks to make bash syntax happy, but result is nice.Empurple
Very helpful... :)Dottydoty
works perfecly! just one question - how can I point path to other location? I would like to create one script that will fire up two servers...Sulfur
M
58

If you read the source you will see that only the port can be overridden on the command line. If you want to change the host it is served on, you will need to implement the test() method of the SimpleHTTPServer and BaseHTTPServer yourself. But that should be really easy.

Here is how you can do it, pretty easily:

import sys
from SimpleHTTPServer import SimpleHTTPRequestHandler
import BaseHTTPServer


def test(HandlerClass=SimpleHTTPRequestHandler,
         ServerClass=BaseHTTPServer.HTTPServer):

    protocol = "HTTP/1.0"
    host = ''
    port = 8000
    if len(sys.argv) > 1:
        arg = sys.argv[1]
        if ':' in arg:
            host, port = arg.split(':')
            port = int(port)
        else:
            try:
                port = int(sys.argv[1])
            except:
                host = sys.argv[1]

    server_address = (host, port)

    HandlerClass.protocol_version = protocol
    httpd = ServerClass(server_address, HandlerClass)

    sa = httpd.socket.getsockname()
    print "Serving HTTP on", sa[0], "port", sa[1], "..."
    httpd.serve_forever()


if __name__ == "__main__":
    test()

And to use it:

> python server.py 127.0.0.1     
Serving HTTP on 127.0.0.1 port 8000 ...

> python server.py 127.0.0.1:9000
Serving HTTP on 127.0.0.1 port 9000 ...

> python server.py 8080          
Serving HTTP on 0.0.0.0 port 8080 ...
Mainsheet answered 4/9, 2012 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.