How to send an html string from a python http web server?

Mika picture Mika · Apr 4, 2013 · Viewed 7.8k times · Source

I found a python http web server from http://www.linuxjournal.com/content/tech-tip-really-simple-http-server-python

import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler


HandlerClass = SimpleHTTPRequestHandler
ServerClass  = BaseHTTPServer.HTTPServer
Protocol     = "HTTP/1.0"

if sys.argv[1:]:
    port = int(sys.argv[1])
else:
    port = 8000
server_address = ('127.0.0.1', 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 the directory has a file named index.html, that file will be served as the initial file. If there is no index.html, then the files in the directory will be listed.

How do I modify the script so that I send a custom html to the browser?

Answer

abarnert picture abarnert · Apr 4, 2013

As the name and documentation imply, SimpleHTTPServer is dead-simple, and intended to be used as sample code for building your own servers on top of the frameworks in the standard library.

So, if you want to do anything with it, you probably want to copy and modify the source, or just use it as inspiration.

And if you want to do anything serious, you probably want to use a framework made for writing real HTTP servers like tornado or twisted, or just use a stock HTTP server and delegate the dynamic pages to Python via, say, WSGI.

But if you really want to do this, you can. There's nothing stopping you from subclassing SimpleHTTPServer.SimpleHTTPRequestHandler and overriding its methods. For example:

class MyHandler(SimpleHTTPRequestHandler):
    def send_head(self):
        if self.translate_path(self.path).endswith('/foo'):
            body = gaping_security_hole(self.path)
            self.send_response(200)
            self.send_header("Content-type", "text/html; charset=utf-8")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            return StringIO(body)
        else:
            return super(MyHandler, self).send_head()

Obviously you can check whatever you want there instead of endswith('/foo'). For example, as you can see from the source, the default implementation checks os.path.isdir, and if it's true checks whether it endswith('/'), and whether the directory has anything named index.html or index.htm, before deciding what to do.