Python has a lot of functionality in its libraries and is designed to enable network programming so it is perhaps not surprising to find a web server . Just six lines of code are enough to get a completely useless and standard breaking server running which we can then expand.
# Python 2 only def mywebserver(environ, start_response): "No matter what is requested, return the path" start_response('200 OK',[('Content-type', 'text/html')]) return ['You looked for %s' % (environ.get('PATH_INFO', ''))] from wsgiref.simple_server import make_server myserver = make_server('localhost',8081,mywebserver) myserver.serve_forever()
simple_server really does live up to its name. It will handle the network sockets and convert the HTTP request into a dictionary object but all the logic to power the web server you have to write yourself. In order to get up and running my web server just returns the path of the object requested.
Even something as simple as this is hiding a problem. I’m hoping you all saw the Python 2 only comment; if you think of one of the major changes between 2 and 3 you may guess (or know) the problem. Unless informed otherwise, and you should really include the character set encoding, web clients nowadays will assume the information returned in UTF-8 encoded. Python 2 defaults to 8bit ASCII strings which is how we got away with the above but in Python 3 the strings are in Unicode.
Still we shouldn’t be relying on luck to keep the output correct so we should encode the output correctly using the appropriately named encode method. While we are doing this we should also include the encoding in the Content-type header line. Our fixed mywebserver function now works on both.
def mywebserver(environ, start_response): "No matter what is requested, return the path" start_response('200 OK',[('Content-type', 'text/plain; charset=utf-8')]) response = 'You looked for %s' % (environ.get('PATH_INFO', '')) return [ response.encode('utf-8') ]
Now lets make our web server do something. One thing we might like to call functions from out webserver. This would give us functionality similar to CGI but without the overhead. As this is only part one, my first webserver program uses a dictionary to map the functions I want to expose to a path.
Each function is passed the environment variables dictionary so it can work out anything it needs. You can have the same function available from different paths which is how I’ve handled / and /index.html. Best of all it is straight forward to add additional functions so start experimenting.