| 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.DefaultResponseHandler] |
| 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 |
| 386 # extension starts with a dot, so we need to remove it | 394 # extension starts with a dot, so we need to remove it |
| 387 return self._mime_types.get(extension[1:], self._default_mime_type) | 395 return self._mime_types.get(extension[1:], self._default_mime_type) |
| 388 | 396 |
| 389 def NoCacheMaxAgeTimeHandler(self): | 397 def NoCacheMaxAgeTimeHandler(self): |
| 390 """This request handler yields a page with the title set to the current | 398 """This request handler yields a page with the title set to the current |
| 391 system time, and no caching requested.""" | 399 system time, and no caching requested.""" |
| 392 | 400 |
| 393 if not self._ShouldHandleRequest("/nocachetime/maxage"): | 401 if not self._ShouldHandleRequest("/nocachetime/maxage"): |
| 394 return False | 402 return False |
| 395 | 403 |
| 396 self.send_response(200) | 404 self.send_response(200) |
| 397 self.send_header('Cache-Control', 'max-age=0') | 405 self.send_header('Cache-Control', 'max-age=0') |
| 398 self.send_header('Content-type', 'text/html') | 406 self.send_header('Content-Type', 'text/html') |
| 399 self.end_headers() | 407 self.end_headers() |
| 400 | 408 |
| 401 self.wfile.write('<html><head><title>%s</title></head></html>' % | 409 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 402 time.time()) | 410 time.time()) |
| 403 | 411 |
| 404 return True | 412 return True |
| 405 | 413 |
| 406 def NoCacheTimeHandler(self): | 414 def NoCacheTimeHandler(self): |
| 407 """This request handler yields a page with the title set to the current | 415 """This request handler yields a page with the title set to the current |
| 408 system time, and no caching requested.""" | 416 system time, and no caching requested.""" |
| 409 | 417 |
| 410 if not self._ShouldHandleRequest("/nocachetime"): | 418 if not self._ShouldHandleRequest("/nocachetime"): |
| 411 return False | 419 return False |
| 412 | 420 |
| 413 self.send_response(200) | 421 self.send_response(200) |
| 414 self.send_header('Cache-Control', 'no-cache') | 422 self.send_header('Cache-Control', 'no-cache') |
| 415 self.send_header('Content-type', 'text/html') | 423 self.send_header('Content-Type', 'text/html') |
| 416 self.end_headers() | 424 self.end_headers() |
| 417 | 425 |
| 418 self.wfile.write('<html><head><title>%s</title></head></html>' % | 426 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 419 time.time()) | 427 time.time()) |
| 420 | 428 |
| 421 return True | 429 return True |
| 422 | 430 |
| 423 def CacheTimeHandler(self): | 431 def CacheTimeHandler(self): |
| 424 """This request handler yields a page with the title set to the current | 432 """This request handler yields a page with the title set to the current |
| 425 system time, and allows caching for one minute.""" | 433 system time, and allows caching for one minute.""" |
| 426 | 434 |
| 427 if not self._ShouldHandleRequest("/cachetime"): | 435 if not self._ShouldHandleRequest("/cachetime"): |
| 428 return False | 436 return False |
| 429 | 437 |
| 430 self.send_response(200) | 438 self.send_response(200) |
| 431 self.send_header('Cache-Control', 'max-age=60') | 439 self.send_header('Cache-Control', 'max-age=60') |
| 432 self.send_header('Content-type', 'text/html') | 440 self.send_header('Content-Type', 'text/html') |
| 433 self.end_headers() | 441 self.end_headers() |
| 434 | 442 |
| 435 self.wfile.write('<html><head><title>%s</title></head></html>' % | 443 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 436 time.time()) | 444 time.time()) |
| 437 | 445 |
| 438 return True | 446 return True |
| 439 | 447 |
| 440 def CacheExpiresHandler(self): | 448 def CacheExpiresHandler(self): |
| 441 """This request handler yields a page with the title set to the current | 449 """This request handler yields a page with the title set to the current |
| 442 system time, and set the page to expire on 1 Jan 2099.""" | 450 system time, and set the page to expire on 1 Jan 2099.""" |
| 443 | 451 |
| 444 if not self._ShouldHandleRequest("/cache/expires"): | 452 if not self._ShouldHandleRequest("/cache/expires"): |
| 445 return False | 453 return False |
| 446 | 454 |
| 447 self.send_response(200) | 455 self.send_response(200) |
| 448 self.send_header('Expires', 'Thu, 1 Jan 2099 00:00:00 GMT') | 456 self.send_header('Expires', 'Thu, 1 Jan 2099 00:00:00 GMT') |
| 449 self.send_header('Content-type', 'text/html') | 457 self.send_header('Content-Type', 'text/html') |
| 450 self.end_headers() | 458 self.end_headers() |
| 451 | 459 |
| 452 self.wfile.write('<html><head><title>%s</title></head></html>' % | 460 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 453 time.time()) | 461 time.time()) |
| 454 | 462 |
| 455 return True | 463 return True |
| 456 | 464 |
| 457 def CacheProxyRevalidateHandler(self): | 465 def CacheProxyRevalidateHandler(self): |
| 458 """This request handler yields a page with the title set to the current | 466 """This request handler yields a page with the title set to the current |
| 459 system time, and allows caching for 60 seconds""" | 467 system time, and allows caching for 60 seconds""" |
| 460 | 468 |
| 461 if not self._ShouldHandleRequest("/cache/proxy-revalidate"): | 469 if not self._ShouldHandleRequest("/cache/proxy-revalidate"): |
| 462 return False | 470 return False |
| 463 | 471 |
| 464 self.send_response(200) | 472 self.send_response(200) |
| 465 self.send_header('Content-type', 'text/html') | 473 self.send_header('Content-Type', 'text/html') |
| 466 self.send_header('Cache-Control', 'max-age=60, proxy-revalidate') | 474 self.send_header('Cache-Control', 'max-age=60, proxy-revalidate') |
| 467 self.end_headers() | 475 self.end_headers() |
| 468 | 476 |
| 469 self.wfile.write('<html><head><title>%s</title></head></html>' % | 477 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 470 time.time()) | 478 time.time()) |
| 471 | 479 |
| 472 return True | 480 return True |
| 473 | 481 |
| 474 def CachePrivateHandler(self): | 482 def CachePrivateHandler(self): |
| 475 """This request handler yields a page with the title set to the current | 483 """This request handler yields a page with the title set to the current |
| 476 system time, and allows caching for 5 seconds.""" | 484 system time, and allows caching for 5 seconds.""" |
| 477 | 485 |
| 478 if not self._ShouldHandleRequest("/cache/private"): | 486 if not self._ShouldHandleRequest("/cache/private"): |
| 479 return False | 487 return False |
| 480 | 488 |
| 481 self.send_response(200) | 489 self.send_response(200) |
| 482 self.send_header('Content-type', 'text/html') | 490 self.send_header('Content-Type', 'text/html') |
| 483 self.send_header('Cache-Control', 'max-age=3, private') | 491 self.send_header('Cache-Control', 'max-age=3, private') |
| 484 self.end_headers() | 492 self.end_headers() |
| 485 | 493 |
| 486 self.wfile.write('<html><head><title>%s</title></head></html>' % | 494 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 487 time.time()) | 495 time.time()) |
| 488 | 496 |
| 489 return True | 497 return True |
| 490 | 498 |
| 491 def CachePublicHandler(self): | 499 def CachePublicHandler(self): |
| 492 """This request handler yields a page with the title set to the current | 500 """This request handler yields a page with the title set to the current |
| 493 system time, and allows caching for 5 seconds.""" | 501 system time, and allows caching for 5 seconds.""" |
| 494 | 502 |
| 495 if not self._ShouldHandleRequest("/cache/public"): | 503 if not self._ShouldHandleRequest("/cache/public"): |
| 496 return False | 504 return False |
| 497 | 505 |
| 498 self.send_response(200) | 506 self.send_response(200) |
| 499 self.send_header('Content-type', 'text/html') | 507 self.send_header('Content-Type', 'text/html') |
| 500 self.send_header('Cache-Control', 'max-age=3, public') | 508 self.send_header('Cache-Control', 'max-age=3, public') |
| 501 self.end_headers() | 509 self.end_headers() |
| 502 | 510 |
| 503 self.wfile.write('<html><head><title>%s</title></head></html>' % | 511 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 504 time.time()) | 512 time.time()) |
| 505 | 513 |
| 506 return True | 514 return True |
| 507 | 515 |
| 508 def CacheSMaxAgeHandler(self): | 516 def CacheSMaxAgeHandler(self): |
| 509 """This request handler yields a page with the title set to the current | 517 """This request handler yields a page with the title set to the current |
| 510 system time, and does not allow for caching.""" | 518 system time, and does not allow for caching.""" |
| 511 | 519 |
| 512 if not self._ShouldHandleRequest("/cache/s-maxage"): | 520 if not self._ShouldHandleRequest("/cache/s-maxage"): |
| 513 return False | 521 return False |
| 514 | 522 |
| 515 self.send_response(200) | 523 self.send_response(200) |
| 516 self.send_header('Content-type', 'text/html') | 524 self.send_header('Content-Type', 'text/html') |
| 517 self.send_header('Cache-Control', 'public, s-maxage = 60, max-age = 0') | 525 self.send_header('Cache-Control', 'public, s-maxage = 60, max-age = 0') |
| 518 self.end_headers() | 526 self.end_headers() |
| 519 | 527 |
| 520 self.wfile.write('<html><head><title>%s</title></head></html>' % | 528 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 521 time.time()) | 529 time.time()) |
| 522 | 530 |
| 523 return True | 531 return True |
| 524 | 532 |
| 525 def CacheMustRevalidateHandler(self): | 533 def CacheMustRevalidateHandler(self): |
| 526 """This request handler yields a page with the title set to the current | 534 """This request handler yields a page with the title set to the current |
| 527 system time, and does not allow caching.""" | 535 system time, and does not allow caching.""" |
| 528 | 536 |
| 529 if not self._ShouldHandleRequest("/cache/must-revalidate"): | 537 if not self._ShouldHandleRequest("/cache/must-revalidate"): |
| 530 return False | 538 return False |
| 531 | 539 |
| 532 self.send_response(200) | 540 self.send_response(200) |
| 533 self.send_header('Content-type', 'text/html') | 541 self.send_header('Content-Type', 'text/html') |
| 534 self.send_header('Cache-Control', 'must-revalidate') | 542 self.send_header('Cache-Control', 'must-revalidate') |
| 535 self.end_headers() | 543 self.end_headers() |
| 536 | 544 |
| 537 self.wfile.write('<html><head><title>%s</title></head></html>' % | 545 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 538 time.time()) | 546 time.time()) |
| 539 | 547 |
| 540 return True | 548 return True |
| 541 | 549 |
| 542 def CacheMustRevalidateMaxAgeHandler(self): | 550 def CacheMustRevalidateMaxAgeHandler(self): |
| 543 """This request handler yields a page with the title set to the current | 551 """This request handler yields a page with the title set to the current |
| 544 system time, and does not allow caching event though max-age of 60 | 552 system time, and does not allow caching event though max-age of 60 |
| 545 seconds is specified.""" | 553 seconds is specified.""" |
| 546 | 554 |
| 547 if not self._ShouldHandleRequest("/cache/must-revalidate/max-age"): | 555 if not self._ShouldHandleRequest("/cache/must-revalidate/max-age"): |
| 548 return False | 556 return False |
| 549 | 557 |
| 550 self.send_response(200) | 558 self.send_response(200) |
| 551 self.send_header('Content-type', 'text/html') | 559 self.send_header('Content-Type', 'text/html') |
| 552 self.send_header('Cache-Control', 'max-age=60, must-revalidate') | 560 self.send_header('Cache-Control', 'max-age=60, must-revalidate') |
| 553 self.end_headers() | 561 self.end_headers() |
| 554 | 562 |
| 555 self.wfile.write('<html><head><title>%s</title></head></html>' % | 563 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 556 time.time()) | 564 time.time()) |
| 557 | 565 |
| 558 return True | 566 return True |
| 559 | 567 |
| 560 def CacheNoStoreHandler(self): | 568 def CacheNoStoreHandler(self): |
| 561 """This request handler yields a page with the title set to the current | 569 """This request handler yields a page with the title set to the current |
| 562 system time, and does not allow the page to be stored.""" | 570 system time, and does not allow the page to be stored.""" |
| 563 | 571 |
| 564 if not self._ShouldHandleRequest("/cache/no-store"): | 572 if not self._ShouldHandleRequest("/cache/no-store"): |
| 565 return False | 573 return False |
| 566 | 574 |
| 567 self.send_response(200) | 575 self.send_response(200) |
| 568 self.send_header('Content-type', 'text/html') | 576 self.send_header('Content-Type', 'text/html') |
| 569 self.send_header('Cache-Control', 'no-store') | 577 self.send_header('Cache-Control', 'no-store') |
| 570 self.end_headers() | 578 self.end_headers() |
| 571 | 579 |
| 572 self.wfile.write('<html><head><title>%s</title></head></html>' % | 580 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 573 time.time()) | 581 time.time()) |
| 574 | 582 |
| 575 return True | 583 return True |
| 576 | 584 |
| 577 def CacheNoStoreMaxAgeHandler(self): | 585 def CacheNoStoreMaxAgeHandler(self): |
| 578 """This request handler yields a page with the title set to the current | 586 """This request handler yields a page with the title set to the current |
| 579 system time, and does not allow the page to be stored even though max-age | 587 system time, and does not allow the page to be stored even though max-age |
| 580 of 60 seconds is specified.""" | 588 of 60 seconds is specified.""" |
| 581 | 589 |
| 582 if not self._ShouldHandleRequest("/cache/no-store/max-age"): | 590 if not self._ShouldHandleRequest("/cache/no-store/max-age"): |
| 583 return False | 591 return False |
| 584 | 592 |
| 585 self.send_response(200) | 593 self.send_response(200) |
| 586 self.send_header('Content-type', 'text/html') | 594 self.send_header('Content-Type', 'text/html') |
| 587 self.send_header('Cache-Control', 'max-age=60, no-store') | 595 self.send_header('Cache-Control', 'max-age=60, no-store') |
| 588 self.end_headers() | 596 self.end_headers() |
| 589 | 597 |
| 590 self.wfile.write('<html><head><title>%s</title></head></html>' % | 598 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 591 time.time()) | 599 time.time()) |
| 592 | 600 |
| 593 return True | 601 return True |
| 594 | 602 |
| 595 | 603 |
| 596 def CacheNoTransformHandler(self): | 604 def CacheNoTransformHandler(self): |
| 597 """This request handler yields a page with the title set to the current | 605 """This request handler yields a page with the title set to the current |
| 598 system time, and does not allow the content to transformed during | 606 system time, and does not allow the content to transformed during |
| 599 user-agent caching""" | 607 user-agent caching""" |
| 600 | 608 |
| 601 if not self._ShouldHandleRequest("/cache/no-transform"): | 609 if not self._ShouldHandleRequest("/cache/no-transform"): |
| 602 return False | 610 return False |
| 603 | 611 |
| 604 self.send_response(200) | 612 self.send_response(200) |
| 605 self.send_header('Content-type', 'text/html') | 613 self.send_header('Content-Type', 'text/html') |
| 606 self.send_header('Cache-Control', 'no-transform') | 614 self.send_header('Cache-Control', 'no-transform') |
| 607 self.end_headers() | 615 self.end_headers() |
| 608 | 616 |
| 609 self.wfile.write('<html><head><title>%s</title></head></html>' % | 617 self.wfile.write('<html><head><title>%s</title></head></html>' % |
| 610 time.time()) | 618 time.time()) |
| 611 | 619 |
| 612 return True | 620 return True |
| 613 | 621 |
| 614 def EchoHeader(self): | 622 def EchoHeader(self): |
| 615 """This handler echoes back the value of a specific request header.""" | 623 """This handler echoes back the value of a specific request header.""" |
| 616 return self.EchoHeaderHelper("/echoheader") | 624 return self.EchoHeaderHelper("/echoheader") |
| 617 | 625 |
| 618 """This function echoes back the value of a specific request header""" | 626 """This function echoes back the value of a specific request header""" |
| 619 """while allowing caching for 16 hours.""" | 627 """while allowing caching for 16 hours.""" |
| 620 def EchoHeaderCache(self): | 628 def EchoHeaderCache(self): |
| 621 return self.EchoHeaderHelper("/echoheadercache") | 629 return self.EchoHeaderHelper("/echoheadercache") |
| 622 | 630 |
| 623 def EchoHeaderHelper(self, echo_header): | 631 def EchoHeaderHelper(self, echo_header): |
| 624 """This function echoes back the value of the request header passed in.""" | 632 """This function echoes back the value of the request header passed in.""" |
| 625 if not self._ShouldHandleRequest(echo_header): | 633 if not self._ShouldHandleRequest(echo_header): |
| 626 return False | 634 return False |
| 627 | 635 |
| 628 query_char = self.path.find('?') | 636 query_char = self.path.find('?') |
| 629 if query_char != -1: | 637 if query_char != -1: |
| 630 header_name = self.path[query_char+1:] | 638 header_name = self.path[query_char+1:] |
| 631 | 639 |
| 632 self.send_response(200) | 640 self.send_response(200) |
| 633 self.send_header('Content-type', 'text/plain') | 641 self.send_header('Content-Type', 'text/plain') |
| 634 if echo_header == '/echoheadercache': | 642 if echo_header == '/echoheadercache': |
| 635 self.send_header('Cache-control', 'max-age=60000') | 643 self.send_header('Cache-control', 'max-age=60000') |
| 636 else: | 644 else: |
| 637 self.send_header('Cache-control', 'no-cache') | 645 self.send_header('Cache-control', 'no-cache') |
| 638 # insert a vary header to properly indicate that the cachability of this | 646 # insert a vary header to properly indicate that the cachability of this |
| 639 # request is subject to value of the request header being echoed. | 647 # request is subject to value of the request header being echoed. |
| 640 if len(header_name) > 0: | 648 if len(header_name) > 0: |
| 641 self.send_header('Vary', header_name) | 649 self.send_header('Vary', header_name) |
| 642 self.end_headers() | 650 self.end_headers() |
| 643 | 651 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 667 return body | 675 return body |
| 668 | 676 |
| 669 def EchoHandler(self): | 677 def EchoHandler(self): |
| 670 """This handler just echoes back the payload of the request, for testing | 678 """This handler just echoes back the payload of the request, for testing |
| 671 form submission.""" | 679 form submission.""" |
| 672 | 680 |
| 673 if not self._ShouldHandleRequest("/echo"): | 681 if not self._ShouldHandleRequest("/echo"): |
| 674 return False | 682 return False |
| 675 | 683 |
| 676 self.send_response(200) | 684 self.send_response(200) |
| 677 self.send_header('Content-type', 'text/html') | 685 self.send_header('Content-Type', 'text/html') |
| 678 self.end_headers() | 686 self.end_headers() |
| 679 self.wfile.write(self.ReadRequestBody()) | 687 self.wfile.write(self.ReadRequestBody()) |
| 680 return True | 688 return True |
| 681 | 689 |
| 682 def EchoTitleHandler(self): | 690 def EchoTitleHandler(self): |
| 683 """This handler is like Echo, but sets the page title to the request.""" | 691 """This handler is like Echo, but sets the page title to the request.""" |
| 684 | 692 |
| 685 if not self._ShouldHandleRequest("/echotitle"): | 693 if not self._ShouldHandleRequest("/echotitle"): |
| 686 return False | 694 return False |
| 687 | 695 |
| 688 self.send_response(200) | 696 self.send_response(200) |
| 689 self.send_header('Content-type', 'text/html') | 697 self.send_header('Content-Type', 'text/html') |
| 690 self.end_headers() | 698 self.end_headers() |
| 691 request = self.ReadRequestBody() | 699 request = self.ReadRequestBody() |
| 692 self.wfile.write('<html><head><title>') | 700 self.wfile.write('<html><head><title>') |
| 693 self.wfile.write(request) | 701 self.wfile.write(request) |
| 694 self.wfile.write('</title></head></html>') | 702 self.wfile.write('</title></head></html>') |
| 695 return True | 703 return True |
| 696 | 704 |
| 697 def EchoAllHandler(self): | 705 def EchoAllHandler(self): |
| 698 """This handler yields a (more) human-readable page listing information | 706 """This handler yields a (more) human-readable page listing information |
| 699 about the request header & contents.""" | 707 about the request header & contents.""" |
| 700 | 708 |
| 701 if not self._ShouldHandleRequest("/echoall"): | 709 if not self._ShouldHandleRequest("/echoall"): |
| 702 return False | 710 return False |
| 703 | 711 |
| 704 self.send_response(200) | 712 self.send_response(200) |
| 705 self.send_header('Content-type', 'text/html') | 713 self.send_header('Content-Type', 'text/html') |
| 706 self.end_headers() | 714 self.end_headers() |
| 707 self.wfile.write('<html><head><style>' | 715 self.wfile.write('<html><head><style>' |
| 708 'pre { border: 1px solid black; margin: 5px; padding: 5px }' | 716 'pre { border: 1px solid black; margin: 5px; padding: 5px }' |
| 709 '</style></head><body>' | 717 '</style></head><body>' |
| 710 '<div style="float: right">' | 718 '<div style="float: right">' |
| 711 '<a href="/echo">back to referring page</a></div>' | 719 '<a href="/echo">back to referring page</a></div>' |
| 712 '<h1>Request Body:</h1><pre>') | 720 '<h1>Request Body:</h1><pre>') |
| 713 | 721 |
| 714 if self.command == 'POST' or self.command == 'PUT': | 722 if self.command == 'POST' or self.command == 'PUT': |
| 715 qs = self.ReadRequestBody() | 723 qs = self.ReadRequestBody() |
| (...skipping 25 matching lines...) Expand all Loading... |
| 741 # small chunks of data to the client. Use a fairly large buffer | 749 # small chunks of data to the client. Use a fairly large buffer |
| 742 # so that we'll fill chrome's IO buffer enough to force it to | 750 # so that we'll fill chrome's IO buffer enough to force it to |
| 743 # actually write the data. | 751 # actually write the data. |
| 744 # See also the comments in the client-side of this test in | 752 # See also the comments in the client-side of this test in |
| 745 # download_uitest.cc | 753 # download_uitest.cc |
| 746 # | 754 # |
| 747 size_chunk1 = 35*1024 | 755 size_chunk1 = 35*1024 |
| 748 size_chunk2 = 10*1024 | 756 size_chunk2 = 10*1024 |
| 749 | 757 |
| 750 self.send_response(200) | 758 self.send_response(200) |
| 751 self.send_header('Content-type', 'application/octet-stream') | 759 self.send_header('Content-Type', 'application/octet-stream') |
| 752 self.send_header('Cache-Control', 'max-age=0') | 760 self.send_header('Cache-Control', 'max-age=0') |
| 753 if send_length: | 761 if send_length: |
| 754 self.send_header('Content-Length', size_chunk1 + size_chunk2) | 762 self.send_header('Content-Length', size_chunk1 + size_chunk2) |
| 755 self.end_headers() | 763 self.end_headers() |
| 756 | 764 |
| 757 # First chunk of data: | 765 # First chunk of data: |
| 758 self.wfile.write("*" * size_chunk1) | 766 self.wfile.write("*" * size_chunk1) |
| 759 self.wfile.flush() | 767 self.wfile.flush() |
| 760 | 768 |
| 761 # handle requests until one of them clears this flag. | 769 # handle requests until one of them clears this flag. |
| 762 self.server.waitForDownload = True | 770 self.server.waitForDownload = True |
| 763 while self.server.waitForDownload: | 771 while self.server.waitForDownload: |
| 764 self.server.handle_request() | 772 self.server.handle_request() |
| 765 | 773 |
| 766 # Second chunk of data: | 774 # Second chunk of data: |
| 767 self.wfile.write("*" * size_chunk2) | 775 self.wfile.write("*" * size_chunk2) |
| 768 return True | 776 return True |
| 769 | 777 |
| 770 def DownloadFinishHandler(self): | 778 def DownloadFinishHandler(self): |
| 771 """This handler just tells the server to finish the current download.""" | 779 """This handler just tells the server to finish the current download.""" |
| 772 | 780 |
| 773 if not self._ShouldHandleRequest("/download-finish"): | 781 if not self._ShouldHandleRequest("/download-finish"): |
| 774 return False | 782 return False |
| 775 | 783 |
| 776 self.server.waitForDownload = False | 784 self.server.waitForDownload = False |
| 777 self.send_response(200) | 785 self.send_response(200) |
| 778 self.send_header('Content-type', 'text/html') | 786 self.send_header('Content-Type', 'text/html') |
| 779 self.send_header('Cache-Control', 'max-age=0') | 787 self.send_header('Cache-Control', 'max-age=0') |
| 780 self.end_headers() | 788 self.end_headers() |
| 781 return True | 789 return True |
| 782 | 790 |
| 783 def _ReplaceFileData(self, data, query_parameters): | 791 def _ReplaceFileData(self, data, query_parameters): |
| 784 """Replaces matching substrings in a file. | 792 """Replaces matching substrings in a file. |
| 785 | 793 |
| 786 If the 'replace_text' URL query parameter is present, it is expected to be | 794 If the 'replace_text' URL query parameter is present, it is expected to be |
| 787 of the form old_text:new_text, which indicates that any old_text strings in | 795 of the form old_text:new_text, which indicates that any old_text strings in |
| 788 the file are replaced with new_text. Multiple 'replace_text' parameters may | 796 the file are replaced with new_text. Multiple 'replace_text' parameters may |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 if query == 'U': | 860 if query == 'U': |
| 853 content_length = uncompressed_len | 861 content_length = uncompressed_len |
| 854 elif query == 'S': | 862 elif query == 'S': |
| 855 content_length = compressed_len / 2 | 863 content_length = compressed_len / 2 |
| 856 elif query == 'M': | 864 elif query == 'M': |
| 857 content_length = (compressed_len + uncompressed_len) / 2 | 865 content_length = (compressed_len + uncompressed_len) / 2 |
| 858 elif query == 'L': | 866 elif query == 'L': |
| 859 content_length = compressed_len + uncompressed_len | 867 content_length = compressed_len + uncompressed_len |
| 860 | 868 |
| 861 self.send_response(200) | 869 self.send_response(200) |
| 862 self.send_header('Content-type', 'application/msword') | 870 self.send_header('Content-Type', 'application/msword') |
| 863 self.send_header('Content-encoding', 'deflate') | 871 self.send_header('Content-encoding', 'deflate') |
| 864 self.send_header('Connection', 'close') | 872 self.send_header('Connection', 'close') |
| 865 self.send_header('Content-Length', content_length) | 873 self.send_header('Content-Length', content_length) |
| 866 self.send_header('ETag', '\'' + file_path + '\'') | 874 self.send_header('ETag', '\'' + file_path + '\'') |
| 867 self.end_headers() | 875 self.end_headers() |
| 868 | 876 |
| 869 self.wfile.write(data) | 877 self.wfile.write(data) |
| 870 | 878 |
| 871 return True | 879 return True |
| 872 | 880 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 end = int(range[1]) | 939 end = int(range[1]) |
| 932 | 940 |
| 933 self.send_response(206) | 941 self.send_response(206) |
| 934 content_range = 'bytes ' + str(start) + '-' + str(end) + '/' + \ | 942 content_range = 'bytes ' + str(start) + '-' + str(end) + '/' + \ |
| 935 str(len(data)) | 943 str(len(data)) |
| 936 self.send_header('Content-Range', content_range) | 944 self.send_header('Content-Range', content_range) |
| 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('?') |
| 958 if query_char != -1: | 967 if query_char != -1: |
| 959 cookie_values = self.path[query_char + 1:].split('&') | 968 cookie_values = self.path[query_char + 1:].split('&') |
| 960 else: | 969 else: |
| 961 cookie_values = ("",) | 970 cookie_values = ("",) |
| 962 self.send_response(200) | 971 self.send_response(200) |
| 963 self.send_header('Content-type', 'text/html') | 972 self.send_header('Content-Type', 'text/html') |
| 964 for cookie_value in cookie_values: | 973 for cookie_value in cookie_values: |
| 965 self.send_header('Set-Cookie', '%s' % cookie_value) | 974 self.send_header('Set-Cookie', '%s' % cookie_value) |
| 966 self.end_headers() | 975 self.end_headers() |
| 967 for cookie_value in cookie_values: | 976 for cookie_value in cookie_values: |
| 968 self.wfile.write('%s' % cookie_value) | 977 self.wfile.write('%s' % cookie_value) |
| 969 return True | 978 return True |
| 970 | 979 |
| 971 def AuthBasicHandler(self): | 980 def AuthBasicHandler(self): |
| 972 """This handler tests 'Basic' authentication. It just sends a page with | 981 """This handler tests 'Basic' authentication. It just sends a page with |
| 973 title 'user/pass' if you succeed.""" | 982 title 'user/pass' if you succeed.""" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 995 raise Exception('no auth') | 1004 raise Exception('no auth') |
| 996 b64str = re.findall(r'Basic (\S+)', auth)[0] | 1005 b64str = re.findall(r'Basic (\S+)', auth)[0] |
| 997 userpass = base64.b64decode(b64str) | 1006 userpass = base64.b64decode(b64str) |
| 998 username, password = re.findall(r'([^:]+):(\S+)', userpass)[0] | 1007 username, password = re.findall(r'([^:]+):(\S+)', userpass)[0] |
| 999 if password != expected_password: | 1008 if password != expected_password: |
| 1000 raise Exception('wrong password') | 1009 raise Exception('wrong password') |
| 1001 except Exception, e: | 1010 except Exception, e: |
| 1002 # Authentication failed. | 1011 # Authentication failed. |
| 1003 self.send_response(401) | 1012 self.send_response(401) |
| 1004 self.send_header('WWW-Authenticate', 'Basic realm="%s"' % realm) | 1013 self.send_header('WWW-Authenticate', 'Basic realm="%s"' % realm) |
| 1005 self.send_header('Content-type', 'text/html') | 1014 self.send_header('Content-Type', 'text/html') |
| 1006 if set_cookie_if_challenged: | 1015 if set_cookie_if_challenged: |
| 1007 self.send_header('Set-Cookie', 'got_challenged=true') | 1016 self.send_header('Set-Cookie', 'got_challenged=true') |
| 1008 self.end_headers() | 1017 self.end_headers() |
| 1009 self.wfile.write('<html><head>') | 1018 self.wfile.write('<html><head>') |
| 1010 self.wfile.write('<title>Denied: %s</title>' % e) | 1019 self.wfile.write('<title>Denied: %s</title>' % e) |
| 1011 self.wfile.write('</head><body>') | 1020 self.wfile.write('</head><body>') |
| 1012 self.wfile.write('auth=%s<p>' % auth) | 1021 self.wfile.write('auth=%s<p>' % auth) |
| 1013 self.wfile.write('b64str=%s<p>' % b64str) | 1022 self.wfile.write('b64str=%s<p>' % b64str) |
| 1014 self.wfile.write('username: %s<p>' % username) | 1023 self.wfile.write('username: %s<p>' % username) |
| 1015 self.wfile.write('userpass: %s<p>' % userpass) | 1024 self.wfile.write('userpass: %s<p>' % userpass) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1034 if not os.path.isfile(gif_path): | 1043 if not os.path.isfile(gif_path): |
| 1035 self.send_error(404) | 1044 self.send_error(404) |
| 1036 self.protocol_version = old_protocol_version | 1045 self.protocol_version = old_protocol_version |
| 1037 return True | 1046 return True |
| 1038 | 1047 |
| 1039 f = open(gif_path, "rb") | 1048 f = open(gif_path, "rb") |
| 1040 data = f.read() | 1049 data = f.read() |
| 1041 f.close() | 1050 f.close() |
| 1042 | 1051 |
| 1043 self.send_response(200) | 1052 self.send_response(200) |
| 1044 self.send_header('Content-type', 'image/gif') | 1053 self.send_header('Content-Type', 'image/gif') |
| 1045 self.send_header('Cache-control', 'max-age=60000') | 1054 self.send_header('Cache-control', 'max-age=60000') |
| 1046 self.send_header('Etag', 'abc') | 1055 self.send_header('Etag', 'abc') |
| 1047 self.end_headers() | 1056 self.end_headers() |
| 1048 self.wfile.write(data) | 1057 self.wfile.write(data) |
| 1049 else: | 1058 else: |
| 1050 self.send_response(200) | 1059 self.send_response(200) |
| 1051 self.send_header('Content-type', 'text/html') | 1060 self.send_header('Content-Type', 'text/html') |
| 1052 self.send_header('Cache-control', 'max-age=60000') | 1061 self.send_header('Cache-control', 'max-age=60000') |
| 1053 self.send_header('Etag', 'abc') | 1062 self.send_header('Etag', 'abc') |
| 1054 self.end_headers() | 1063 self.end_headers() |
| 1055 self.wfile.write('<html><head>') | 1064 self.wfile.write('<html><head>') |
| 1056 self.wfile.write('<title>%s/%s</title>' % (username, password)) | 1065 self.wfile.write('<title>%s/%s</title>' % (username, password)) |
| 1057 self.wfile.write('</head><body>') | 1066 self.wfile.write('</head><body>') |
| 1058 self.wfile.write('auth=%s<p>' % auth) | 1067 self.wfile.write('auth=%s<p>' % auth) |
| 1059 self.wfile.write('You sent:<br>%s<p>' % self.headers) | 1068 self.wfile.write('You sent:<br>%s<p>' % self.headers) |
| 1060 self.wfile.write('</body></html>') | 1069 self.wfile.write('</body></html>') |
| 1061 | 1070 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 hdr = ('Digest ' | 1138 hdr = ('Digest ' |
| 1130 'realm="%s", ' | 1139 'realm="%s", ' |
| 1131 'domain="/", ' | 1140 'domain="/", ' |
| 1132 'qop="auth", ' | 1141 'qop="auth", ' |
| 1133 'algorithm=MD5, ' | 1142 'algorithm=MD5, ' |
| 1134 'nonce="%s", ' | 1143 'nonce="%s", ' |
| 1135 'opaque="%s"') % (realm, nonce, opaque) | 1144 'opaque="%s"') % (realm, nonce, opaque) |
| 1136 if stale: | 1145 if stale: |
| 1137 hdr += ', stale="TRUE"' | 1146 hdr += ', stale="TRUE"' |
| 1138 self.send_header('WWW-Authenticate', hdr) | 1147 self.send_header('WWW-Authenticate', hdr) |
| 1139 self.send_header('Content-type', 'text/html') | 1148 self.send_header('Content-Type', 'text/html') |
| 1140 self.end_headers() | 1149 self.end_headers() |
| 1141 self.wfile.write('<html><head>') | 1150 self.wfile.write('<html><head>') |
| 1142 self.wfile.write('<title>Denied: %s</title>' % e) | 1151 self.wfile.write('<title>Denied: %s</title>' % e) |
| 1143 self.wfile.write('</head><body>') | 1152 self.wfile.write('</head><body>') |
| 1144 self.wfile.write('auth=%s<p>' % auth) | 1153 self.wfile.write('auth=%s<p>' % auth) |
| 1145 self.wfile.write('pairs=%s<p>' % pairs) | 1154 self.wfile.write('pairs=%s<p>' % pairs) |
| 1146 self.wfile.write('You sent:<br>%s<p>' % self.headers) | 1155 self.wfile.write('You sent:<br>%s<p>' % self.headers) |
| 1147 self.wfile.write('We are replying:<br>%s<p>' % hdr) | 1156 self.wfile.write('We are replying:<br>%s<p>' % hdr) |
| 1148 self.wfile.write('</body></html>') | 1157 self.wfile.write('</body></html>') |
| 1149 return True | 1158 return True |
| 1150 | 1159 |
| 1151 # Authentication successful. | 1160 # Authentication successful. |
| 1152 self.send_response(200) | 1161 self.send_response(200) |
| 1153 self.send_header('Content-type', 'text/html') | 1162 self.send_header('Content-Type', 'text/html') |
| 1154 self.end_headers() | 1163 self.end_headers() |
| 1155 self.wfile.write('<html><head>') | 1164 self.wfile.write('<html><head>') |
| 1156 self.wfile.write('<title>%s/%s</title>' % (pairs['username'], password)) | 1165 self.wfile.write('<title>%s/%s</title>' % (pairs['username'], password)) |
| 1157 self.wfile.write('</head><body>') | 1166 self.wfile.write('</head><body>') |
| 1158 self.wfile.write('auth=%s<p>' % auth) | 1167 self.wfile.write('auth=%s<p>' % auth) |
| 1159 self.wfile.write('pairs=%s<p>' % pairs) | 1168 self.wfile.write('pairs=%s<p>' % pairs) |
| 1160 self.wfile.write('</body></html>') | 1169 self.wfile.write('</body></html>') |
| 1161 | 1170 |
| 1162 return True | 1171 return True |
| 1163 | 1172 |
| 1164 def SlowServerHandler(self): | 1173 def SlowServerHandler(self): |
| 1165 """Wait for the user suggested time before responding. The syntax is | 1174 """Wait for the user suggested time before responding. The syntax is |
| 1166 /slow?0.5 to wait for half a second.""" | 1175 /slow?0.5 to wait for half a second.""" |
| 1167 if not self._ShouldHandleRequest("/slow"): | 1176 if not self._ShouldHandleRequest("/slow"): |
| 1168 return False | 1177 return False |
| 1169 query_char = self.path.find('?') | 1178 query_char = self.path.find('?') |
| 1170 wait_sec = 1.0 | 1179 wait_sec = 1.0 |
| 1171 if query_char >= 0: | 1180 if query_char >= 0: |
| 1172 try: | 1181 try: |
| 1173 wait_sec = int(self.path[query_char + 1:]) | 1182 wait_sec = int(self.path[query_char + 1:]) |
| 1174 except ValueError: | 1183 except ValueError: |
| 1175 pass | 1184 pass |
| 1176 time.sleep(wait_sec) | 1185 time.sleep(wait_sec) |
| 1177 self.send_response(200) | 1186 self.send_response(200) |
| 1178 self.send_header('Content-type', 'text/plain') | 1187 self.send_header('Content-Type', 'text/plain') |
| 1179 self.end_headers() | 1188 self.end_headers() |
| 1180 self.wfile.write("waited %d seconds" % wait_sec) | 1189 self.wfile.write("waited %d seconds" % wait_sec) |
| 1181 return True | 1190 return True |
| 1182 | 1191 |
| 1183 def ChunkedServerHandler(self): | 1192 def ChunkedServerHandler(self): |
| 1184 """Send chunked response. Allows to specify chunks parameters: | 1193 """Send chunked response. Allows to specify chunks parameters: |
| 1185 - waitBeforeHeaders - ms to wait before sending headers | 1194 - waitBeforeHeaders - ms to wait before sending headers |
| 1186 - waitBetweenChunks - ms to wait between chunks | 1195 - waitBetweenChunks - ms to wait between chunks |
| 1187 - chunkSize - size of each chunk in bytes | 1196 - chunkSize - size of each chunk in bytes |
| 1188 - chunksNumber - number of chunks | 1197 - chunksNumber - number of chunks |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1200 for param in params: | 1209 for param in params: |
| 1201 keyValue = param.split('=') | 1210 keyValue = param.split('=') |
| 1202 if len(keyValue) == 2: | 1211 if len(keyValue) == 2: |
| 1203 try: | 1212 try: |
| 1204 chunkedSettings[keyValue[0]] = int(keyValue[1]) | 1213 chunkedSettings[keyValue[0]] = int(keyValue[1]) |
| 1205 except ValueError: | 1214 except ValueError: |
| 1206 pass | 1215 pass |
| 1207 time.sleep(0.001 * chunkedSettings['waitBeforeHeaders']); | 1216 time.sleep(0.001 * chunkedSettings['waitBeforeHeaders']); |
| 1208 self.protocol_version = 'HTTP/1.1' # Needed for chunked encoding | 1217 self.protocol_version = 'HTTP/1.1' # Needed for chunked encoding |
| 1209 self.send_response(200) | 1218 self.send_response(200) |
| 1210 self.send_header('Content-type', 'text/plain') | 1219 self.send_header('Content-Type', 'text/plain') |
| 1211 self.send_header('Connection', 'close') | 1220 self.send_header('Connection', 'close') |
| 1212 self.send_header('Transfer-Encoding', 'chunked') | 1221 self.send_header('Transfer-Encoding', 'chunked') |
| 1213 self.end_headers() | 1222 self.end_headers() |
| 1214 # Chunked encoding: sending all chunks, then final zero-length chunk and | 1223 # Chunked encoding: sending all chunks, then final zero-length chunk and |
| 1215 # then final CRLF. | 1224 # then final CRLF. |
| 1216 for i in range(0, chunkedSettings['chunksNumber']): | 1225 for i in range(0, chunkedSettings['chunksNumber']): |
| 1217 if i > 0: | 1226 if i > 0: |
| 1218 time.sleep(0.001 * chunkedSettings['waitBetweenChunks']) | 1227 time.sleep(0.001 * chunkedSettings['waitBetweenChunks']) |
| 1219 self.sendChunkHelp('*' * chunkedSettings['chunkSize']) | 1228 self.sendChunkHelp('*' * chunkedSettings['chunkSize']) |
| 1220 self.wfile.flush(); # Keep in mind that we start flushing only after 1kb. | 1229 self.wfile.flush(); # Keep in mind that we start flushing only after 1kb. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 return False | 1264 return False |
| 1256 | 1265 |
| 1257 query_char = self.path.find('?') | 1266 query_char = self.path.find('?') |
| 1258 if query_char < 0 or len(self.path) <= query_char + 1: | 1267 if query_char < 0 or len(self.path) <= query_char + 1: |
| 1259 self.sendRedirectHelp(test_name) | 1268 self.sendRedirectHelp(test_name) |
| 1260 return True | 1269 return True |
| 1261 dest = self.path[query_char + 1:] | 1270 dest = self.path[query_char + 1:] |
| 1262 | 1271 |
| 1263 self.send_response(301) # moved permanently | 1272 self.send_response(301) # moved permanently |
| 1264 self.send_header('Location', dest) | 1273 self.send_header('Location', dest) |
| 1265 self.send_header('Content-type', 'text/html') | 1274 self.send_header('Content-Type', 'text/html') |
| 1266 self.end_headers() | 1275 self.end_headers() |
| 1267 self.wfile.write('<html><head>') | 1276 self.wfile.write('<html><head>') |
| 1268 self.wfile.write('</head><body>Redirecting to %s</body></html>' % dest) | 1277 self.wfile.write('</head><body>Redirecting to %s</body></html>' % dest) |
| 1269 | 1278 |
| 1270 return True | 1279 return True |
| 1271 | 1280 |
| 1272 def ClientRedirectHandler(self): | 1281 def ClientRedirectHandler(self): |
| 1273 """Sends a client redirect to the given URL. The syntax is | 1282 """Sends a client redirect to the given URL. The syntax is |
| 1274 '/client-redirect?http://foo.bar/asdf' to redirect to | 1283 '/client-redirect?http://foo.bar/asdf' to redirect to |
| 1275 'http://foo.bar/asdf'""" | 1284 'http://foo.bar/asdf'""" |
| 1276 | 1285 |
| 1277 test_name = "/client-redirect" | 1286 test_name = "/client-redirect" |
| 1278 if not self._ShouldHandleRequest(test_name): | 1287 if not self._ShouldHandleRequest(test_name): |
| 1279 return False | 1288 return False |
| 1280 | 1289 |
| 1281 query_char = self.path.find('?'); | 1290 query_char = self.path.find('?'); |
| 1282 if query_char < 0 or len(self.path) <= query_char + 1: | 1291 if query_char < 0 or len(self.path) <= query_char + 1: |
| 1283 self.sendRedirectHelp(test_name) | 1292 self.sendRedirectHelp(test_name) |
| 1284 return True | 1293 return True |
| 1285 dest = self.path[query_char + 1:] | 1294 dest = self.path[query_char + 1:] |
| 1286 | 1295 |
| 1287 self.send_response(200) | 1296 self.send_response(200) |
| 1288 self.send_header('Content-type', 'text/html') | 1297 self.send_header('Content-Type', 'text/html') |
| 1289 self.end_headers() | 1298 self.end_headers() |
| 1290 self.wfile.write('<html><head>') | 1299 self.wfile.write('<html><head>') |
| 1291 self.wfile.write('<meta http-equiv="refresh" content="0;url=%s">' % dest) | 1300 self.wfile.write('<meta http-equiv="refresh" content="0;url=%s">' % dest) |
| 1292 self.wfile.write('</head><body>Redirecting to %s</body></html>' % dest) | 1301 self.wfile.write('</head><body>Redirecting to %s</body></html>' % dest) |
| 1293 | 1302 |
| 1294 return True | 1303 return True |
| 1295 | 1304 |
| 1296 def MultipartHandler(self): | 1305 def MultipartHandler(self): |
| 1297 """Send a multipart response (10 text/html pages).""" | 1306 """Send a multipart response (10 text/html pages).""" |
| 1298 test_name = '/multipart' | 1307 test_name = '/multipart' |
| 1299 if not self._ShouldHandleRequest(test_name): | 1308 if not self._ShouldHandleRequest(test_name): |
| 1300 return False | 1309 return False |
| 1301 | 1310 |
| 1302 num_frames = 10 | 1311 num_frames = 10 |
| 1303 bound = '12345' | 1312 bound = '12345' |
| 1304 self.send_response(200) | 1313 self.send_response(200) |
| 1305 self.send_header('Content-type', | 1314 self.send_header('Content-Type', |
| 1306 'multipart/x-mixed-replace;boundary=' + bound) | 1315 'multipart/x-mixed-replace;boundary=' + bound) |
| 1307 self.end_headers() | 1316 self.end_headers() |
| 1308 | 1317 |
| 1309 for i in xrange(num_frames): | 1318 for i in xrange(num_frames): |
| 1310 self.wfile.write('--' + bound + '\r\n') | 1319 self.wfile.write('--' + bound + '\r\n') |
| 1311 self.wfile.write('Content-type: text/html\r\n\r\n') | 1320 self.wfile.write('Content-Type: text/html\r\n\r\n') |
| 1312 self.wfile.write('<title>page ' + str(i) + '</title>') | 1321 self.wfile.write('<title>page ' + str(i) + '</title>') |
| 1313 self.wfile.write('page ' + str(i)) | 1322 self.wfile.write('page ' + str(i)) |
| 1314 | 1323 |
| 1315 self.wfile.write('--' + bound + '--') | 1324 self.wfile.write('--' + bound + '--') |
| 1316 return True | 1325 return True |
| 1317 | 1326 |
| 1318 def MultipartSlowHandler(self): | 1327 def MultipartSlowHandler(self): |
| 1319 """Send a multipart response (3 text/html pages) with a slight delay | 1328 """Send a multipart response (3 text/html pages) with a slight delay |
| 1320 between each page. This is similar to how some pages show status using | 1329 between each page. This is similar to how some pages show status using |
| 1321 multipart.""" | 1330 multipart.""" |
| 1322 test_name = '/multipart-slow' | 1331 test_name = '/multipart-slow' |
| 1323 if not self._ShouldHandleRequest(test_name): | 1332 if not self._ShouldHandleRequest(test_name): |
| 1324 return False | 1333 return False |
| 1325 | 1334 |
| 1326 num_frames = 3 | 1335 num_frames = 3 |
| 1327 bound = '12345' | 1336 bound = '12345' |
| 1328 self.send_response(200) | 1337 self.send_response(200) |
| 1329 self.send_header('Content-type', | 1338 self.send_header('Content-Type', |
| 1330 'multipart/x-mixed-replace;boundary=' + bound) | 1339 'multipart/x-mixed-replace;boundary=' + bound) |
| 1331 self.end_headers() | 1340 self.end_headers() |
| 1332 | 1341 |
| 1333 for i in xrange(num_frames): | 1342 for i in xrange(num_frames): |
| 1334 self.wfile.write('--' + bound + '\r\n') | 1343 self.wfile.write('--' + bound + '\r\n') |
| 1335 self.wfile.write('Content-type: text/html\r\n\r\n') | 1344 self.wfile.write('Content-Type: text/html\r\n\r\n') |
| 1336 time.sleep(0.25) | 1345 time.sleep(0.25) |
| 1337 if i == 2: | 1346 if i == 2: |
| 1338 self.wfile.write('<title>PASS</title>') | 1347 self.wfile.write('<title>PASS</title>') |
| 1339 else: | 1348 else: |
| 1340 self.wfile.write('<title>page ' + str(i) + '</title>') | 1349 self.wfile.write('<title>page ' + str(i) + '</title>') |
| 1341 self.wfile.write('page ' + str(i) + '<!-- ' + ('x' * 2048) + '-->') | 1350 self.wfile.write('page ' + str(i) + '<!-- ' + ('x' * 2048) + '-->') |
| 1342 | 1351 |
| 1343 self.wfile.write('--' + bound + '--') | 1352 self.wfile.write('--' + bound + '--') |
| 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') |
| 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 if (self.command != 'HEAD'): |
| 1367 self.wfile.write(contents) |
| 1358 return True | 1368 return True |
| 1359 | 1369 |
| 1360 def RedirectConnectHandler(self): | 1370 def RedirectConnectHandler(self): |
| 1361 """Sends a redirect to the CONNECT request for www.redirect.com. This | 1371 """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 | 1372 response is not specified by the RFC, so the browser should not follow |
| 1363 the redirect.""" | 1373 the redirect.""" |
| 1364 | 1374 |
| 1365 if (self.path.find("www.redirect.com") < 0): | 1375 if (self.path.find("www.redirect.com") < 0): |
| 1366 return False | 1376 return False |
| 1367 | 1377 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1389 self.end_headers() | 1399 self.end_headers() |
| 1390 return True | 1400 return True |
| 1391 | 1401 |
| 1392 def DefaultConnectResponseHandler(self): | 1402 def DefaultConnectResponseHandler(self): |
| 1393 """This is the catch-all response handler for CONNECT requests that aren't | 1403 """This is the catch-all response handler for CONNECT requests that aren't |
| 1394 handled by one of the special handlers above. Real Web servers respond | 1404 handled by one of the special handlers above. Real Web servers respond |
| 1395 with 400 to CONNECT requests.""" | 1405 with 400 to CONNECT requests.""" |
| 1396 | 1406 |
| 1397 contents = "Your client has issued a malformed or illegal request." | 1407 contents = "Your client has issued a malformed or illegal request." |
| 1398 self.send_response(400) # bad request | 1408 self.send_response(400) # bad request |
| 1399 self.send_header('Content-type', 'text/html') | 1409 self.send_header('Content-Type', 'text/html') |
| 1400 self.send_header("Content-Length", len(contents)) | 1410 self.send_header('Content-Length', len(contents)) |
| 1401 self.end_headers() | 1411 self.end_headers() |
| 1402 self.wfile.write(contents) | 1412 self.wfile.write(contents) |
| 1403 return True | 1413 return True |
| 1404 | 1414 |
| 1405 def DeviceManagementHandler(self): | 1415 def DeviceManagementHandler(self): |
| 1406 """Delegates to the device management service used for cloud policy.""" | 1416 """Delegates to the device management service used for cloud policy.""" |
| 1407 if not self._ShouldHandleRequest("/device_management"): | 1417 if not self._ShouldHandleRequest("/device_management"): |
| 1408 return False | 1418 return False |
| 1409 | 1419 |
| 1410 raw_request = self.ReadRequestBody() | 1420 raw_request = self.ReadRequestBody() |
| 1411 | 1421 |
| 1412 if not self.server._device_management_handler: | 1422 if not self.server._device_management_handler: |
| 1413 import device_management | 1423 import device_management |
| 1414 policy_path = os.path.join(self.server.data_dir, 'device_management') | 1424 policy_path = os.path.join(self.server.data_dir, 'device_management') |
| 1415 self.server._device_management_handler = ( | 1425 self.server._device_management_handler = ( |
| 1416 device_management.TestServer(policy_path, | 1426 device_management.TestServer(policy_path, |
| 1417 self.server.policy_keys, | 1427 self.server.policy_keys, |
| 1418 self.server.policy_user)) | 1428 self.server.policy_user)) |
| 1419 | 1429 |
| 1420 http_response, raw_reply = ( | 1430 http_response, raw_reply = ( |
| 1421 self.server._device_management_handler.HandleRequest(self.path, | 1431 self.server._device_management_handler.HandleRequest(self.path, |
| 1422 self.headers, | 1432 self.headers, |
| 1423 raw_request)) | 1433 raw_request)) |
| 1424 self.send_response(http_response) | 1434 self.send_response(http_response) |
| 1425 if (http_response == 200): | 1435 if (http_response == 200): |
| 1426 self.send_header('Content-type', 'application/x-protobuffer') | 1436 self.send_header('Content-Type', 'application/x-protobuffer') |
| 1427 self.end_headers() | 1437 self.end_headers() |
| 1428 self.wfile.write(raw_reply) | 1438 self.wfile.write(raw_reply) |
| 1429 return True | 1439 return True |
| 1430 | 1440 |
| 1431 # called by the redirect handling function when there is no parameter | 1441 # called by the redirect handling function when there is no parameter |
| 1432 def sendRedirectHelp(self, redirect_name): | 1442 def sendRedirectHelp(self, redirect_name): |
| 1433 self.send_response(200) | 1443 self.send_response(200) |
| 1434 self.send_header('Content-type', 'text/html') | 1444 self.send_header('Content-Type', 'text/html') |
| 1435 self.end_headers() | 1445 self.end_headers() |
| 1436 self.wfile.write('<html><body><h1>Error: no redirect destination</h1>') | 1446 self.wfile.write('<html><body><h1>Error: no redirect destination</h1>') |
| 1437 self.wfile.write('Use <pre>%s?http://dest...</pre>' % redirect_name) | 1447 self.wfile.write('Use <pre>%s?http://dest...</pre>' % redirect_name) |
| 1438 self.wfile.write('</body></html>') | 1448 self.wfile.write('</body></html>') |
| 1439 | 1449 |
| 1440 # called by chunked handling function | 1450 # called by chunked handling function |
| 1441 def sendChunkHelp(self, chunk): | 1451 def sendChunkHelp(self, chunk): |
| 1442 # Each chunk consists of: chunk size (hex), CRLF, chunk body, CRLF | 1452 # Each chunk consists of: chunk size (hex), CRLF, chunk body, CRLF |
| 1443 self.wfile.write('%X\r\n' % len(chunk)) | 1453 self.wfile.write('%X\r\n' % len(chunk)) |
| 1444 self.wfile.write(chunk) | 1454 self.wfile.write(chunk) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1456 self.ChromiumSyncSendNotificationOpHandler, | 1466 self.ChromiumSyncSendNotificationOpHandler, |
| 1457 self.ChromiumSyncBirthdayErrorOpHandler, | 1467 self.ChromiumSyncBirthdayErrorOpHandler, |
| 1458 self.ChromiumSyncTransientErrorOpHandler, | 1468 self.ChromiumSyncTransientErrorOpHandler, |
| 1459 self.ChromiumSyncSyncTabsOpHandler, | 1469 self.ChromiumSyncSyncTabsOpHandler, |
| 1460 self.ChromiumSyncErrorOpHandler, | 1470 self.ChromiumSyncErrorOpHandler, |
| 1461 self.ChromiumSyncCredHandler] | 1471 self.ChromiumSyncCredHandler] |
| 1462 | 1472 |
| 1463 post_handlers = [self.ChromiumSyncCommandHandler, | 1473 post_handlers = [self.ChromiumSyncCommandHandler, |
| 1464 self.ChromiumSyncTimeHandler] | 1474 self.ChromiumSyncTimeHandler] |
| 1465 BasePageHandler.__init__(self, request, client_address, | 1475 BasePageHandler.__init__(self, request, client_address, |
| 1466 sync_http_server, [], get_handlers, | 1476 sync_http_server, [], get_handlers, [], |
| 1467 post_handlers, []) | 1477 post_handlers, []) |
| 1468 | 1478 |
| 1469 | 1479 |
| 1470 def ChromiumSyncTimeHandler(self): | 1480 def ChromiumSyncTimeHandler(self): |
| 1471 """Handle Chromium sync .../time requests. | 1481 """Handle Chromium sync .../time requests. |
| 1472 | 1482 |
| 1473 The syncer sometimes checks server reachability by examining /time. | 1483 The syncer sometimes checks server reachability by examining /time. |
| 1474 """ | 1484 """ |
| 1475 test_name = "/chromiumsync/time" | 1485 test_name = "/chromiumsync/time" |
| 1476 if not self._ShouldHandleRequest(test_name): | 1486 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 ' | 1925 'random key if none is specified on the command ' |
| 1916 'line.') | 1926 'line.') |
| 1917 option_parser.add_option('', '--policy-user', default='user@example.com', | 1927 option_parser.add_option('', '--policy-user', default='user@example.com', |
| 1918 dest='policy_user', | 1928 dest='policy_user', |
| 1919 help='Specify the user name the server should ' | 1929 help='Specify the user name the server should ' |
| 1920 'report back to the client as the user owning the ' | 1930 'report back to the client as the user owning the ' |
| 1921 'token used for making the policy request.') | 1931 'token used for making the policy request.') |
| 1922 options, args = option_parser.parse_args() | 1932 options, args = option_parser.parse_args() |
| 1923 | 1933 |
| 1924 sys.exit(main(options, args)) | 1934 sys.exit(main(options, args)) |
| OLD | NEW |