8

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?

4
  • Explain further your requirements (and why). Are you wanting to implement the full application-level stack, or can you use e.g. Apache? Explain more what you need And why. Finally, when you have the "websocket" tag, do you mean it or was that just an incorrect tag to use? Commented Apr 10, 2012 at 15:08
  • 2
    Without using any libraries? Surely socket is going to be required at a minimum? Commented Apr 10, 2012 at 15:09
  • check this documentation page, here I assume that "any libraries" are libraries that are not included in the python installation. Commented Apr 10, 2012 at 15:10
  • @Wooble: I think it is quite fair to assume "any libraries" to mean "any non-standard libraries". Commented Apr 10, 2012 at 15:12

4 Answers 4

10

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I would probably say you should check the HTTP documentation first. like RFC.
7

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).

7 Comments

-1. Did you try this? This doesn't work at all; it's a socket server, but doesn't speak HTTP.
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.
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?
@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
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. : )
|
2

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.

Comments

-1

There is a very simple solution mentioned above, but the solution above doesn't work. This solution is tested on chrome and it works. This is python 3 although it may work on python 2 since I never tested it.

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(bytes("HTTP/1.1 200 OK\n"
         +"Content-Type: text/html\n"
         +"\n" # Important!
         +"<html><body>Hello World</body></html>\n",'utf-8'))
        clientsocket.shutdown(SHUT_WR)
        clientsocket.close()

    serversocket.close()

createServer()

This is improved from the answer that was accepted, but I will post this so future users can use it easily.

1 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.