Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / NativeClient / bin_html / httpd.py
1 #!/usr/bin/python
2 #
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.
6 #
7
8 """A tiny web server.
9
10 This is intended to be used for testing, and only run from within the examples
11 directory.
12 """
13
14 import BaseHTTPServer
15 import logging
16 import os
17 import SimpleHTTPServer
18 import SocketServer
19 import sys
20 import urlparse
21
22 logging.getLogger().setLevel(logging.INFO)
23
24 # Using 'localhost' means that we only accept connections
25 # via the loop back interface.
26 SERVER_PORT = 5103
27 SERVER_HOST = ''
28
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.
35
36 SAFE_DIR_COMPONENTS = ['bin_html']
37 SAFE_DIR_SUFFIX = apply(os.path.join, SAFE_DIR_COMPONENTS)
38
39 def SanityCheckDirectory():
40   if os.getcwd().endswith(SAFE_DIR_SUFFIX):
41     return
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())
45   sys.exit(1)
46
47
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
50 # faster responses.
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:
57       self.handle_request()
58
59   def shutdown(self):
60     self.is_running = False
61     return 1
62
63
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
66 # empty string.
67 def KeyValuePair(str, sep='='):
68   if sep in str:
69     return str.split(sep)
70   else:
71     return [str, '']
72
73
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):
77   def do_GET(self):
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')
85       self.end_headers()
86       self.server.shutdown()
87       return
88
89     SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
90
91
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",
98                server_address[1])
99   try:
100     httpd.serve_forever()
101   except KeyboardInterrupt:
102     logging.info("Received keyboard interrupt.")
103     httpd.server_close()
104
105   logging.info("Shutting down local server on port %d", server_address[1])
106
107
108 if __name__ == '__main__':
109   SanityCheckDirectory()
110   if len(sys.argv) > 1:
111     Run((SERVER_HOST, int(sys.argv[1])))
112   else:
113     Run((SERVER_HOST, SERVER_PORT))
114   sys.exit(0)