Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: net/tools/testserver/testserver.py

Issue 8418024: Don't convert HEAD requests to GETs on 303 redirects. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Response to comments Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | net/url_request/url_request.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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))
OLDNEW
« no previous file with comments | « no previous file | net/url_request/url_request.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698