| OLD | NEW |
| 1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
| 2 # Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2008 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 server used for testing Chrome. | 6 """This is a simple HTTP 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 It defaults to living on localhost:8888. | 9 It defaults to living on localhost:8888. |
| 10 It can use https if you specify the flag --https=CERT where CERT is the path | 10 It can use https if you specify the flag --https=CERT where CERT is the path |
| 11 to a pem file containing the certificate and private key that should be used. | 11 to a pem file containing the certificate and private key that should be used. |
| 12 To shut it down properly, visit localhost:8888/kill. | 12 To shut it down properly, visit localhost:8888/kill. |
| 13 """ | 13 """ |
| 14 | 14 |
| 15 import base64 | 15 import base64 |
| 16 import BaseHTTPServer | 16 import BaseHTTPServer |
| 17 import cgi | 17 import cgi |
| 18 import optparse | 18 import optparse |
| 19 import os | 19 import os |
| 20 import re | 20 import re |
| 21 import shutil | 21 import shutil |
| 22 import SocketServer | 22 import SocketServer |
| 23 import sys | 23 import sys |
| 24 import time | 24 import time |
| 25 import urllib2 | |
| 26 | |
| 27 import pyftpdlib.ftpserver | |
| 28 import tlslite | 25 import tlslite |
| 29 import tlslite.api | 26 import tlslite.api |
| 30 | 27 import pyftpdlib.ftpserver |
| 31 import chromiumsync | |
| 32 | 28 |
| 33 try: | 29 try: |
| 34 import hashlib | 30 import hashlib |
| 35 _new_md5 = hashlib.md5 | 31 _new_md5 = hashlib.md5 |
| 36 except ImportError: | 32 except ImportError: |
| 37 import md5 | 33 import md5 |
| 38 _new_md5 = md5.new | 34 _new_md5 = md5.new |
| 39 | 35 |
| 40 SERVER_HTTP = 0 | 36 SERVER_HTTP = 0 |
| 41 SERVER_FTP = 1 | 37 SERVER_FTP = 1 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 self.FileHandler, | 118 self.FileHandler, |
| 123 self.RealFileWithCommonHeaderHandler, | 119 self.RealFileWithCommonHeaderHandler, |
| 124 self.RealBZ2FileWithCommonHeaderHandler, | 120 self.RealBZ2FileWithCommonHeaderHandler, |
| 125 self.SetCookieHandler, | 121 self.SetCookieHandler, |
| 126 self.AuthBasicHandler, | 122 self.AuthBasicHandler, |
| 127 self.AuthDigestHandler, | 123 self.AuthDigestHandler, |
| 128 self.SlowServerHandler, | 124 self.SlowServerHandler, |
| 129 self.ContentTypeHandler, | 125 self.ContentTypeHandler, |
| 130 self.ServerRedirectHandler, | 126 self.ServerRedirectHandler, |
| 131 self.ClientRedirectHandler, | 127 self.ClientRedirectHandler, |
| 132 self.ChromiumSyncTimeHandler, | |
| 133 self.MultipartHandler, | 128 self.MultipartHandler, |
| 134 self.DefaultResponseHandler] | 129 self.DefaultResponseHandler] |
| 135 self._post_handlers = [ | 130 self._post_handlers = [ |
| 136 self.WriteFile, | 131 self.WriteFile, |
| 137 self.EchoTitleHandler, | 132 self.EchoTitleHandler, |
| 138 self.EchoAllHandler, | 133 self.EchoAllHandler, |
| 139 self.ChromiumSyncCommandHandler, | |
| 140 self.EchoHandler] + self._get_handlers | 134 self.EchoHandler] + self._get_handlers |
| 141 self._put_handlers = [ | 135 self._put_handlers = [ |
| 142 self.WriteFile, | 136 self.WriteFile, |
| 143 self.EchoTitleHandler, | 137 self.EchoTitleHandler, |
| 144 self.EchoAllHandler, | 138 self.EchoAllHandler, |
| 145 self.EchoHandler] + self._get_handlers | 139 self.EchoHandler] + self._get_handlers |
| 146 | 140 |
| 147 self._mime_types = { | 141 self._mime_types = { |
| 148 'gif': 'image/gif', | 142 'gif': 'image/gif', |
| 149 'jpeg' : 'image/jpeg', | 143 'jpeg' : 'image/jpeg', |
| 150 'jpg' : 'image/jpeg', | 144 'jpg' : 'image/jpeg', |
| 151 'xml' : 'text/xml' | 145 'xml' : 'text/xml' |
| 152 } | 146 } |
| 153 self._default_mime_type = 'text/html' | 147 self._default_mime_type = 'text/html' |
| 154 | 148 |
| 155 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request, | 149 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request, |
| 156 client_address, | 150 client_address, |
| 157 socket_server) | 151 socket_server) |
| 158 # Class variable; shared across requests. | |
| 159 _sync_handler = chromiumsync.TestServer() | |
| 160 | 152 |
| 161 def _ShouldHandleRequest(self, handler_name): | 153 def _ShouldHandleRequest(self, handler_name): |
| 162 """Determines if the path can be handled by the handler. | 154 """Determines if the path can be handled by the handler. |
| 163 | 155 |
| 164 We consider a handler valid if the path begins with the | 156 We consider a handler valid if the path begins with the |
| 165 handler name. It can optionally be followed by "?*", "/*". | 157 handler name. It can optionally be followed by "?*", "/*". |
| 166 """ | 158 """ |
| 167 | 159 |
| 168 pattern = re.compile('%s($|\?|/).*' % handler_name) | 160 pattern = re.compile('%s($|\?|/).*' % handler_name) |
| 169 return pattern.match(self.path) | 161 return pattern.match(self.path) |
| (...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 | 989 |
| 998 self.send_response(200) | 990 self.send_response(200) |
| 999 self.send_header('Content-type', 'text/html') | 991 self.send_header('Content-type', 'text/html') |
| 1000 self.end_headers() | 992 self.end_headers() |
| 1001 self.wfile.write('<html><head>') | 993 self.wfile.write('<html><head>') |
| 1002 self.wfile.write('<meta http-equiv="refresh" content="0;url=%s">' % dest) | 994 self.wfile.write('<meta http-equiv="refresh" content="0;url=%s">' % dest) |
| 1003 self.wfile.write('</head><body>Redirecting to %s</body></html>' % dest) | 995 self.wfile.write('</head><body>Redirecting to %s</body></html>' % dest) |
| 1004 | 996 |
| 1005 return True | 997 return True |
| 1006 | 998 |
| 1007 def ChromiumSyncTimeHandler(self): | |
| 1008 """Handle Chromium sync .../time requests. | |
| 1009 | |
| 1010 The syncer sometimes checks server reachability by examining /time. | |
| 1011 """ | |
| 1012 test_name = "/chromiumsync/time" | |
| 1013 if not self._ShouldHandleRequest(test_name): | |
| 1014 return False | |
| 1015 | |
| 1016 self.send_response(200) | |
| 1017 self.send_header('Content-type', 'text/html') | |
| 1018 self.end_headers() | |
| 1019 return True | |
| 1020 | |
| 1021 def ChromiumSyncCommandHandler(self): | |
| 1022 """Handle a chromiumsync command arriving via http. | |
| 1023 | |
| 1024 This covers all sync protocol commands: authentication, getupdates, and | |
| 1025 commit. | |
| 1026 """ | |
| 1027 test_name = "/chromiumsync/command" | |
| 1028 if not self._ShouldHandleRequest(test_name): | |
| 1029 return False | |
| 1030 | |
| 1031 length = int(self.headers.getheader('content-length')) | |
| 1032 raw_request = self.rfile.read(length) | |
| 1033 | |
| 1034 http_response, raw_reply = self._sync_handler.HandleCommand(raw_request) | |
| 1035 self.send_response(http_response) | |
| 1036 self.end_headers() | |
| 1037 self.wfile.write(raw_reply) | |
| 1038 return True | |
| 1039 | |
| 1040 def MultipartHandler(self): | 999 def MultipartHandler(self): |
| 1041 """Send a multipart response (10 text/html pages).""" | 1000 """Send a multipart response (10 text/html pages).""" |
| 1042 test_name = "/multipart" | 1001 test_name = "/multipart" |
| 1043 if not self._ShouldHandleRequest(test_name): | 1002 if not self._ShouldHandleRequest(test_name): |
| 1044 return False | 1003 return False |
| 1045 | 1004 |
| 1046 num_frames = 10 | 1005 num_frames = 10 |
| 1047 bound = '12345' | 1006 bound = '12345' |
| 1048 self.send_response(200) | 1007 self.send_response(200) |
| 1049 self.send_header('Content-type', | 1008 self.send_header('Content-type', |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1159 def MakeDataDir(): | 1118 def MakeDataDir(): |
| 1160 if options.data_dir: | 1119 if options.data_dir: |
| 1161 if not os.path.isdir(options.data_dir): | 1120 if not os.path.isdir(options.data_dir): |
| 1162 print 'specified data dir not found: ' + options.data_dir + ' exiting...' | 1121 print 'specified data dir not found: ' + options.data_dir + ' exiting...' |
| 1163 return None | 1122 return None |
| 1164 my_data_dir = options.data_dir | 1123 my_data_dir = options.data_dir |
| 1165 else: | 1124 else: |
| 1166 # Create the default path to our data dir, relative to the exe dir. | 1125 # Create the default path to our data dir, relative to the exe dir. |
| 1167 my_data_dir = os.path.dirname(sys.argv[0]) | 1126 my_data_dir = os.path.dirname(sys.argv[0]) |
| 1168 my_data_dir = os.path.join(my_data_dir, "..", "..", "..", "..", | 1127 my_data_dir = os.path.join(my_data_dir, "..", "..", "..", "..", |
| 1169 "test", "data") | 1128 "test", "data") |
| 1170 | 1129 |
| 1171 #TODO(ibrar): Must use Find* funtion defined in google\tools | 1130 #TODO(ibrar): Must use Find* funtion defined in google\tools |
| 1172 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data") | 1131 #i.e my_data_dir = FindUpward(my_data_dir, "test", "data") |
| 1173 | 1132 |
| 1174 return my_data_dir | 1133 return my_data_dir |
| 1175 | 1134 |
| 1176 def TryKillingOldServer(port): | |
| 1177 # Note that an HTTP /kill request to the FTP server has the effect of | |
| 1178 # killing it. | |
| 1179 for protocol in ["http", "https"]: | |
| 1180 try: | |
| 1181 urllib2.urlopen("%s://localhost:%d/kill" % (protocol, port)).read() | |
| 1182 print "Killed old server instance on port %d (via %s)" % (port, protocol) | |
| 1183 except urllib2.URLError: | |
| 1184 # Common case, indicates no server running. | |
| 1185 pass | |
| 1186 | |
| 1187 def main(options, args): | 1135 def main(options, args): |
| 1188 # redirect output to a log file so it doesn't spam the unit test output | 1136 # redirect output to a log file so it doesn't spam the unit test output |
| 1189 logfile = open('testserver.log', 'w') | 1137 logfile = open('testserver.log', 'w') |
| 1190 sys.stderr = sys.stdout = logfile | 1138 sys.stderr = sys.stdout = logfile |
| 1191 | 1139 |
| 1192 port = options.port | 1140 port = options.port |
| 1193 | 1141 |
| 1194 # Try to free up the port if there's an orphaned old instance. | |
| 1195 TryKillingOldServer(port) | |
| 1196 | |
| 1197 if options.server_type == SERVER_HTTP: | 1142 if options.server_type == SERVER_HTTP: |
| 1198 if options.cert: | 1143 if options.cert: |
| 1199 # let's make sure the cert file exists. | 1144 # let's make sure the cert file exists. |
| 1200 if not os.path.isfile(options.cert): | 1145 if not os.path.isfile(options.cert): |
| 1201 print 'specified cert file not found: ' + options.cert + ' exiting...' | 1146 print 'specified cert file not found: ' + options.cert + ' exiting...' |
| 1202 return | 1147 return |
| 1203 if options.forking: | 1148 if options.forking: |
| 1204 server_class = ForkingHTTPSServer | 1149 server_class = ForkingHTTPSServer |
| 1205 else: | 1150 else: |
| 1206 server_class = HTTPSServer | 1151 server_class = HTTPSServer |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 option_parser.add_option('', '--file-root-url', default='/files/', | 1222 option_parser.add_option('', '--file-root-url', default='/files/', |
| 1278 help='Specify a root URL for files served.') | 1223 help='Specify a root URL for files served.') |
| 1279 option_parser.add_option('', '--never-die', default=False, | 1224 option_parser.add_option('', '--never-die', default=False, |
| 1280 action="store_true", | 1225 action="store_true", |
| 1281 help='Prevent the server from dying when visiting ' | 1226 help='Prevent the server from dying when visiting ' |
| 1282 'a /kill URL. Useful for manually running some ' | 1227 'a /kill URL. Useful for manually running some ' |
| 1283 'tests.') | 1228 'tests.') |
| 1284 options, args = option_parser.parse_args() | 1229 options, args = option_parser.parse_args() |
| 1285 | 1230 |
| 1286 sys.exit(main(options, args)) | 1231 sys.exit(main(options, args)) |
| OLD | NEW |