3 # Copyright (c) 2011, The Native Client Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
10 This is intended to be used for testing, and only run from within the examples
17 import SimpleHTTPServer
22 logging.getLogger().setLevel(logging.INFO)
24 # Using 'localhost' means that we only accept connections
25 # via the loop back interface.
29 # We only run from the examples directory (the one that contains scons-out), so
30 # that not too much is exposed via this HTTP server. Everything in the
31 # directory is served, so there should never be anything potentially sensitive
32 # in the serving directory, especially if the machine might be a
33 # multi-user machine and not all users are trusted. We only serve via
34 # the loopback interface.
36 SAFE_DIR_COMPONENTS = ['bin_html']
37 SAFE_DIR_SUFFIX = apply(os.path.join, SAFE_DIR_COMPONENTS)
39 def SanityCheckDirectory():
40 if os.getcwd().endswith(SAFE_DIR_SUFFIX):
42 logging.error('httpd.py should only be run from the %s', SAFE_DIR_SUFFIX)
43 logging.error('directory for testing purposes.')
44 logging.error('We are currently in %s', os.getcwd())
48 # An HTTP server that will quit when |is_running| is set to False. We also use
49 # SocketServer.ThreadingMixIn in order to handle requests asynchronously for
51 class QuittableHTTPServer(SocketServer.ThreadingMixIn,
52 BaseHTTPServer.HTTPServer):
53 def serve_forever(self, timeout=0.5):
54 self.is_running = True
55 self.timeout = timeout
56 while self.is_running:
60 self.is_running = False
64 # "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not
65 # exist in |str|, then the entire |str| is the key and the value is set to an
67 def KeyValuePair(str, sep='='):
74 # A small handler that looks for '?quit=1' query in the path and shuts itself
75 # down if it finds that parameter.
76 class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
78 (_, _, _, query, _) = urlparse.urlsplit(self.path)
79 url_params = dict([KeyValuePair(key_value)
80 for key_value in query.split('&')])
81 if 'quit' in url_params and '1' in url_params['quit']:
82 self.send_response(200, 'OK')
83 self.send_header('Content-type', 'text/html')
84 self.send_header('Content-length', '0')
86 self.server.shutdown()
89 SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
92 def Run(server_address,
93 server_class=QuittableHTTPServer,
94 handler_class=QuittableHTTPHandler):
95 httpd = server_class(server_address, handler_class)
96 logging.info("Starting local server on port %d", server_address[1])
97 logging.info("To shut down send http://localhost:%d?quit=1",
100 httpd.serve_forever()
101 except KeyboardInterrupt:
102 logging.info("Received keyboard interrupt.")
105 logging.info("Shutting down local server on port %d", server_address[1])
108 if __name__ == '__main__':
109 SanityCheckDirectory()
110 if len(sys.argv) > 1:
111 Run((SERVER_HOST, int(sys.argv[1])))
113 Run((SERVER_HOST, SERVER_PORT))