Bug 1230862 - Remove mozhttpd. r=wlach

This commit is contained in:
Julien Pagès 2016-02-09 03:26:43 +01:00
parent 13dafc7856
commit df45cd49c3
37 changed files with 49 additions and 988 deletions

View File

@ -80,7 +80,6 @@ SEARCH_PATHS = [
'testing/mozbase/mozdebug',
'testing/mozbase/mozdevice',
'testing/mozbase/mozfile',
'testing/mozbase/mozhttpd',
'testing/mozbase/mozinfo',
'testing/mozbase/mozinstall',
'testing/mozbase/mozleak',

View File

@ -7,7 +7,7 @@
from mozprofile import FirefoxProfile, Profile, Preferences
from mozprofile.permissions import ServerLocations
from mozrunner import FirefoxRunner, CLI
from mozhttpd import MozHttpd
from wptserve.server import WebTestHttpd
import json
import socket
import threading
@ -26,8 +26,8 @@ if __name__ == '__main__':
debug_args, interactive = cli.debugger_arguments()
build = MozbuildObject.from_environment()
httpd = MozHttpd(port=PORT,
docroot=os.path.join(build.topsrcdir, "build", "pgo"))
httpd = WebTestHttpd(port=PORT,
doc_root=os.path.join(build.topsrcdir, "build", "pgo"))
httpd.start(block=False)
locations = ServerLocations()

View File

@ -47,7 +47,7 @@ class MachCommands(MachCommandBase):
from mozbuild.base import MozbuildObject
from mozfile import TemporaryDirectory
from mozhttpd import MozHttpd
from wptserve.server import WebTestHttpd
from mozprofile import FirefoxProfile, Preferences
from mozprofile.permissions import ServerLocations
from mozrunner import FirefoxRunner
@ -58,7 +58,7 @@ class MachCommands(MachCommandBase):
# XXX: currently we just use the PGO inputs for Valgrind runs. This may
# change in the future.
httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
httpd = WebTestHttpd(doc_root=os.path.join(build_dir, 'pgo'))
httpd.start(block=False)
with TemporaryDirectory() as profilePath:

View File

@ -3,7 +3,6 @@ manifestparser==1.1
mozcrash==0.16
mozdevice==0.48
mozfile==1.2
mozhttpd==0.7
mozinfo==0.9
# optional - mozharness install step
mozInstall==1.12

View File

@ -3,7 +3,6 @@
../mozbase/mozdebug
../mozbase/mozdevice
../mozbase/mozfile
../mozbase/mozhttpd
../mozbase/mozinfo
../mozbase/mozinstall
../mozbase/mozleak

View File

@ -44,7 +44,6 @@ want to do then dive in!
manifestparser
gettinginfo
setuprunning
mozhttpd
loggingreporting
devicemanagement

View File

@ -1,22 +0,0 @@
Serving up content to be consumed by the browser
================================================
.. warning:: The mozhttpd module is considered obsolete. For new code,
please use wptserve_ which can do everything mozhttpd does
and more.
.. _wptserve: https://pypi.python.org/pypi/wptserve
:mod:`mozhttpd` --- Simple webserver
------------------------------------
.. automodule:: mozhttpd
:members:
Interface
`````````
.. autoclass:: MozHttpd
:members:

View File

@ -14,7 +14,6 @@ python_modules = [
'mozdebug',
'mozdevice',
'mozfile',
'mozhttpd',
'mozinfo',
'mozinstall',
'mozleak',

View File

@ -6,7 +6,8 @@
import os, unittest, subprocess, tempfile, shutil, urlparse, zipfile, StringIO
import mozcrash
import mozhttpd
from wptserve.server import WebTestHttpd
from wptserve import handlers
import mozlog.unstructured as mozlog
# Make logs go away
@ -165,11 +166,12 @@ class TestCrash(unittest.TestCase):
z.writestr("symbols.txt", "abc/xyz")
z.close()
return data.getvalue()
def get_symbols(req):
headers = {}
return (200, headers, make_zipfile())
httpd = mozhttpd.MozHttpd(port=0,
urlhandlers=[{'method':'GET', 'path':'/symbols', 'function':get_symbols}])
@handlers.handler
def get_symbols(request, response):
return (200, [], [make_zipfile()])
httpd = WebTestHttpd(port=0,
routes=[("GET", "/symbols", get_symbols)])
httpd.start()
symbol_url = urlparse.urlunsplit(('http', '%s:%d' % httpd.httpd.server_address,
'/symbols','',''))

View File

@ -21,5 +21,5 @@ setup(name=PACKAGE_NAME,
include_package_data=True,
zip_safe=False,
install_requires=[],
tests_require=['mozhttpd']
tests_require=['wptserve']
)

View File

@ -4,7 +4,7 @@
tests for mozfile.load
"""
import mozhttpd
from wptserve import server, handlers
import os
import tempfile
import unittest
@ -15,20 +15,20 @@ class TestLoad(unittest.TestCase):
"""test the load function"""
def test_http(self):
"""test with mozhttpd and a http:// URL"""
"""test with wptserve and a http:// URL"""
def example(request):
@handlers.handler
def example(request, reponse):
"""example request handler"""
body = 'example'
return (200, {'Content-type': 'text/plain',
'Content-length': len(body)
}, body)
return (200, [{'Content-type': 'text/plain',
'Content-length': len(body)
}], [body])
host = '127.0.0.1'
httpd = mozhttpd.MozHttpd(host=host,
urlhandlers=[{'method': 'GET',
'path': '.*',
'function': example}])
httpd = server.WebTestHttpd(
host=host,
routes=[('GET', "*", example)])
try:
httpd.start(block=False)
content = load(httpd.get_url()).read()

View File

@ -1,46 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
"""
Mozhttpd is a simple http webserver written in python, designed expressly
for use in automated testing scenarios. It is designed to both serve static
content and provide simple web services.
The server is based on python standard library modules such as
SimpleHttpServer, urlparse, etc. The ThreadingMixIn is used to
serve each request on a discrete thread.
Some existing uses of mozhttpd include Peptest_, Eideticker_, and Talos_.
.. _Peptest: https://github.com/mozilla/peptest/
.. _Eideticker: https://github.com/mozilla/eideticker/
.. _Talos: http://hg.mozilla.org/build/
The following simple example creates a basic HTTP server which serves
content from the current directory, defines a single API endpoint
`/api/resource/<resourceid>` and then serves requests indefinitely:
::
import mozhttpd
@mozhttpd.handlers.json_response
def resource_get(request, objid):
return (200, { 'id': objid,
'query': request.query })
httpd = mozhttpd.MozHttpd(port=8080, docroot='.',
urlhandlers = [ { 'method': 'GET',
'path': '/api/resources/([^/]+)/?',
'function': resource_get } ])
print "Serving '%s' at %s:%s" % (httpd.docroot, httpd.host, httpd.port)
httpd.start(block=True)
"""
from mozhttpd import MozHttpd, Request, RequestHandler, main
from handlers import json_response

View File

@ -1,15 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import json
def json_response(func):
""" Translates results of 'func' into a JSON response. """
def wrap(*a, **kw):
(code, data) = func(*a, **kw)
json_data = json.dumps(data)
return (code, { 'Content-type': 'application/json',
'Content-Length': len(json_data) }, json_data)
return wrap

View File

@ -1,329 +0,0 @@
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import BaseHTTPServer
import SimpleHTTPServer
import errno
import logging
import threading
import posixpath
import socket
import sys
import os
import urllib
import urlparse
import re
import moznetwork
import time
from SocketServer import ThreadingMixIn
class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
allow_reuse_address = True
acceptable_errors = (errno.EPIPE, errno.ECONNABORTED)
def handle_error(self, request, client_address):
error = sys.exc_value
if ((isinstance(error, socket.error) and
isinstance(error.args, tuple) and
error.args[0] in self.acceptable_errors)
or
(isinstance(error, IOError) and
error.errno in self.acceptable_errors)):
pass # remote hang up before the result is sent
else:
logging.error(error)
class Request(object):
"""Details of a request."""
# attributes from urlsplit that this class also sets
uri_attrs = ('scheme', 'netloc', 'path', 'query', 'fragment')
def __init__(self, uri, headers, rfile=None):
self.uri = uri
self.headers = headers
parsed = urlparse.urlsplit(uri)
for i, attr in enumerate(self.uri_attrs):
setattr(self, attr, parsed[i])
try:
body_len = int(self.headers.get('Content-length', 0))
except ValueError:
body_len = 0
if body_len and rfile:
self.body = rfile.read(body_len)
else:
self.body = None
class RequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
docroot = os.getcwd() # current working directory at time of import
proxy_host_dirs = False
request_log = []
log_requests = False
request = None
def __init__(self, *args, **kwargs):
SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
self.extensions_map['.svg'] = 'image/svg+xml'
def _try_handler(self, method):
if self.log_requests:
self.request_log.append({ 'method': method,
'path': self.request.path,
'time': time.time() })
handlers = [handler for handler in self.urlhandlers
if handler['method'] == method]
for handler in handlers:
m = re.match(handler['path'], self.request.path)
if m:
(response_code, headerdict, data) = \
handler['function'](self.request, *m.groups())
self.send_response(response_code)
for (keyword, value) in headerdict.iteritems():
self.send_header(keyword, value)
self.end_headers()
self.wfile.write(data)
return True
return False
def _find_path(self):
"""Find the on-disk path to serve this request from,
using self.path_mappings and self.docroot.
Return (url_path, disk_path)."""
path_components = filter(None, self.request.path.split('/'))
for prefix, disk_path in self.path_mappings.iteritems():
prefix_components = filter(None, prefix.split('/'))
if len(path_components) < len(prefix_components):
continue
if path_components[:len(prefix_components)] == prefix_components:
return ('/'.join(path_components[len(prefix_components):]),
disk_path)
if self.docroot:
return self.request.path, self.docroot
return None
def parse_request(self):
retval = SimpleHTTPServer.SimpleHTTPRequestHandler.parse_request(self)
self.request = Request(self.path, self.headers, self.rfile)
return retval
def do_GET(self):
if not self._try_handler('GET'):
res = self._find_path()
if res:
self.path, self.disk_root = res
# don't include query string and fragment, and prepend
# host directory if required.
if self.request.netloc and self.proxy_host_dirs:
self.path = '/' + self.request.netloc + \
self.path
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
else:
self.send_response(404)
self.end_headers()
self.wfile.write('')
def do_POST(self):
# if we don't have a match, we always fall through to 404 (this may
# not be "technically" correct if we have a local file at the same
# path as the resource but... meh)
if not self._try_handler('POST'):
self.send_response(404)
self.end_headers()
self.wfile.write('')
def do_DEL(self):
# if we don't have a match, we always fall through to 404 (this may
# not be "technically" correct if we have a local file at the same
# path as the resource but... meh)
if not self._try_handler('DEL'):
self.send_response(404)
self.end_headers()
self.wfile.write('')
def translate_path(self, path):
# this is taken from SimpleHTTPRequestHandler.translate_path(),
# except we serve from self.docroot instead of os.getcwd(), and
# parse_request()/do_GET() have already stripped the query string and
# fragment and mangled the path for proxying, if required.
path = posixpath.normpath(urllib.unquote(self.path))
words = path.split('/')
words = filter(None, words)
path = self.disk_root
for word in words:
drive, word = os.path.splitdrive(word)
head, word = os.path.split(word)
if word in (os.curdir, os.pardir): continue
path = os.path.join(path, word)
return 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):
"""
:param host: Host from which to serve (default 127.0.0.1)
:param port: Port from which to serve (default 8888)
:param docroot: Server root (default os.getcwd())
:param urlhandlers: Handlers to specify behavior against method and path match (default None)
:param path_mappings: A dict mapping URL prefixes to additional on-disk paths.
:param proxy_host_dirs: Toggle proxy behavior (default False)
:param log_requests: Toggle logging behavior (default False)
Very basic HTTP server class. Takes a docroot (path on the filesystem)
and a set of urlhandler dictionaries of the form:
::
{
'method': HTTP method (string): GET, POST, or DEL,
'path': PATH_INFO (regular expression string),
'function': function of form fn(arg1, arg2, arg3, ..., request)
}
and serves HTTP. For each request, MozHttpd will either return a file
off the docroot, or dispatch to a handler function (if both path and
method match).
Note that one of docroot or urlhandlers may be None (in which case no
local files or handlers, respectively, will be used). If both docroot or
urlhandlers are None then MozHttpd will default to serving just the local
directory.
MozHttpd also handles proxy requests (i.e. with a full URI on the request
line). By default files are served from docroot according to the request
URI's path component, but if proxy_host_dirs is True, files are served
from <self.docroot>/<host>/.
For example, the request "GET http://foo.bar/dir/file.html" would
(assuming no handlers match) serve <docroot>/dir/file.html if
proxy_host_dirs is False, or <docroot>/foo.bar/dir/file.html if it is
True.
"""
def __init__(self,
host="127.0.0.1",
port=0,
docroot=None,
urlhandlers=None,
path_mappings=None,
proxy_host_dirs=False,
log_requests=False):
self.host = host
self.port = int(port)
self.docroot = docroot
if not (urlhandlers or docroot or path_mappings):
self.docroot = os.getcwd()
self.proxy_host_dirs = proxy_host_dirs
self.httpd = None
self.urlhandlers = urlhandlers or []
self.path_mappings = path_mappings or {}
self.log_requests = log_requests
self.request_log = []
class RequestHandlerInstance(RequestHandler):
docroot = self.docroot
urlhandlers = self.urlhandlers
path_mappings = self.path_mappings
proxy_host_dirs = self.proxy_host_dirs
request_log = self.request_log
log_requests = self.log_requests
self.handler_class = RequestHandlerInstance
def start(self, block=False):
"""
Starts 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().
"""
self.httpd = EasyServer((self.host, self.port), self.handler_class)
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 stop(self):
"""
Stops the server.
If the server is not running, this method has no effect.
"""
if self.httpd:
### FIXME: There is no shutdown() method in Python 2.4...
try:
self.httpd.shutdown()
except AttributeError:
pass
self.httpd = None
def get_url(self, path="/"):
"""
Returns a URL that can be used for accessing the server (e.g. http://192.168.1.3:4321/)
:param path: Path to append to URL (e.g. if path were /foobar.html you would get a URL like
http://192.168.1.3:4321/foobar.html). Default is `/`.
"""
if not self.httpd:
return None
return "http://%s:%s%s" % (self.host, self.httpd.server_port, path)
__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('-i', '--external-ip', action="store_true",
dest='external_ip', default=False,
help="find and use external ip for host")
parser.add_option('-d', '--docroot', dest='docroot',
default=os.getcwd(),
help="directory to serve files from [DEFAULT: %default]")
options, args = parser.parse_args(args)
if args:
parser.error("mozhttpd does not take any arguments")
if options.external_ip:
host = moznetwork.get_lan_ip()
else:
host = options.host
# create the server
server = MozHttpd(host=host, port=options.port, docroot=options.docroot)
print "Serving '%s' at %s:%s" % (server.docroot, server.host, server.port)
server.start(block=True)
if __name__ == '__main__':
main()

View File

@ -1,30 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
from setuptools import setup
PACKAGE_VERSION = '0.7'
deps = ['moznetwork >= 0.24']
setup(name='mozhttpd',
version=PACKAGE_VERSION,
description="Python webserver intended for use with Mozilla testing",
long_description="see http://mozbase.readthedocs.org/",
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords='mozilla',
author='Mozilla Automation and Testing Team',
author_email='tools@lists.mozilla.org',
url='https://wiki.mozilla.org/Auto-tools/Projects/Mozbase',
license='MPL',
packages=['mozhttpd'],
include_package_data=True,
zip_safe=False,
install_requires=deps,
entry_points="""
# -*- Entry points: -*-
[console_scripts]
mozhttpd = mozhttpd:main
""",
)

View File

@ -1,262 +0,0 @@
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import mozfile
import mozhttpd
import urllib2
import os
import unittest
import json
import tempfile
here = os.path.dirname(os.path.abspath(__file__))
class ApiTest(unittest.TestCase):
resource_get_called = 0
resource_post_called = 0
resource_del_called = 0
@mozhttpd.handlers.json_response
def resource_get(self, request, objid):
self.resource_get_called += 1
return (200, { 'called': self.resource_get_called,
'id': objid,
'query': request.query })
@mozhttpd.handlers.json_response
def resource_post(self, request):
self.resource_post_called += 1
return (201, { 'called': self.resource_post_called,
'data': json.loads(request.body),
'query': request.query })
@mozhttpd.handlers.json_response
def resource_del(self, request, objid):
self.resource_del_called += 1
return (200, { 'called': self.resource_del_called,
'id': objid,
'query': request.query })
def get_url(self, path, server_port, querystr):
url = "http://127.0.0.1:%s%s" % (server_port, path)
if querystr:
url += "?%s" % querystr
return url
def try_get(self, server_port, querystr):
self.resource_get_called = 0
f = urllib2.urlopen(self.get_url('/api/resource/1', server_port, querystr))
try:
self.assertEqual(f.getcode(), 200)
except AttributeError:
pass # python 2.4
self.assertEqual(json.loads(f.read()), { 'called': 1, 'id': str(1), 'query': querystr })
self.assertEqual(self.resource_get_called, 1)
def try_post(self, server_port, querystr):
self.resource_post_called = 0
postdata = { 'hamburgers': '1234' }
try:
f = urllib2.urlopen(self.get_url('/api/resource/', server_port, querystr),
data=json.dumps(postdata))
except urllib2.HTTPError, e:
# python 2.4
self.assertEqual(e.code, 201)
body = e.fp.read()
else:
self.assertEqual(f.getcode(), 201)
body = f.read()
self.assertEqual(json.loads(body), { 'called': 1,
'data': postdata,
'query': querystr })
self.assertEqual(self.resource_post_called, 1)
def try_del(self, server_port, querystr):
self.resource_del_called = 0
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request(self.get_url('/api/resource/1', server_port, querystr))
request.get_method = lambda: 'DEL'
f = opener.open(request)
try:
self.assertEqual(f.getcode(), 200)
except AttributeError:
pass # python 2.4
self.assertEqual(json.loads(f.read()), { 'called': 1, 'id': str(1), 'query': querystr })
self.assertEqual(self.resource_del_called, 1)
def test_api(self):
httpd = mozhttpd.MozHttpd(port=0,
urlhandlers = [ { 'method': 'GET',
'path': '/api/resource/([^/]+)/?',
'function': self.resource_get },
{ 'method': 'POST',
'path': '/api/resource/?',
'function': self.resource_post },
{ 'method': 'DEL',
'path': '/api/resource/([^/]+)/?',
'function': self.resource_del }
])
httpd.start(block=False)
server_port = httpd.httpd.server_port
# GET
self.try_get(server_port, '')
self.try_get(server_port, '?foo=bar')
# POST
self.try_post(server_port, '')
self.try_post(server_port, '?foo=bar')
# DEL
self.try_del(server_port, '')
self.try_del(server_port, '?foo=bar')
# GET: By default we don't serve any files if we just define an API
exception_thrown = False
try:
urllib2.urlopen(self.get_url('/', server_port, None))
except urllib2.HTTPError, e:
self.assertEqual(e.code, 404)
exception_thrown = True
self.assertTrue(exception_thrown)
def test_nonexistent_resources(self):
# Create a server with a placeholder handler so we don't fall back
# to serving local files
httpd = mozhttpd.MozHttpd(port=0)
httpd.start(block=False)
server_port = httpd.httpd.server_port
# GET: Return 404 for non-existent endpoint
exception_thrown = False
try:
urllib2.urlopen(self.get_url('/api/resource/', server_port, None))
except urllib2.HTTPError, e:
self.assertEqual(e.code, 404)
exception_thrown = True
self.assertTrue(exception_thrown)
# POST: POST should also return 404
exception_thrown = False
try:
urllib2.urlopen(self.get_url('/api/resource/', server_port, None),
data=json.dumps({}))
except urllib2.HTTPError, e:
self.assertEqual(e.code, 404)
exception_thrown = True
self.assertTrue(exception_thrown)
# DEL: DEL should also return 404
exception_thrown = False
try:
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request(self.get_url('/api/resource/', server_port,
None))
request.get_method = lambda: 'DEL'
opener.open(request)
except urllib2.HTTPError:
self.assertEqual(e.code, 404)
exception_thrown = True
self.assertTrue(exception_thrown)
def test_api_with_docroot(self):
httpd = mozhttpd.MozHttpd(port=0, docroot=here,
urlhandlers = [ { 'method': 'GET',
'path': '/api/resource/([^/]+)/?',
'function': self.resource_get } ])
httpd.start(block=False)
server_port = httpd.httpd.server_port
# We defined a docroot, so we expect a directory listing
f = urllib2.urlopen(self.get_url('/', server_port, None))
try:
self.assertEqual(f.getcode(), 200)
except AttributeError:
pass # python 2.4
self.assertTrue('Directory listing for' in f.read())
# Make sure API methods still work
self.try_get(server_port, '')
self.try_get(server_port, '?foo=bar')
class ProxyTest(unittest.TestCase):
def tearDown(self):
# reset proxy opener in case it changed
urllib2.install_opener(None)
def test_proxy(self):
docroot = tempfile.mkdtemp()
self.addCleanup(mozfile.remove, docroot)
hosts = ('mozilla.com', 'mozilla.org')
unproxied_host = 'notmozilla.org'
def url(host): return 'http://%s/' % host
index_filename = 'index.html'
def index_contents(host): return '%s index' % host
index = file(os.path.join(docroot, index_filename), 'w')
index.write(index_contents('*'))
index.close()
httpd = mozhttpd.MozHttpd(port=0, docroot=docroot)
httpd.start(block=False)
server_port = httpd.httpd.server_port
proxy_support = urllib2.ProxyHandler({'http': 'http://127.0.0.1:%d' %
server_port})
urllib2.install_opener(urllib2.build_opener(proxy_support))
for host in hosts:
f = urllib2.urlopen(url(host))
try:
self.assertEqual(f.getcode(), 200)
except AttributeError:
pass # python 2.4
self.assertEqual(f.read(), index_contents('*'))
httpd.stop()
# test separate directories per host
httpd = mozhttpd.MozHttpd(port=0, docroot=docroot, proxy_host_dirs=True)
httpd.start(block=False)
server_port = httpd.httpd.server_port
proxy_support = urllib2.ProxyHandler({'http': 'http://127.0.0.1:%d' %
server_port})
urllib2.install_opener(urllib2.build_opener(proxy_support))
# set up dirs
for host in hosts:
os.mkdir(os.path.join(docroot, host))
file(os.path.join(docroot, host, index_filename), 'w') \
.write(index_contents(host))
for host in hosts:
f = urllib2.urlopen(url(host))
try:
self.assertEqual(f.getcode(), 200)
except AttributeError:
pass # python 2.4
self.assertEqual(f.read(), index_contents(host))
exc = None
try:
urllib2.urlopen(url(unproxied_host))
except urllib2.HTTPError, e:
exc = e
self.assertNotEqual(exc, None)
self.assertEqual(exc.code, 404)
if __name__ == '__main__':
unittest.main()

View File

@ -1,18 +0,0 @@
import mozhttpd
import unittest
class BaseUrlTest(unittest.TestCase):
def test_base_url(self):
httpd = mozhttpd.MozHttpd(port=0)
self.assertEqual(httpd.get_url(), None)
httpd.start(block=False)
self.assertEqual("http://127.0.0.1:%s/" % httpd.httpd.server_port,
httpd.get_url())
self.assertEqual("http://127.0.0.1:%s/cheezburgers.html" % \
httpd.httpd.server_port,
httpd.get_url(path="/cheezburgers.html"))
httpd.stop()
if __name__ == '__main__':
unittest.main()

View File

@ -1,46 +0,0 @@
#!/usr/bin/env python
import mozhttpd
import mozfile
import os
import tempfile
import unittest
class TestBasic(unittest.TestCase):
""" Test basic Mozhttpd capabilites """
def test_basic(self):
""" Test mozhttpd can serve files """
tempdir = tempfile.mkdtemp()
# sizes is a dict of the form: name -> [size, binary_string, filepath]
sizes = {'small': [128], 'large': [16384]}
for k in sizes.keys():
# Generate random binary string
sizes[k].append(os.urandom(sizes[k][0]))
# Add path of file with binary string to list
fpath = os.path.join(tempdir, k)
sizes[k].append(fpath)
# Write binary string to file
with open(fpath, 'wb') as f:
f.write(sizes[k][1])
server = mozhttpd.MozHttpd(docroot=tempdir)
server.start()
server_url = server.get_url()
# Retrieve file and check contents matchup
for k in sizes.keys():
retrieved_content = mozfile.load(server_url + k).read()
self.assertEqual(retrieved_content, sizes[k][1])
# Cleanup tempdir and related files
mozfile.rmtree(tempdir)
if __name__ == '__main__':
unittest.main()

View File

@ -1,41 +0,0 @@
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import mozhttpd
import urllib2
import os
import unittest
import re
here = os.path.dirname(os.path.abspath(__file__))
class FileListingTest(unittest.TestCase):
def check_filelisting(self, path=''):
filelist = os.listdir(here)
httpd = mozhttpd.MozHttpd(port=0, docroot=here)
httpd.start(block=False)
f = urllib2.urlopen("http://%s:%s/%s" % ('127.0.0.1', httpd.httpd.server_port, path))
for line in f.readlines():
webline = re.sub('\<[a-zA-Z0-9\-\_\.\=\"\'\/\\\%\!\@\#\$\^\&\*\(\) ]*\>', '', line.strip('\n')).strip('/').strip().strip('@')
if webline and not webline.startswith("Directory listing for"):
self.assertTrue(webline in filelist,
"File %s in dir listing corresponds to a file" % webline)
filelist.remove(webline)
self.assertFalse(filelist, "Should have no items in filelist (%s) unaccounted for" % filelist)
def test_filelist(self):
self.check_filelisting()
def test_filelist_params(self):
self.check_filelisting('?foo=bar&fleem=&foo=fleem')
if __name__ == '__main__':
unittest.main()

View File

@ -1,6 +0,0 @@
[api.py]
[baseurl.py]
[basic.py]
[filelisting.py]
[paths.py]
[requestlog.py]

View File

@ -1,75 +0,0 @@
#!/usr/bin/env python
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
from mozfile import TemporaryDirectory
import mozhttpd
import os
import unittest
import urllib2
class PathTest(unittest.TestCase):
def try_get(self, url, expected_contents):
f = urllib2.urlopen(url)
self.assertEqual(f.getcode(), 200)
self.assertEqual(f.read(), expected_contents)
def try_get_expect_404(self, url):
with self.assertRaises(urllib2.HTTPError) as cm:
urllib2.urlopen(url)
self.assertEqual(404, cm.exception.code)
def test_basic(self):
"""Test that requests to docroot and a path mapping work as expected."""
with TemporaryDirectory() as d1, TemporaryDirectory() as d2:
open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents")
open(os.path.join(d2, "test2.txt"), "w").write("test 2 contents")
httpd = mozhttpd.MozHttpd(port=0,
docroot=d1,
path_mappings={'/files': d2}
)
httpd.start(block=False)
self.try_get(httpd.get_url("/test1.txt"), "test 1 contents")
self.try_get(httpd.get_url("/files/test2.txt"), "test 2 contents")
self.try_get_expect_404(httpd.get_url("/files/test2_nope.txt"))
httpd.stop()
def test_substring_mappings(self):
"""Test that a path mapping that's a substring of another works."""
with TemporaryDirectory() as d1, TemporaryDirectory() as d2:
open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents")
open(os.path.join(d2, "test2.txt"), "w").write("test 2 contents")
httpd = mozhttpd.MozHttpd(port=0,
path_mappings={'/abcxyz': d1,
'/abc': d2,}
)
httpd.start(block=False)
self.try_get(httpd.get_url("/abcxyz/test1.txt"), "test 1 contents")
self.try_get(httpd.get_url("/abc/test2.txt"), "test 2 contents")
httpd.stop()
def test_multipart_path_mapping(self):
"""Test that a path mapping with multiple directories works."""
with TemporaryDirectory() as d1:
open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents")
httpd = mozhttpd.MozHttpd(port=0,
path_mappings={'/abc/def/ghi': d1}
)
httpd.start(block=False)
self.try_get(httpd.get_url("/abc/def/ghi/test1.txt"), "test 1 contents")
self.try_get_expect_404(httpd.get_url("/abc/test1.txt"))
self.try_get_expect_404(httpd.get_url("/abc/def/test1.txt"))
httpd.stop()
def test_no_docroot(self):
"""Test that path mappings with no docroot work."""
with TemporaryDirectory() as d1:
httpd = mozhttpd.MozHttpd(port=0,
path_mappings={'/foo': d1})
httpd.start(block=False)
self.try_get_expect_404(httpd.get_url())
httpd.stop()
if __name__ == '__main__':
unittest.main()

View File

@ -1,40 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import mozhttpd
import urllib2
import os
import unittest
here = os.path.dirname(os.path.abspath(__file__))
class RequestLogTest(unittest.TestCase):
def check_logging(self, log_requests=False):
httpd = mozhttpd.MozHttpd(port=0, docroot=here, log_requests=log_requests)
httpd.start(block=False)
url = "http://%s:%s/" % ('127.0.0.1', httpd.httpd.server_port)
f = urllib2.urlopen(url)
f.read()
return httpd.request_log
def test_logging_enabled(self):
request_log = self.check_logging(log_requests=True)
self.assertEqual(len(request_log), 1)
log_entry = request_log[0]
self.assertEqual(log_entry['method'], 'GET')
self.assertEqual(log_entry['path'], '/')
self.assertEqual(type(log_entry['time']), float)
def test_logging_disabled(self):
request_log = self.check_logging(log_requests=False)
self.assertEqual(len(request_log), 0)
if __name__ == '__main__':
unittest.main()

View File

@ -35,7 +35,7 @@ setup(name=PACKAGE_NAME,
zip_safe=False,
install_requires=deps,
extras_require={'manifest': ['manifestparser >= 0.6']},
tests_require=['mozhttpd'],
tests_require=['wptserve'],
entry_points="""
# -*- Entry points: -*-
[console_scripts]

View File

@ -12,7 +12,7 @@ import urllib2
from manifestparser import ManifestParser
import mozfile
import mozhttpd
from wptserve.server import WebTestHttpd
import mozlog.unstructured as mozlog
import mozprofile
@ -63,7 +63,7 @@ class TestAddonsManager(unittest.TestCase):
self.am.clean()
def test_download(self):
server = mozhttpd.MozHttpd(docroot=os.path.join(here, 'addons'))
server = WebTestHttpd(doc_root=os.path.join(here, 'addons'))
server.start()
# Download a valid add-on without a class instance to the general
@ -173,7 +173,7 @@ class TestAddonsManager(unittest.TestCase):
self.am.clean()
def test_install_from_path_url(self):
server = mozhttpd.MozHttpd(docroot=os.path.join(here, 'addons'))
server = WebTestHttpd(doc_root=os.path.join(here, 'addons'))
server.start()
addon = server.get_url() + 'empty.xpi'
@ -345,7 +345,7 @@ class TestAddonsManager(unittest.TestCase):
def test_noclean(self):
"""test `restore=True/False` functionality"""
server = mozhttpd.MozHttpd(docroot=os.path.join(here, 'addons'))
server = WebTestHttpd(doc_root=os.path.join(here, 'addons'))
server.start()
profile = tempfile.mkdtemp()

View File

@ -5,7 +5,7 @@
# You can obtain one at http://mozilla.org/MPL/2.0/.
import mozfile
import mozhttpd
from wptserve.server import WebTestHttpd
import os
import shutil
import tempfile
@ -352,13 +352,11 @@ user_pref("webgl.force-enabled", true);
self.assertEqual(dict(read_prefs), expected_prefs)
def test_read_prefs_ttw(self):
"""test reading preferences through the web via mozhttpd"""
"""test reading preferences through the web via wptserve"""
# create a MozHttpd instance
docroot = os.path.join(here, 'files')
host = '127.0.0.1'
port = 8888
httpd = mozhttpd.MozHttpd(host=host, port=port, docroot=docroot)
# create a server instance
httpd = WebTestHttpd(host='127.0.0.1', port=0,
doc_root=os.path.join(here, 'files'))
# create a preferences instance
prefs = Preferences()
@ -368,7 +366,8 @@ user_pref("webgl.force-enabled", true);
httpd.start(block=False)
# read preferences through the web
read = prefs.read_prefs('http://%s:%d/prefs_with_comments.js' % (host, port))
read = prefs.read_prefs('http://%s:%d/prefs_with_comments.js' %
httpd.httpd.server_address)
self.assertEqual(dict(read), self._prefs_with_comments)
finally:
httpd.stop()

View File

@ -4,7 +4,6 @@ mozcrash.pth:testing/mozbase/mozcrash
mozdebug.pth:testing/mozbase/mozdebug
mozdevice.pth:testing/mozbase/mozdevice
mozfile.pth:testing/mozbase/mozfile
mozhttpd.pth:testing/mozbase/mozhttpd
mozinfo.pth:testing/mozbase/mozinfo
mozinstall.pth:testing/mozbase/mozinstall
mozleak.pth:testing/mozbase/mozleak

View File

@ -12,7 +12,6 @@
[include:mozcrash/tests/manifest.ini]
[include:mozdevice/tests/manifest.ini]
[include:mozfile/tests/manifest.ini]
[include:mozhttpd/tests/manifest.ini]
[include:mozinfo/tests/manifest.ini]
[include:mozinstall/tests/manifest.ini]
[include:mozlog/tests/manifest.ini]

View File

@ -31,7 +31,7 @@ class MozbaseMixin(object):
url=os.path.join(mozbase_dir, 'manifestdestiny')
)
for m in ('mozfile', 'mozlog', 'mozinfo', 'moznetwork', 'mozhttpd',
for m in ('mozfile', 'mozlog', 'mozinfo', 'moznetwork',
'mozcrash', 'mozinstall', 'mozdevice', 'mozprofile',
'mozprocess', 'mozrunner'):
self.register_virtualenv_module(

View File

@ -243,7 +243,7 @@ class MarionetteTest(TestingMixin, MercurialScript, BlobUploadMixin, TransferMix
mozbase_dir = os.path.join('tests', 'mozbase')
self.register_virtualenv_module(
'manifestparser', os.path.join(mozbase_dir, 'manifestdestiny'))
for m in ('mozfile', 'mozlog', 'mozinfo', 'moznetwork', 'mozhttpd',
for m in ('mozfile', 'mozlog', 'mozinfo', 'moznetwork',
'mozcrash', 'mozinstall', 'mozdevice', 'mozprofile',
'mozprocess', 'mozrunner'):
self.register_virtualenv_module(

View File

@ -9,7 +9,6 @@ logilab-astng==0.23.1
logilab-common==0.57.1
mozdevice==0.2
-e hg+https://hg.mozilla.org/build/mozharness@df6b7f1e14d8c472125ef7a77b8a3b40c96ae181#egg=mozharness-jetperf
mozhttpd==0.3
mozinfo==0.3.3
nose==1.1.2
pyflakes==0.5.0

View File

@ -22,7 +22,6 @@ class TestVirtualenvMixin(unittest.TestCase):
'logilab-astng': '0.23.1',
'logilab-common': '0.57.1',
'mozdevice': '0.2',
'mozhttpd': '0.3',
'mozinfo': '0.3.3',
'nose': '1.1.2',
'pyflakes': '0.5.0',

View File

@ -1,7 +1,7 @@
mozlog>=3.1
mozcrash>=0.15
mozfile>=1.2
mozhttpd>=0.7
wptserve>=1.3.0
mozinfo>=0.8
mozprocess>=0.22
mozversion>=1.3

View File

@ -11,8 +11,8 @@ import time
import traceback
import urllib
import utils
import mozhttpd
from wptserve.server import WebTestHttpd
from mozlog import get_proxy_logger
from talos.results import TalosResults
@ -68,11 +68,11 @@ def buildCommandLine(test):
def setup_webserver(webserver):
"""use mozhttpd to setup a webserver"""
"""use wptserve to setup a webserver"""
LOG.info("starting webserver on %r" % webserver)
host, port = webserver.split(':')
return mozhttpd.MozHttpd(host=host, port=int(port), docroot=here)
return WebTestHttpd(host=host, port=int(port), doc_root=here)
def run_tests(config, browser_config):

View File

@ -16,7 +16,6 @@ SEARCH_PATHS = [
'mozbase/mozdebug',
'mozbase/mozdevice',
'mozbase/mozfile',
'mozbase/mozhttpd',
'mozbase/mozleak',
'mozbase/mozlog',
'mozbase/moznetwork',

View File

@ -9,7 +9,7 @@ version = '0.5'
deps = ['httplib2 == 0.7.3',
'mozfile == 1.1',
'mozhttpd == 0.7',
'wptserve == 1.3.0',
'mozinfo == 0.7',
'mozinstall == 1.10',
'mozprocess == 0.19',

View File

@ -11,7 +11,7 @@ import tempfile
import time
import traceback
from mozhttpd import MozHttpd
from wptserve.server import WebTestHttpd
import mozinfo
from mozprofile import Profile
import mozversion
@ -435,8 +435,8 @@ class TPSTestRunner(object):
testlist = [os.path.basename(self.testfile)]
testdir = os.path.dirname(self.testfile)
self.mozhttpd = MozHttpd(port=4567, docroot=testdir)
self.mozhttpd.start()
self.httpd = WebTestHttpd(port=4567, doc_root=testdir)
self.httpd.start()
# run each test, and save the results
for test in testlist:
@ -459,7 +459,7 @@ class TPSTestRunner(object):
print '\nTest failed with --stop-on-error specified; not running any more tests.\n'
break
self.mozhttpd.stop()
self.httpd.stop()
# generate the postdata we'll use to post the results to the db
self.postdata = { 'tests': self.results,

View File

@ -13,7 +13,7 @@ from mach.decorators import (
CommandProvider,
)
import mozhttpd
from wptserve.server import WebTestHttpd
from mozbuild.base import MachCommandBase
@ -90,7 +90,7 @@ class Documentation(MachCommandBase):
if len(addr) != 2:
return die('invalid address: %s' % http)
httpd = mozhttpd.MozHttpd(host=addr[0], port=addr[1], docroot=outdir)
httpd = WebTestHttpd(host=addr[0], port=addr[1], doc_root=outdir)
print('listening on %s:%d' % addr)
httpd.start(block=True)