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 """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 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 self.AuthDigestHandler, | 371 self.AuthDigestHandler, |
372 self.SlowServerHandler, | 372 self.SlowServerHandler, |
373 self.ChunkedServerHandler, | 373 self.ChunkedServerHandler, |
374 self.ContentTypeHandler, | 374 self.ContentTypeHandler, |
375 self.NoContentHandler, | 375 self.NoContentHandler, |
376 self.ServerRedirectHandler, | 376 self.ServerRedirectHandler, |
377 self.ClientRedirectHandler, | 377 self.ClientRedirectHandler, |
378 self.MultipartHandler, | 378 self.MultipartHandler, |
379 self.MultipartSlowHandler, | 379 self.MultipartSlowHandler, |
380 self.GetSSLSessionCacheHandler, | 380 self.GetSSLSessionCacheHandler, |
| 381 self.CloseSocketHandler, |
381 self.DefaultResponseHandler] | 382 self.DefaultResponseHandler] |
382 post_handlers = [ | 383 post_handlers = [ |
383 self.EchoTitleHandler, | 384 self.EchoTitleHandler, |
384 self.EchoHandler, | 385 self.EchoHandler, |
385 self.DeviceManagementHandler, | 386 self.DeviceManagementHandler, |
386 self.PostOnlyFileHandler] + get_handlers | 387 self.PostOnlyFileHandler] + get_handlers |
387 put_handlers = [ | 388 put_handlers = [ |
388 self.EchoTitleHandler, | 389 self.EchoTitleHandler, |
389 self.EchoHandler] + get_handlers | 390 self.EchoHandler] + get_handlers |
390 head_handlers = [ | 391 head_handlers = [ |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 | 916 |
916 def PostOnlyFileHandler(self): | 917 def PostOnlyFileHandler(self): |
917 """This handler sends the contents of the requested file on a POST.""" | 918 """This handler sends the contents of the requested file on a POST.""" |
918 prefix = urlparse.urljoin(self.server.file_root_url, 'post/') | 919 prefix = urlparse.urljoin(self.server.file_root_url, 'post/') |
919 if not self.path.startswith(prefix): | 920 if not self.path.startswith(prefix): |
920 return False | 921 return False |
921 self.ReadRequestBody() | 922 self.ReadRequestBody() |
922 return self._FileHandlerHelper(prefix) | 923 return self._FileHandlerHelper(prefix) |
923 | 924 |
924 def _FileHandlerHelper(self, prefix): | 925 def _FileHandlerHelper(self, prefix): |
| 926 old_protocol_version = self.protocol_version |
925 _, _, url_path, _, query, _ = urlparse.urlparse(self.path) | 927 _, _, url_path, _, query, _ = urlparse.urlparse(self.path) |
926 sub_path = url_path[len(prefix):] | 928 sub_path = url_path[len(prefix):] |
927 entries = sub_path.split('/') | 929 entries = sub_path.split('/') |
928 file_path = os.path.join(self.server.data_dir, *entries) | 930 file_path = os.path.join(self.server.data_dir, *entries) |
929 if os.path.isdir(file_path): | 931 if os.path.isdir(file_path): |
930 file_path = os.path.join(file_path, 'index.html') | 932 file_path = os.path.join(file_path, 'index.html') |
931 | 933 |
932 if not os.path.isfile(file_path): | 934 if not os.path.isfile(file_path): |
933 print "File not found " + sub_path + " full path:" + file_path | 935 print "File not found " + sub_path + " full path:" + file_path |
934 self.send_error(404) | 936 self.send_error(404) |
935 return True | 937 return True |
936 | 938 |
937 f = open(file_path, "rb") | 939 f = open(file_path, "rb") |
938 data = f.read() | 940 data = f.read() |
939 f.close() | 941 f.close() |
940 | 942 |
941 data = self._ReplaceFileData(data, query) | 943 data = self._ReplaceFileData(data, query) |
942 | 944 |
943 # If file.mock-http-headers exists, it contains the headers we | 945 # If file.mock-http-headers exists, it contains the headers we |
944 # should send. Read them in and parse them. | 946 # should send. Read them in and parse them. |
945 headers_path = file_path + '.mock-http-headers' | 947 headers_path = file_path + '.mock-http-headers' |
946 if os.path.isfile(headers_path): | 948 if os.path.isfile(headers_path): |
947 f = open(headers_path, "r") | 949 f = open(headers_path, "r") |
948 | 950 |
949 # "HTTP/1.1 200 OK" | 951 # "HTTP/1.1 200 OK" |
950 response = f.readline() | 952 response = f.readline() |
951 status_code = re.findall('HTTP/\d+.\d+ (\d+)', response)[0] | 953 http_major, http_minor, status_code = re.findall( |
| 954 'HTTP/(\d+).(\d+) (\d+)', response)[0] |
| 955 self.protocol_version = "HTTP/%s.%s" % (http_major, http_minor) |
952 self.send_response(int(status_code)) | 956 self.send_response(int(status_code)) |
953 | 957 |
954 for line in f: | 958 for line in f: |
955 header_values = re.findall('(\S+):\s*(.*)', line) | 959 header_values = re.findall('(\S+):\s*(.*)', line) |
956 if len(header_values) > 0: | 960 if len(header_values) > 0: |
957 # "name: value" | 961 # "name: value" |
958 name, value = header_values[0] | 962 name, value = header_values[0] |
959 self.send_header(name, value) | 963 self.send_header(name, value) |
960 f.close() | 964 f.close() |
961 else: | 965 else: |
(...skipping 21 matching lines...) Expand all Loading... |
983 | 987 |
984 self.send_header('Content-Type', self.GetMIMETypeFromName(file_path)) | 988 self.send_header('Content-Type', self.GetMIMETypeFromName(file_path)) |
985 self.send_header('Accept-Ranges', 'bytes') | 989 self.send_header('Accept-Ranges', 'bytes') |
986 self.send_header('Content-Length', len(data)) | 990 self.send_header('Content-Length', len(data)) |
987 self.send_header('ETag', '\'' + file_path + '\'') | 991 self.send_header('ETag', '\'' + file_path + '\'') |
988 self.end_headers() | 992 self.end_headers() |
989 | 993 |
990 if (self.command != 'HEAD'): | 994 if (self.command != 'HEAD'): |
991 self.wfile.write(data) | 995 self.wfile.write(data) |
992 | 996 |
| 997 self.protocol_version = old_protocol_version |
993 return True | 998 return True |
994 | 999 |
995 def SetCookieHandler(self): | 1000 def SetCookieHandler(self): |
996 """This handler just sets a cookie, for testing cookie handling.""" | 1001 """This handler just sets a cookie, for testing cookie handling.""" |
997 | 1002 |
998 if not self._ShouldHandleRequest("/set-cookie"): | 1003 if not self._ShouldHandleRequest("/set-cookie"): |
999 return False | 1004 return False |
1000 | 1005 |
1001 query_char = self.path.find('?') | 1006 query_char = self.path.find('?') |
1002 if query_char != -1: | 1007 if query_char != -1: |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1420 self.send_header('Content-Type', 'text/plain') | 1425 self.send_header('Content-Type', 'text/plain') |
1421 self.end_headers() | 1426 self.end_headers() |
1422 try: | 1427 try: |
1423 for (action, sessionID) in self.server.session_cache.log: | 1428 for (action, sessionID) in self.server.session_cache.log: |
1424 self.wfile.write('%s\t%s\n' % (action, sessionID.encode('hex'))) | 1429 self.wfile.write('%s\t%s\n' % (action, sessionID.encode('hex'))) |
1425 except AttributeError, e: | 1430 except AttributeError, e: |
1426 self.wfile.write('Pass --https-record-resume in order to use' + | 1431 self.wfile.write('Pass --https-record-resume in order to use' + |
1427 ' this request') | 1432 ' this request') |
1428 return True | 1433 return True |
1429 | 1434 |
| 1435 def CloseSocketHandler(self): |
| 1436 """Closes the socket without sending anything.""" |
| 1437 |
| 1438 if not self._ShouldHandleRequest('/close-socket'): |
| 1439 return False |
| 1440 |
| 1441 self.wfile.close() |
| 1442 return True |
| 1443 |
1430 def DefaultResponseHandler(self): | 1444 def DefaultResponseHandler(self): |
1431 """This is the catch-all response handler for requests that aren't handled | 1445 """This is the catch-all response handler for requests that aren't handled |
1432 by one of the special handlers above. | 1446 by one of the special handlers above. |
1433 Note that we specify the content-length as without it the https connection | 1447 Note that we specify the content-length as without it the https connection |
1434 is not closed properly (and the browser keeps expecting data).""" | 1448 is not closed properly (and the browser keeps expecting data).""" |
1435 | 1449 |
1436 contents = "Default response given for path: " + self.path | 1450 contents = "Default response given for path: " + self.path |
1437 self.send_response(200) | 1451 self.send_response(200) |
1438 self.send_header('Content-Type', 'text/html') | 1452 self.send_header('Content-Type', 'text/html') |
1439 self.send_header('Content-Length', len(contents)) | 1453 self.send_header('Content-Length', len(contents)) |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2005 'random key if none is specified on the command ' | 2019 'random key if none is specified on the command ' |
2006 'line.') | 2020 'line.') |
2007 option_parser.add_option('', '--policy-user', default='user@example.com', | 2021 option_parser.add_option('', '--policy-user', default='user@example.com', |
2008 dest='policy_user', | 2022 dest='policy_user', |
2009 help='Specify the user name the server should ' | 2023 help='Specify the user name the server should ' |
2010 'report back to the client as the user owning the ' | 2024 'report back to the client as the user owning the ' |
2011 'token used for making the policy request.') | 2025 'token used for making the policy request.') |
2012 options, args = option_parser.parse_args() | 2026 options, args = option_parser.parse_args() |
2013 | 2027 |
2014 sys.exit(main(options, args)) | 2028 sys.exit(main(options, args)) |
OLD | NEW |