OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 """This is a simple HTTP/FTP/SYNC/TCP/UDP/ server used for testing Chrome. | 6 """This is a simple HTTP/FTP/SYNC/TCP/UDP/ server used for testing Chrome. |
7 | 7 |
8 It supports several test URLs, as specified by the handlers in TestPageHandler. | 8 It supports several test URLs, as specified by the handlers in TestPageHandler. |
9 By default, it listens on an ephemeral port and sends the port number back to | 9 By default, it listens on an ephemeral port and sends the port number back to |
10 the originating process over a pipe. The originating process can specify an | 10 the originating process over a pipe. The originating process can specify an |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 self.stop = False | 259 self.stop = False |
260 self.nonce_time = None | 260 self.nonce_time = None |
261 while not self.stop: | 261 while not self.stop: |
262 self.handle_request() | 262 self.handle_request() |
263 self.socket.close() | 263 self.socket.close() |
264 | 264 |
265 | 265 |
266 class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler): | 266 class BasePageHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
267 | 267 |
268 def __init__(self, request, client_address, socket_server, | 268 def __init__(self, request, client_address, socket_server, |
269 connect_handlers, get_handlers, post_handlers, put_handlers): | 269 connect_handlers, get_handlers, head_handlers, post_handlers, |
270 put_handlers): | |
270 self._connect_handlers = connect_handlers | 271 self._connect_handlers = connect_handlers |
271 self._get_handlers = get_handlers | 272 self._get_handlers = get_handlers |
273 self._head_handlers = head_handlers | |
272 self._post_handlers = post_handlers | 274 self._post_handlers = post_handlers |
273 self._put_handlers = put_handlers | 275 self._put_handlers = put_handlers |
274 BaseHTTPServer.BaseHTTPRequestHandler.__init__( | 276 BaseHTTPServer.BaseHTTPRequestHandler.__init__( |
275 self, request, client_address, socket_server) | 277 self, request, client_address, socket_server) |
276 | 278 |
277 def log_request(self, *args, **kwargs): | 279 def log_request(self, *args, **kwargs): |
278 # Disable request logging to declutter test log output. | 280 # Disable request logging to declutter test log output. |
279 pass | 281 pass |
280 | 282 |
281 def _ShouldHandleRequest(self, handler_name): | 283 def _ShouldHandleRequest(self, handler_name): |
282 """Determines if the path can be handled by the handler. | 284 """Determines if the path can be handled by the handler. |
283 | 285 |
284 We consider a handler valid if the path begins with the | 286 We consider a handler valid if the path begins with the |
285 handler name. It can optionally be followed by "?*", "/*". | 287 handler name. It can optionally be followed by "?*", "/*". |
286 """ | 288 """ |
287 | 289 |
288 pattern = re.compile('%s($|\?|/).*' % handler_name) | 290 pattern = re.compile('%s($|\?|/).*' % handler_name) |
289 return pattern.match(self.path) | 291 return pattern.match(self.path) |
290 | 292 |
291 def do_CONNECT(self): | 293 def do_CONNECT(self): |
292 for handler in self._connect_handlers: | 294 for handler in self._connect_handlers: |
293 if handler(): | 295 if handler(): |
294 return | 296 return |
295 | 297 |
296 def do_GET(self): | 298 def do_GET(self): |
297 for handler in self._get_handlers: | 299 for handler in self._get_handlers: |
298 if handler(): | 300 if handler(): |
299 return | 301 return |
300 | 302 |
303 def do_HEAD(self): | |
304 for handler in self._head_handlers: | |
305 if handler(): | |
306 return | |
307 | |
301 def do_POST(self): | 308 def do_POST(self): |
302 for handler in self._post_handlers: | 309 for handler in self._post_handlers: |
303 if handler(): | 310 if handler(): |
304 return | 311 return |
305 | 312 |
306 def do_PUT(self): | 313 def do_PUT(self): |
307 for handler in self._put_handlers: | 314 for handler in self._put_handlers: |
308 if handler(): | 315 if handler(): |
309 return | 316 return |
310 | 317 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
344 self.ChunkedServerHandler, | 351 self.ChunkedServerHandler, |
345 self.ContentTypeHandler, | 352 self.ContentTypeHandler, |
346 self.NoContentHandler, | 353 self.NoContentHandler, |
347 self.ServerRedirectHandler, | 354 self.ServerRedirectHandler, |
348 self.ClientRedirectHandler, | 355 self.ClientRedirectHandler, |
349 self.MultipartHandler, | 356 self.MultipartHandler, |
350 self.MultipartSlowHandler, | 357 self.MultipartSlowHandler, |
351 self.DefaultResponseHandler] | 358 self.DefaultResponseHandler] |
352 post_handlers = [ | 359 post_handlers = [ |
353 self.EchoTitleHandler, | 360 self.EchoTitleHandler, |
354 self.EchoAllHandler, | |
355 self.EchoHandler, | 361 self.EchoHandler, |
356 self.DeviceManagementHandler] + get_handlers | 362 self.DeviceManagementHandler] + get_handlers |
357 put_handlers = [ | 363 put_handlers = [ |
358 self.EchoTitleHandler, | 364 self.EchoTitleHandler, |
359 self.EchoAllHandler, | |
360 self.EchoHandler] + get_handlers | 365 self.EchoHandler] + get_handlers |
366 head_handlers = [ | |
367 self.FileHandler, | |
368 self.DefaultHeadResponseHandler] | |
361 | 369 |
362 self._mime_types = { | 370 self._mime_types = { |
363 'crx' : 'application/x-chrome-extension', | 371 'crx' : 'application/x-chrome-extension', |
364 'exe' : 'application/octet-stream', | 372 'exe' : 'application/octet-stream', |
365 'gif': 'image/gif', | 373 'gif': 'image/gif', |
366 'jpeg' : 'image/jpeg', | 374 'jpeg' : 'image/jpeg', |
367 'jpg' : 'image/jpeg', | 375 'jpg' : 'image/jpeg', |
368 'pdf' : 'application/pdf', | 376 'pdf' : 'application/pdf', |
369 'xml' : 'text/xml' | 377 'xml' : 'text/xml' |
370 } | 378 } |
371 self._default_mime_type = 'text/html' | 379 self._default_mime_type = 'text/html' |
372 | 380 |
373 BasePageHandler.__init__(self, request, client_address, socket_server, | 381 BasePageHandler.__init__(self, request, client_address, socket_server, |
374 connect_handlers, get_handlers, post_handlers, | 382 connect_handlers, get_handlers, head_handlers, |
375 put_handlers) | 383 post_handlers, put_handlers) |
376 | 384 |
377 def GetMIMETypeFromName(self, file_name): | 385 def GetMIMETypeFromName(self, file_name): |
378 """Returns the mime type for the specified file_name. So far it only looks | 386 """Returns the mime type for the specified file_name. So far it only looks |
379 at the file extension.""" | 387 at the file extension.""" |
380 | 388 |
381 (shortname, extension) = os.path.splitext(file_name.split("?")[0]) | 389 (shortname, extension) = os.path.splitext(file_name.split("?")[0]) |
382 if len(extension) == 0: | 390 if len(extension) == 0: |
383 # no extension. | 391 # no extension. |
384 return self._default_mime_type | 392 return self._default_mime_type |
385 | 393 |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
937 data = data[start: end + 1] | 945 data = data[start: end + 1] |
938 else: | 946 else: |
939 self.send_response(200) | 947 self.send_response(200) |
940 | 948 |
941 self.send_header('Content-type', self.GetMIMETypeFromName(file_path)) | 949 self.send_header('Content-type', self.GetMIMETypeFromName(file_path)) |
942 self.send_header('Accept-Ranges', 'bytes') | 950 self.send_header('Accept-Ranges', 'bytes') |
943 self.send_header('Content-Length', len(data)) | 951 self.send_header('Content-Length', len(data)) |
944 self.send_header('ETag', '\'' + file_path + '\'') | 952 self.send_header('ETag', '\'' + file_path + '\'') |
945 self.end_headers() | 953 self.end_headers() |
946 | 954 |
947 self.wfile.write(data) | 955 if (self.command != 'HEAD'): |
956 self.wfile.write(data) | |
948 | 957 |
949 return True | 958 return True |
950 | 959 |
951 def SetCookieHandler(self): | 960 def SetCookieHandler(self): |
952 """This handler just sets a cookie, for testing cookie handling.""" | 961 """This handler just sets a cookie, for testing cookie handling.""" |
953 | 962 |
954 if not self._ShouldHandleRequest("/set-cookie"): | 963 if not self._ShouldHandleRequest("/set-cookie"): |
955 return False | 964 return False |
956 | 965 |
957 query_char = self.path.find('?') | 966 query_char = self.path.find('?') |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1344 return True | 1353 return True |
1345 | 1354 |
1346 def DefaultResponseHandler(self): | 1355 def DefaultResponseHandler(self): |
1347 """This is the catch-all response handler for requests that aren't handled | 1356 """This is the catch-all response handler for requests that aren't handled |
1348 by one of the special handlers above. | 1357 by one of the special handlers above. |
1349 Note that we specify the content-length as without it the https connection | 1358 Note that we specify the content-length as without it the https connection |
1350 is not closed properly (and the browser keeps expecting data).""" | 1359 is not closed properly (and the browser keeps expecting data).""" |
1351 | 1360 |
1352 contents = "Default response given for path: " + self.path | 1361 contents = "Default response given for path: " + self.path |
1353 self.send_response(200) | 1362 self.send_response(200) |
1354 self.send_header('Content-type', 'text/html') | 1363 self.send_header('Content-type', 'text/html') |
wtc
2011/10/31 23:02:51
Nit: capitalize "Type".
mmenke
2011/10/31 23:29:12
Done. Fixed a bunch of other cases of that, too.
| |
1355 self.send_header("Content-Length", len(contents)) | 1364 self.send_header("Content-Length", len(contents)) |
1356 self.end_headers() | 1365 self.end_headers() |
1357 self.wfile.write(contents) | 1366 self.wfile.write(contents) |
1358 return True | 1367 return True |
1359 | 1368 |
1369 def DefaultHeadResponseHandler(self): | |
1370 """This is the catch-all response handler for HEAD requests that aren't | |
1371 handled by one of the special handlers above.""" | |
1372 | |
1373 self.send_response(200) | |
1374 self.send_header('Content-Type', 'text/html') | |
1375 self.send_header('Content-Length', '0') | |
wtc
2011/10/31 23:02:51
An alternative to sending a Content-Length of 0 is
mmenke
2011/10/31 23:29:12
The last suggestion sounds like a good idea to me.
| |
1376 self.end_headers() | |
1377 return True | |
1378 | |
1360 def RedirectConnectHandler(self): | 1379 def RedirectConnectHandler(self): |
1361 """Sends a redirect to the CONNECT request for www.redirect.com. This | 1380 """Sends a redirect to the CONNECT request for www.redirect.com. This |
1362 response is not specified by the RFC, so the browser should not follow | 1381 response is not specified by the RFC, so the browser should not follow |
1363 the redirect.""" | 1382 the redirect.""" |
1364 | 1383 |
1365 if (self.path.find("www.redirect.com") < 0): | 1384 if (self.path.find("www.redirect.com") < 0): |
1366 return False | 1385 return False |
1367 | 1386 |
1368 dest = "http://www.destination.com/foo.js" | 1387 dest = "http://www.destination.com/foo.js" |
1369 | 1388 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1456 self.ChromiumSyncSendNotificationOpHandler, | 1475 self.ChromiumSyncSendNotificationOpHandler, |
1457 self.ChromiumSyncBirthdayErrorOpHandler, | 1476 self.ChromiumSyncBirthdayErrorOpHandler, |
1458 self.ChromiumSyncTransientErrorOpHandler, | 1477 self.ChromiumSyncTransientErrorOpHandler, |
1459 self.ChromiumSyncSyncTabsOpHandler, | 1478 self.ChromiumSyncSyncTabsOpHandler, |
1460 self.ChromiumSyncErrorOpHandler, | 1479 self.ChromiumSyncErrorOpHandler, |
1461 self.ChromiumSyncCredHandler] | 1480 self.ChromiumSyncCredHandler] |
1462 | 1481 |
1463 post_handlers = [self.ChromiumSyncCommandHandler, | 1482 post_handlers = [self.ChromiumSyncCommandHandler, |
1464 self.ChromiumSyncTimeHandler] | 1483 self.ChromiumSyncTimeHandler] |
1465 BasePageHandler.__init__(self, request, client_address, | 1484 BasePageHandler.__init__(self, request, client_address, |
1466 sync_http_server, [], get_handlers, | 1485 sync_http_server, [], get_handlers, [], |
1467 post_handlers, []) | 1486 post_handlers, []) |
1468 | 1487 |
1469 | 1488 |
1470 def ChromiumSyncTimeHandler(self): | 1489 def ChromiumSyncTimeHandler(self): |
1471 """Handle Chromium sync .../time requests. | 1490 """Handle Chromium sync .../time requests. |
1472 | 1491 |
1473 The syncer sometimes checks server reachability by examining /time. | 1492 The syncer sometimes checks server reachability by examining /time. |
1474 """ | 1493 """ |
1475 test_name = "/chromiumsync/time" | 1494 test_name = "/chromiumsync/time" |
1476 if not self._ShouldHandleRequest(test_name): | 1495 if not self._ShouldHandleRequest(test_name): |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1915 'random key if none is specified on the command ' | 1934 'random key if none is specified on the command ' |
1916 'line.') | 1935 'line.') |
1917 option_parser.add_option('', '--policy-user', default='user@example.com', | 1936 option_parser.add_option('', '--policy-user', default='user@example.com', |
1918 dest='policy_user', | 1937 dest='policy_user', |
1919 help='Specify the user name the server should ' | 1938 help='Specify the user name the server should ' |
1920 'report back to the client as the user owning the ' | 1939 'report back to the client as the user owning the ' |
1921 'token used for making the policy request.') | 1940 'token used for making the policy request.') |
1922 options, args = option_parser.parse_args() | 1941 options, args = option_parser.parse_args() |
1923 | 1942 |
1924 sys.exit(main(options, args)) | 1943 sys.exit(main(options, args)) |
OLD | NEW |