Chromium Code Reviews| 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, post_handlers, put_handlers, |
| 270 head_handlers): | |
|
wtc
2011/10/31 19:21:00
Nit: list 'head_handlers' and 'do_HEAD' in alphabe
mmenke
2011/10/31 20:46:40
Done.
| |
| 270 self._connect_handlers = connect_handlers | 271 self._connect_handlers = connect_handlers |
| 271 self._get_handlers = get_handlers | 272 self._get_handlers = get_handlers |
| 272 self._post_handlers = post_handlers | 273 self._post_handlers = post_handlers |
| 273 self._put_handlers = put_handlers | 274 self._put_handlers = put_handlers |
| 275 self._head_handlers = head_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 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 301 def do_POST(self): | 303 def do_POST(self): |
| 302 for handler in self._post_handlers: | 304 for handler in self._post_handlers: |
| 303 if handler(): | 305 if handler(): |
| 304 return | 306 return |
| 305 | 307 |
| 306 def do_PUT(self): | 308 def do_PUT(self): |
| 307 for handler in self._put_handlers: | 309 for handler in self._put_handlers: |
| 308 if handler(): | 310 if handler(): |
| 309 return | 311 return |
| 310 | 312 |
| 313 def do_HEAD(self): | |
| 314 for handler in self._head_handlers: | |
| 315 if handler(): | |
| 316 return | |
| 317 | |
| 311 | 318 |
| 312 class TestPageHandler(BasePageHandler): | 319 class TestPageHandler(BasePageHandler): |
| 313 | 320 |
| 314 def __init__(self, request, client_address, socket_server): | 321 def __init__(self, request, client_address, socket_server): |
| 315 connect_handlers = [ | 322 connect_handlers = [ |
| 316 self.RedirectConnectHandler, | 323 self.RedirectConnectHandler, |
| 317 self.ServerAuthConnectHandler, | 324 self.ServerAuthConnectHandler, |
| 318 self.DefaultConnectResponseHandler] | 325 self.DefaultConnectResponseHandler] |
| 319 get_handlers = [ | 326 get_handlers = [ |
| 320 self.NoCacheMaxAgeTimeHandler, | 327 self.NoCacheMaxAgeTimeHandler, |
| (...skipping 23 matching lines...) Expand all 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, | |
|
wtc
2011/10/31 19:21:00
Why did you remove self.EchoAllHandler from post_h
mmenke
2011/10/31 20:46:40
It's in get_handlers already, so there's no reason
| |
| 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, post_handlers, |
| 375 put_handlers) | 383 put_handlers, head_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 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 887 entries = sub_path.split('/') | 895 entries = sub_path.split('/') |
| 888 file_path = os.path.join(self.server.data_dir, *entries) | 896 file_path = os.path.join(self.server.data_dir, *entries) |
| 889 if os.path.isdir(file_path): | 897 if os.path.isdir(file_path): |
| 890 file_path = os.path.join(file_path, 'index.html') | 898 file_path = os.path.join(file_path, 'index.html') |
| 891 | 899 |
| 892 if not os.path.isfile(file_path): | 900 if not os.path.isfile(file_path): |
| 893 print "File not found " + sub_path + " full path:" + file_path | 901 print "File not found " + sub_path + " full path:" + file_path |
| 894 self.send_error(404) | 902 self.send_error(404) |
| 895 return True | 903 return True |
| 896 | 904 |
| 897 f = open(file_path, "rb") | 905 data = ''; |
| 898 data = f.read() | 906 if (self.command != 'HEAD'): |
| 899 f.close() | 907 f = open(file_path, "rb") |
| 908 data = f.read() | |
| 909 f.close() | |
| 900 | 910 |
| 901 data = self._ReplaceFileData(data, query) | 911 data = self._ReplaceFileData(data, query) |
|
wtc
2011/10/31 19:21:00
Just wanted to confirm that this statement should
mmenke
2011/10/31 20:46:40
It didn't matter, either way. Removed the if stat
| |
| 902 | 912 |
| 903 # If file.mock-http-headers exists, it contains the headers we | 913 # If file.mock-http-headers exists, it contains the headers we |
| 904 # should send. Read them in and parse them. | 914 # should send. Read them in and parse them. |
| 905 headers_path = file_path + '.mock-http-headers' | 915 headers_path = file_path + '.mock-http-headers' |
| 906 if os.path.isfile(headers_path): | 916 if os.path.isfile(headers_path): |
| 907 f = open(headers_path, "r") | 917 f = open(headers_path, "r") |
| 908 | 918 |
| 909 # "HTTP/1.1 200 OK" | 919 # "HTTP/1.1 200 OK" |
| 910 response = f.readline() | 920 response = f.readline() |
| 911 status_code = re.findall('HTTP/\d+.\d+ (\d+)', response)[0] | 921 status_code = re.findall('HTTP/\d+.\d+ (\d+)', response)[0] |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 933 self.send_response(206) | 943 self.send_response(206) |
| 934 content_range = 'bytes ' + str(start) + '-' + str(end) + '/' + \ | 944 content_range = 'bytes ' + str(start) + '-' + str(end) + '/' + \ |
| 935 str(len(data)) | 945 str(len(data)) |
| 936 self.send_header('Content-Range', content_range) | 946 self.send_header('Content-Range', content_range) |
| 937 data = data[start: end + 1] | 947 data = data[start: end + 1] |
| 938 else: | 948 else: |
| 939 self.send_response(200) | 949 self.send_response(200) |
| 940 | 950 |
| 941 self.send_header('Content-type', self.GetMIMETypeFromName(file_path)) | 951 self.send_header('Content-type', self.GetMIMETypeFromName(file_path)) |
| 942 self.send_header('Accept-Ranges', 'bytes') | 952 self.send_header('Accept-Ranges', 'bytes') |
| 943 self.send_header('Content-Length', len(data)) | 953 if (self.command != 'HEAD'): |
| 954 self.send_header('Content-Length', len(data)) | |
|
wtc
2011/10/31 19:21:00
Just curious: are HEAD responses forbidden to have
wtc
2011/10/31 19:59:41
julian.reschke: thank you for the reply.
mmenke:
mmenke
2011/10/31 20:46:40
Done. You're right. I misread the RFC.
| |
| 944 self.send_header('ETag', '\'' + file_path + '\'') | 955 self.send_header('ETag', '\'' + file_path + '\'') |
| 945 self.end_headers() | 956 self.end_headers() |
| 946 | 957 |
| 947 self.wfile.write(data) | 958 self.wfile.write(data) |
| 948 | 959 |
| 949 return True | 960 return True |
| 950 | 961 |
| 951 def SetCookieHandler(self): | 962 def SetCookieHandler(self): |
| 952 """This handler just sets a cookie, for testing cookie handling.""" | 963 """This handler just sets a cookie, for testing cookie handling.""" |
| 953 | 964 |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1350 is not closed properly (and the browser keeps expecting data).""" | 1361 is not closed properly (and the browser keeps expecting data).""" |
| 1351 | 1362 |
| 1352 contents = "Default response given for path: " + self.path | 1363 contents = "Default response given for path: " + self.path |
| 1353 self.send_response(200) | 1364 self.send_response(200) |
| 1354 self.send_header('Content-type', 'text/html') | 1365 self.send_header('Content-type', 'text/html') |
| 1355 self.send_header("Content-Length", len(contents)) | 1366 self.send_header("Content-Length", len(contents)) |
| 1356 self.end_headers() | 1367 self.end_headers() |
| 1357 self.wfile.write(contents) | 1368 self.wfile.write(contents) |
| 1358 return True | 1369 return True |
| 1359 | 1370 |
| 1371 def DefaultHeadResponseHandler(self): | |
| 1372 """This is the catch-all response handler for head requests that aren't | |
|
wtc
2011/10/31 19:21:00
Capitalize "HEAD".
mmenke
2011/10/31 20:46:40
Done.
| |
| 1373 handled by one of the special handlers above.""" | |
| 1374 | |
| 1375 self.send_response(200) | |
| 1376 self.send_header('Content-type', 'text/html') | |
|
wtc
2011/10/31 19:21:00
Since there is no |contents|, it seems that we sho
mmenke
2011/10/31 20:46:40
Not done (As per spec - "The Content-Type entity-h
mmenke
2011/10/31 20:49:25
On second thought, you're right, with a 0 content-
mmenke
2011/10/31 20:52:14
Or maybe not? Honestly, I have no idea. Suppose
| |
| 1377 self.end_headers() | |
| 1378 return True | |
| 1379 | |
| 1360 def RedirectConnectHandler(self): | 1380 def RedirectConnectHandler(self): |
| 1361 """Sends a redirect to the CONNECT request for www.redirect.com. This | 1381 """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 | 1382 response is not specified by the RFC, so the browser should not follow |
| 1363 the redirect.""" | 1383 the redirect.""" |
| 1364 | 1384 |
| 1365 if (self.path.find("www.redirect.com") < 0): | 1385 if (self.path.find("www.redirect.com") < 0): |
| 1366 return False | 1386 return False |
| 1367 | 1387 |
| 1368 dest = "http://www.destination.com/foo.js" | 1388 dest = "http://www.destination.com/foo.js" |
| 1369 | 1389 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1457 self.ChromiumSyncBirthdayErrorOpHandler, | 1477 self.ChromiumSyncBirthdayErrorOpHandler, |
| 1458 self.ChromiumSyncTransientErrorOpHandler, | 1478 self.ChromiumSyncTransientErrorOpHandler, |
| 1459 self.ChromiumSyncSyncTabsOpHandler, | 1479 self.ChromiumSyncSyncTabsOpHandler, |
| 1460 self.ChromiumSyncErrorOpHandler, | 1480 self.ChromiumSyncErrorOpHandler, |
| 1461 self.ChromiumSyncCredHandler] | 1481 self.ChromiumSyncCredHandler] |
| 1462 | 1482 |
| 1463 post_handlers = [self.ChromiumSyncCommandHandler, | 1483 post_handlers = [self.ChromiumSyncCommandHandler, |
| 1464 self.ChromiumSyncTimeHandler] | 1484 self.ChromiumSyncTimeHandler] |
| 1465 BasePageHandler.__init__(self, request, client_address, | 1485 BasePageHandler.__init__(self, request, client_address, |
| 1466 sync_http_server, [], get_handlers, | 1486 sync_http_server, [], get_handlers, |
| 1467 post_handlers, []) | 1487 post_handlers, [], []) |
| 1468 | 1488 |
| 1469 | 1489 |
| 1470 def ChromiumSyncTimeHandler(self): | 1490 def ChromiumSyncTimeHandler(self): |
| 1471 """Handle Chromium sync .../time requests. | 1491 """Handle Chromium sync .../time requests. |
| 1472 | 1492 |
| 1473 The syncer sometimes checks server reachability by examining /time. | 1493 The syncer sometimes checks server reachability by examining /time. |
| 1474 """ | 1494 """ |
| 1475 test_name = "/chromiumsync/time" | 1495 test_name = "/chromiumsync/time" |
| 1476 if not self._ShouldHandleRequest(test_name): | 1496 if not self._ShouldHandleRequest(test_name): |
| 1477 return False | 1497 return False |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1915 'random key if none is specified on the command ' | 1935 'random key if none is specified on the command ' |
| 1916 'line.') | 1936 'line.') |
| 1917 option_parser.add_option('', '--policy-user', default='user@example.com', | 1937 option_parser.add_option('', '--policy-user', default='user@example.com', |
| 1918 dest='policy_user', | 1938 dest='policy_user', |
| 1919 help='Specify the user name the server should ' | 1939 help='Specify the user name the server should ' |
| 1920 'report back to the client as the user owning the ' | 1940 'report back to the client as the user owning the ' |
| 1921 'token used for making the policy request.') | 1941 'token used for making the policy request.') |
| 1922 options, args = option_parser.parse_args() | 1942 options, args = option_parser.parse_args() |
| 1923 | 1943 |
| 1924 sys.exit(main(options, args)) | 1944 sys.exit(main(options, args)) |
| OLD | NEW |