#!/usr/bin/env python # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is mozilla.org code. # # The Initial Developer of the Original Code is # the Mozilla Foundation. # Portions created by the Initial Developer are Copyright (C) 2011 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Joel Maher # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** import BaseHTTPServer import SimpleHTTPServer import threading import sys import os import urllib import re from SocketServer import ThreadingMixIn class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): allow_reuse_address = True class MozRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): docroot = os.getcwd() def parse_request(self): retval = SimpleHTTPServer.SimpleHTTPRequestHandler.parse_request(self) if '?' in self.path: # ignore query string, otherwise SimpleHTTPRequestHandler # will treat it as PATH_INFO for `translate_path` self.path = self.path.split('?', 1)[0] return retval def translate_path(self, path): path = path.strip('/').split() if path == ['']: path = [] path.insert(0, self.docroot) return os.path.join(*path) # I found on my local network that calls to this were timing out # I believe all of these calls are from log_message def address_string(self): return "a.b.c.d" # This produces a LOT of noise def log_message(self, format, *args): pass class MozHttpd(object): def __init__(self, host="127.0.0.1", port=8888, docroot=os.getcwd()): self.host = host self.port = int(port) self.docroot = docroot self.httpd = None def start(self, block=False): """ start the server. If block is True, the call will not return. If block is False, the server will be started on a separate thread that can be terminated by a call to .stop() """ class MozRequestHandlerInstance(MozRequestHandler): docroot = self.docroot self.httpd = EasyServer((self.host, self.port), MozRequestHandlerInstance) if block: self.httpd.serve_forever() else: self.server = threading.Thread(target=self.httpd.serve_forever) self.server.setDaemon(True) # don't hang on exit self.server.start() def testServer(self): fileList = os.listdir(self.docroot) filehandle = urllib.urlopen('http://%s:%s/?foo=bar&fleem=&foo=fleem' % (self.host, self.port)) data = filehandle.readlines() filehandle.close() retval = True for line in data: found = False # '@' denotes a symlink and we need to ignore it. webline = re.sub('\<[a-zA-Z0-9\-\_\.\=\"\'\/\\\%\!\@\#\$\^\&\*\(\) ]*\>', '', line.strip('\n')).strip('/').strip().strip('@') if webline != "": if webline == "Directory listing for": found = True else: for fileName in fileList: if fileName == webline: found = True if not found: retval = False print >> sys.stderr, "NOT FOUND: " + webline.strip() return retval def stop(self): if self.httpd: self.httpd.shutdown() self.httpd = None __del__ = stop def main(args=sys.argv[1:]): # parse command line options from optparse import OptionParser parser = OptionParser() parser.add_option('-p', '--port', dest='port', type="int", default=8888, help="port to run the server on [DEFAULT: %default]") parser.add_option('-H', '--host', dest='host', default='127.0.0.1', help="host [DEFAULT: %default]") parser.add_option('-d', '--docroot', dest='docroot', default=os.getcwd(), help="directory to serve files from [DEFAULT: %default]") parser.add_option('--test', dest='test', action='store_true', default=False, help='run the tests and exit') options, args = parser.parse_args(args) if args: parser.print_help() parser.exit() # create the server kwargs = options.__dict__.copy() test = kwargs.pop('test') server = MozHttpd(**kwargs) if test: server.start() server.testServer() else: server.start(block=True) if __name__ == '__main__': main()