Python SimpleHTTPServer Recipe: Serve specific directory

  • We need to be able to pass the path to the root of the directory tree we wish to serve.
  • We can only pass arguments to the ServerClass and not HandlerClass. Note however that HandlerClass is passed as an argument to ServerClass so we should be able to propagate the argument to HandlerClass.
  • The translate_path method of SimpleHTTPRequestHandler takes the /-separated path specified in the URL and prepends os.getcwd() to it. We just have to instead prepend the argument we propagated to SimpleHTTPRequestHandler.
  • Lastly we modify the test function to take multiple optional arguments (port and base path) using the excellent module argparse.
#! /usr/bin/env python

import posixpath
import argparse
import urllib
import os

from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer

class RootedHTTPServer(HTTPServer):

    def __init__(self, base_path, *args, **kwargs):
        HTTPServer.__init__(self, *args, **kwargs)
        self.RequestHandlerClass.base_path = base_path

class RootedHTTPRequestHandler(SimpleHTTPRequestHandler):

    def translate_path(self, path):
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        path = self.base_path
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir):
            path = os.path.join(path, word)
        return path

def test(HandlerClass=RootedHTTPRequestHandler, ServerClass=RootedHTTPServer):

    parser = argparse.ArgumentParser()
    parser.add_argument('--port', '-p', default=8000, type=int)
    parser.add_argument('--dir', '-d', default=os.getcwd(), type=str)
    args = parser.parse_args()

    server_address = ('', args.port)

    httpd = ServerClass(args.dir, server_address, HandlerClass)

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

if __name__ == '__main__':
$ python ~/Documents
$ python ~/Documents 5000


Comments powered by Disqus