How can I implement a simple web server using Python without using any libraries?

31,683

Solution 1

You can use socket programming for this purpose. The following snippet creates a tcp socket and listens on port 9000 for http requests:

from socket import *

def createServer():
    serversocket = socket(AF_INET, SOCK_STREAM)
    serversocket.bind(('localhost',9000))
    serversocket.listen(5)
    while(1):
        (clientsocket, address) = serversocket.accept()
        clientsocket.send("HTTP/1.1 200 OK\n"
         +"Content-Type: text/html\n"
         +"\n" # Important!
         +"<html><body>Hello World</body></html>\n")
        clientsocket.shutdown(SHUT_WR)
        clientsocket.close()

    serversocket.close()

createServer()

Start the server, $ python server.py. Open http://localhost:9000/ in your web-browser (which acts as client). Then in the browser window, you can see the text "Hello World" (http response).

EDIT** The previous code was only tested on chrome, and as you guys suggested about other browsers, the code was modified as:

  1. To make the response http-alike you can send in plain header with http version 1.1, status code 200 OK and content-type text/html.
  2. The client socket needs to be closed once response is submitted as it's a TCP socket.
  3. To properly close the client socket, shutdown() needs to be called socket.shutdown vs socket.close

Then the code was tested on chrome, firefox (http://localhost:9000/) and simple curl in terminal (curl http://localhost:9000).

Solution 2

You should look at the SimpleHttpServer (py3: http.server) module.

Depending on what you're trying to do, you can either just use it, or check out the module's source (py2, py3) for ideas.

If you want to get more low-level, SimpleHttpServer extends BaseHttpServer (source) to make it just work.

If you want to get even more low-level, take a look at SocketServer (source: py2, py3).

People will often run python like python -m SimpleHttpServer (or python3 -m http.server) if they just want to share a directory: it's a fully functional and... simple server.

Solution 3

I decided to make this work in Python 3 and make it work for Chrome to use as an example for an online course I am developing. Python 3 of course needs encode() and decode() in the right places. Chrome - really wants to send its GET request before it gets data. I also added some error checking so it cleans up its socket if you abort the server or it blows up:

def createServer():
    serversocket = socket(AF_INET, SOCK_STREAM)
    try :
        serversocket.bind(('localhost',9000))
        serversocket.listen(5)
        while(1):
            (clientsocket, address) = serversocket.accept()

            rd = clientsocket.recv(5000).decode()
            pieces = rd.split("\n")
            if ( len(pieces) > 0 ) : print(pieces[0])

            data = "HTTP/1.1 200 OK\r\n"
            data += "Content-Type: text/html; charset=utf-8\r\n"
            data += "\r\n"
            data += "<html><body>Hello World</body></html>\r\n\r\n"
            clientsocket.sendall(data.encode())
            clientsocket.shutdown(SHUT_WR)

    except KeyboardInterrupt :
        print("\nShutting down...\n");
    except Exception as exc :
        print("Error:\n");
        print(exc)

    serversocket.close()

print('Access http://localhost:9000')
createServer()

The server also prints out the incoming HTTP request. The code of course only sends text/html regardless of the request - even if the browser is asking for the favicon:

$ python3 server.py
Access http://localhost:9000
GET / HTTP/1.1
GET /favicon.ico HTTP/1.1
^C
Shutting down...

But it is a pretty good example that mostly shows why you want to use a framework like Flask or DJango instead of writing your own. Thanks for the initial code.

Share:
31,683
antonpug
Author by

antonpug

Updated on July 09, 2022

Comments

  • antonpug
    antonpug almost 2 years

    I need to implement a very simple web-server-like app in Python which would perform basic HTTP requests and responses and display very basic output on the web page. I am not too concerned about actually coding it in Python, but I am not sure where to start? How to set this up? One file? Multiple files? I guess I have no idea how to approach the fact that this is a "server" - so I am unfamiliar with how to approach dealing with HTTP requests/sockets/processing requests, etc. Any advice? Resources?

  • zinking
    zinking almost 12 years
    I would probably say you should check the HTTP documentation first. like RFC.
  • Asherah
    Asherah almost 12 years
    -1. Did you try this? This doesn't work at all; it's a socket server, but doesn't speak HTTP.
  • Asherah
    Asherah almost 12 years
    It doesn't actually speak HTTP, so almost every browser wouldn't work with this. It doesn't work in Chrome. It only works in Firefox if you press the Stop button. This is not a web server.
  • Xantium
    Xantium over 6 years
    I copied your script ran it and I'm getting an error saying a byte-like object is required not 'str' how do I fix this?
  • pritam
    pritam over 6 years
    @Simon Modified the code a bit. Also it was tested on python 2.7.6. If you are using python 3, where strings are Unicode; but when transmitting on the network, we need to send bytes strings instead. So try sendall() instead of send() with string output encoded as utf-8. #START output = "It works" clientsocket.sendall(output.encode("utf-8")) #END
  • Xantium
    Xantium over 6 years
    Super! That's just what I needed. I do use Python 3 so the ` sendall()` and .encode("utf-8") are absolutely essential and both these have fixed the error I was getting. all my server attempts up to this point have failed so I am very grateful. This is a well deserved up-vote however I do not like the clientsocket.send("HTTP/1.1 200 OK\n" +"Content-Type: text/html\n" +"\n" # Important! +"<html><body>Hello World</body></html>\n") shouldn't that be all on the same line? I had to modify that part. Thanks again. : )
  • Xantium
    Xantium about 6 years
    @Ashe It works normally in Chrome/Firefox/Edge for me. As I mentioned the byte-like error but apart from that this works great.
  • Asherah
    Asherah about 6 years
    @Simon the answer as originally posted (six years ago) did not have anything resembling HTTP; see stackoverflow.com/revisions/10592712/1.
  • chb
    chb over 5 years
    Welcome to Stack Overflow. This question is a near duplicate of the answer provided by @drchuck. The only thing that differentiates it from the latter is the lack of exception handling.