Mercurial > hg > simpypi
view simpypi/factory.py @ 25:511210365ce3
WIP getting paste StaticURLParser to serve directories
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Wed, 29 Feb 2012 10:29:11 -0800 |
parents | 13ed82d10144 |
children | fb03f34a982f |
line wrap: on
line source
#!/usr/bin/env python """ factories for simpypi """ import optparse import os import shutil import sys import tempfile from paste.httpexceptions import HTTPExceptionHandler from paste.urlparser import StaticURLParser from pkg_resources import resource_filename from wsgi import SimPyPI from wsgiref import simple_server class DirectoryServer(StaticURLParser): def __init__(self, directory): StaticURLParser.__init__(self, directory) def index(self, directory): """ generate a directory listing for a given directory """ parts = ['<html><head><title>Simple Index</title></head><body>'] listings = os.listdir(directory) listings = [(os.path.isdir(os.path.join(directory, entry)) and entry + '/' or entry, entry) for entry in listings] for link, entry in listings: parts.append('<a href="%s">%s</a><br/>' % (link, entry)) parts.append('</body></html>') return '\n'.join(parts) def __call__(self, environ, start_response): # normalize path # from paste.urlparser.StaticURLParser path_info = environ.get('PATH_INFO', '') if not path_info: return self.add_slash(environ, start_response) full = self.normpath(os.path.join(self.directory, path_info.strip('/'))) if not full.startswith(self.root_directory): # Out of bounds return self.not_found(environ, start_response) # return index listing if os.path.isdir(full): if not path_info.endswith('/'): return self.add_slash(environ, start_response) index = self.index(full) response_headers = [('Content-Type', 'text/html'), ('Content-Length', str(len(index)))] start_response('200 OK', response_headers) return [index] return StaticURLParser.__call__(self, environ, start_response) class PassthroughFileserver(object): """serve files if they exist""" def __init__(self, app, directory): self.app = app self.directory = directory self.fileserver = StaticURLParser(directory) def __call__(self, environ, start_response): path = self.path(environ['PATH_INFO'].strip('/')) if path and os.path.exists(os.path.join(self.directory, path)): return self.fileserver(environ, start_response) return self.app(environ, start_response) class NamespacedFileserver(DirectoryServer): def __init__(self, app, directory, namespace): DirectoryServer.__init__(self, directory) self.app = app self.namespace = namespace def __call__(self, environ, start_response): path = environ['PATH_INFO'] if path == self.namespace: return self.add_slash(environ, start_response) environ['PATH_INFO'] = '/' return DirectoryServer.__call__(self, environ, start_response) elif path.startswith(self.namespace + '/'): environ['PATH_INFO'] = path[len(self.namespace):] return DirectoryServer.__call__(self, environ, start_response) return self.app(environ, start_response) def factory(**app_conf): """create a webob view and wrap it in middleware""" directory = app_conf['directory'] app = SimPyPI(**app_conf) return NamespacedFileserver(app, directory, '/index') def main(args=sys.argv[:]): # parse command line options usage = '%prog [options]' parser = optparse.OptionParser(usage=usage) parser.add_option('-p', '--port', dest='port', type='int', default=8080, help="port to run the server on") parser.add_option('-d', '--directory', dest='directory', help='directory to serve') options, args = parser.parse_args(args) # create a temporary directory, if none specified tmpdir = None if not options.directory: tmpdir = tempfile.mkdtemp() options.directory = tmpdir # serve print "http://localhost:%d/" % options.port try: app = factory(directory=options.directory) server = simple_server.make_server(host='0.0.0.0', port=options.port, app=app) server.serve_forever() finally: if tmpdir: shutil.rmtree(tmpdir) if __name__ == '__main__': main()