OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """A tiny web server. | 6 """A tiny web server. |
7 | 7 |
8 This is intended to be used for testing, and only run from within the examples | 8 This is intended to be used for testing, and only run from within the examples |
9 directory. | 9 directory. |
10 """ | 10 """ |
11 | 11 |
12 import BaseHTTPServer | 12 import BaseHTTPServer |
13 import logging | 13 import logging |
14 import optparse | 14 import optparse |
15 import os | 15 import os |
16 import SimpleHTTPServer | 16 import SimpleHTTPServer |
17 import SocketServer | 17 import SocketServer |
18 import sys | 18 import sys |
19 import urlparse | 19 import urlparse |
20 | 20 |
21 | 21 |
22 EXAMPLE_PATH=os.path.dirname(os.path.abspath(__file__)) | 22 EXAMPLE_PATH = os.path.dirname(os.path.abspath(__file__)) |
23 NACL_SDK_ROOT = os.getenv('NACL_SDK_ROOT', os.path.dirname(EXAMPLE_PATH)) | 23 NACL_SDK_ROOT = os.getenv('NACL_SDK_ROOT', os.path.dirname(EXAMPLE_PATH)) |
24 | 24 |
25 | 25 |
26 if os.path.exists(NACL_SDK_ROOT): | 26 if os.path.exists(NACL_SDK_ROOT): |
27 sys.path.append(os.path.join(NACL_SDK_ROOT, 'tools')) | 27 sys.path.append(os.path.join(NACL_SDK_ROOT, 'tools')) |
| 28 # pylint: disable=F0401 |
28 import decode_dump | 29 import decode_dump |
29 import getos | 30 import getos |
30 else: | 31 else: |
31 NACL_SDK_ROOT=None | 32 NACL_SDK_ROOT = None |
32 | 33 |
33 last_nexe = None | 34 last_nexe = None |
34 last_nmf = None | 35 last_nmf = None |
35 | 36 |
36 logging.getLogger().setLevel(logging.INFO) | 37 logging.getLogger().setLevel(logging.INFO) |
37 | 38 |
38 # Using 'localhost' means that we only accept connections | 39 # Using 'localhost' means that we only accept connections |
39 # via the loop back interface. | 40 # via the loop back interface. |
40 SERVER_PORT = 5103 | 41 SERVER_PORT = 5103 |
41 SERVER_HOST = '' | 42 SERVER_HOST = '' |
(...skipping 14 matching lines...) Expand all Loading... |
56 logging.error('example directory tree.') | 57 logging.error('example directory tree.') |
57 logging.error('We are currently in %s.' % serve_path) | 58 logging.error('We are currently in %s.' % serve_path) |
58 sys.exit(1) | 59 sys.exit(1) |
59 | 60 |
60 | 61 |
61 # An HTTP server that will quit when |is_running| is set to False. We also use | 62 # An HTTP server that will quit when |is_running| is set to False. We also use |
62 # SocketServer.ThreadingMixIn in order to handle requests asynchronously for | 63 # SocketServer.ThreadingMixIn in order to handle requests asynchronously for |
63 # faster responses. | 64 # faster responses. |
64 class QuittableHTTPServer(SocketServer.ThreadingMixIn, | 65 class QuittableHTTPServer(SocketServer.ThreadingMixIn, |
65 BaseHTTPServer.HTTPServer): | 66 BaseHTTPServer.HTTPServer): |
| 67 is_running = False |
| 68 |
66 def serve_forever(self, timeout=0.5): | 69 def serve_forever(self, timeout=0.5): |
67 self.is_running = True | 70 self.is_running = True |
68 self.timeout = timeout | 71 self.timeout = timeout |
69 while self.is_running: | 72 while self.is_running: |
70 sys.stderr.flush() | 73 sys.stderr.flush() |
71 sys.stdout.flush() | 74 sys.stdout.flush() |
72 self.handle_request() | 75 self.handle_request() |
73 | 76 |
74 def shutdown(self): | 77 def shutdown(self): |
75 self.is_running = False | 78 self.is_running = False |
76 return 1 | 79 return 1 |
77 | 80 |
78 | 81 |
79 # "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not | 82 # "Safely" split a string at |sep| into a [key, value] pair. If |sep| does not |
80 # exist in |str|, then the entire |str| is the key and the value is set to an | 83 # exist in |pair|, then the entire |pair| is the key and the value is set to an |
81 # empty string. | 84 # empty string. |
82 def KeyValuePair(str, sep='='): | 85 def KeyValuePair(pair, sep='='): |
83 if sep in str: | 86 if sep in pair: |
84 return str.split(sep) | 87 return pair.split(sep) |
85 else: | 88 else: |
86 return [str, ''] | 89 return [pair, ''] |
87 | 90 |
88 | 91 |
89 # A small handler that looks for '?quit=1' query in the path and shuts itself | 92 # A small handler that looks for '?quit=1' query in the path and shuts itself |
90 # down if it finds that parameter. | 93 # down if it finds that parameter. |
91 class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): | 94 class QuittableHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): |
92 def send_head(self): | 95 def send_head(self): |
93 """Common code for GET and HEAD commands. | 96 """Common code for GET and HEAD commands. |
94 | 97 |
95 This sends the response code and MIME headers. | 98 This sends the response code and MIME headers. |
96 | 99 |
97 Return value is either a file object (which has to be copied | 100 Return value is either a file object (which has to be copied |
98 to the outputfile by the caller unless the command was HEAD, | 101 to the outputfile by the caller unless the command was HEAD, |
99 and must be closed by the caller under all circumstances), or | 102 and must be closed by the caller under all circumstances), or |
100 None, in which case the caller has nothing further to do. | 103 None, in which case the caller has nothing further to do. |
101 | 104 |
102 """ | 105 """ |
103 path = self.translate_path(self.path) | 106 path = self.translate_path(self.path) |
104 f = None | 107 f = None |
105 if os.path.isdir(path): | 108 if os.path.isdir(path): |
106 if not self.path.endswith('/'): | 109 if not self.path.endswith('/'): |
107 # redirect browser - doing basically what apache does | 110 # redirect browser - doing basically what apache does |
108 self.send_response(301) | 111 self.send_response(301) |
109 self.send_header("Location", self.path + "/") | 112 self.send_header("Location", self.path + "/") |
110 self.end_headers() | 113 self.end_headers() |
111 return None | 114 return None |
112 for index in "index.html", "index.htm": | 115 for index in "index.html", "index.htm": |
113 index = os.path.join(path, index) | 116 index = os.path.join(path, index) |
114 if os.path.exists(index): | 117 if os.path.exists(index): |
115 path = index | 118 path = index |
116 break | 119 break |
117 else: | 120 else: |
118 return self.list_directory(path) | 121 return self.list_directory(path) |
119 ctype = self.guess_type(path) | 122 ctype = self.guess_type(path) |
120 try: | 123 try: |
121 # Always read in binary mode. Opening files in text mode may cause | 124 # Always read in binary mode. Opening files in text mode may cause |
122 # newline translations, making the actual size of the content | 125 # newline translations, making the actual size of the content |
123 # transmitted *less* than the content-length! | 126 # transmitted *less* than the content-length! |
124 f = open(path, 'rb') | 127 f = open(path, 'rb') |
125 except IOError: | 128 except IOError: |
126 self.send_error(404, "File not found") | 129 self.send_error(404, "File not found") |
127 return None | 130 return None |
128 self.send_response(200) | 131 self.send_response(200) |
129 self.send_header("Content-type", ctype) | 132 self.send_header("Content-type", ctype) |
130 fs = os.fstat(f.fileno()) | 133 fs = os.fstat(f.fileno()) |
131 self.send_header("Content-Length", str(fs[6])) | 134 self.send_header("Content-Length", str(fs[6])) |
132 self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) | 135 self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) |
133 self.send_header('Cache-Control','no-cache, must-revalidate') | 136 self.send_header('Cache-Control','no-cache, must-revalidate') |
134 self.send_header('Expires','-1') | 137 self.send_header('Expires','-1') |
135 self.end_headers() | 138 self.end_headers() |
136 return f | 139 return f |
137 | 140 |
(...skipping 11 matching lines...) Expand all Loading... |
149 return | 152 return |
150 | 153 |
151 if path.endswith('.nexe'): | 154 if path.endswith('.nexe'): |
152 last_nexe = path | 155 last_nexe = path |
153 if path.endswith('.nmf'): | 156 if path.endswith('.nmf'): |
154 last_nmf = path | 157 last_nmf = path |
155 | 158 |
156 SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) | 159 SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) |
157 | 160 |
158 def do_POST(self): | 161 def do_POST(self): |
159 (_, _,path, query, _) = urlparse.urlsplit(self.path) | |
160 if 'Content-Length' in self.headers: | 162 if 'Content-Length' in self.headers: |
161 if not NACL_SDK_ROOT: | 163 if not NACL_SDK_ROOT: |
162 self.wfile('Could not find NACL_SDK_ROOT to decode trace.') | 164 self.wfile('Could not find NACL_SDK_ROOT to decode trace.') |
163 return | 165 return |
164 data = self.rfile.read(int(self.headers['Content-Length'])) | 166 data = self.rfile.read(int(self.headers['Content-Length'])) |
165 nexe = '.' + last_nexe | 167 nexe = '.' + last_nexe |
166 nmf = '.' + last_nmf | 168 nmf = '.' + last_nmf |
167 addr = os.path.join(NACL_SDK_ROOT, 'toolchain', | 169 addr = os.path.join(NACL_SDK_ROOT, 'toolchain', |
168 getos.GetPlatform() + '_x86_newlib', | 170 getos.GetPlatform() + '_x86_newlib', |
169 'bin', 'x86_64-nacl-addr2line') | 171 'bin', 'x86_64-nacl-addr2line') |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 parser.print_help() | 207 parser.print_help() |
206 elif len(args) == 2: | 208 elif len(args) == 2: |
207 Run((SERVER_HOST, int(args[1]))) | 209 Run((SERVER_HOST, int(args[1]))) |
208 else: | 210 else: |
209 Run((SERVER_HOST, SERVER_PORT)) | 211 Run((SERVER_HOST, SERVER_PORT)) |
210 return 0 | 212 return 0 |
211 | 213 |
212 | 214 |
213 if __name__ == '__main__': | 215 if __name__ == '__main__': |
214 sys.exit(main()) | 216 sys.exit(main()) |
OLD | NEW |