Minimal HTTP File Server in Python

23 Nov 2008

At the bottom is a deminimus HTTP file server in Python. Why? perhaps you are on a virtual or remote machine want to look a file in your native web browser, or do a quick file transfer without setting up 1,000 ssh tunnels, and you don't want to install Apache.

  • Requests are limited to within the 'root' directory for security.
  • Mime types correctly handled
  • Directory listings
  • No daemonization, once you log out, it's gone.
#!/usr/bin/env python
# http://blog.modp.com/2008/11/minimal-http-file-server-in-python.html
# v1.0 23-Nov-2008 Nick Galbreath
# PUBLIC DOMAIN, but it would be nice if you gave me credit ;-)                      
import os, os.path, mimetypes, wsgiref.simple_server

port = 8003  # anything
root = os.path.expanduser('/home/YOU/YOURDIR')

def makelink(dir, file):
    link = (os.path.join(dir,file))[len(root):]
    return '<a href="%s">%s</a><br>\n' % (link, file)
def run(environ, start_response):
    cmd = environ['PATH_INFO']
    filename = os.path.abspath(os.path.join(root,cmd[cmd.find('/')+1:]))
    data = ''
    mtype = 'text/plain'
    if not filename.startswith(root):
        status = '403 Forbidden'
        data = 'Request outside of root directory\n'
    else:
        status = '200 OK'
        try:
            if os.path.isdir(filename):
                mtype = 'text/html'
                files = sorted(os.listdir(filename))
                links = [makelink(filename,f) for f in files]
                data = '<html><head><title>' + filename + \
                    '</title></head><body>\n' + makelink(filename, '..')+ \
                    ''.join(links) + '</body></html>\n'
            else:
                f = open(filename); data = f.read(); f.close()
                m = mimetypes.guess_type(filename)
                if m[0] is not None: mtype = m[0]
        except IOError,e:
            data = str(e) + '\n'
            status = "404 Not Found"
    start_response(status, [('Content-Type', mtype)])
    return [ data ]
if __name__ == '__main__':
    httpd = wsgiref.simple_server.make_server('', port, run)
    sa = httpd.socket.getsockname()
    httpd.serve_forever()

Comment 2009-10-26 by None

Well, this one-liner has served me well for this purpose:

python -mSimpleHTTPServer