| 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-2010 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 """ | 12 """ |
| 13 | 13 |
| 14 import base64 | 14 import base64 |
| 15 import BaseHTTPServer | 15 import BaseHTTPServer |
| 16 import cgi | 16 import cgi |
| 17 import optparse | 17 import optparse |
| 18 import os | 18 import os |
| 19 import re | 19 import re |
| 20 import shutil | 20 import shutil |
| 21 import SocketServer | 21 import SocketServer |
| 22 import sys | 22 import sys |
| 23 import time | 23 import time |
| 24 import urllib2 | 24 import urlparse |
| 25 import warnings | 25 import warnings |
| 26 | 26 |
| 27 # Ignore deprecation warnings, they make our output more cluttered. | 27 # Ignore deprecation warnings, they make our output more cluttered. |
| 28 warnings.filterwarnings("ignore", category=DeprecationWarning) | 28 warnings.filterwarnings("ignore", category=DeprecationWarning) |
| 29 | 29 |
| 30 import pyftpdlib.ftpserver | 30 import pyftpdlib.ftpserver |
| 31 import tlslite | 31 import tlslite |
| 32 import tlslite.api | 32 import tlslite.api |
| 33 | 33 |
| 34 try: | 34 try: |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 if not self._ShouldHandleRequest("/download-finish"): | 566 if not self._ShouldHandleRequest("/download-finish"): |
| 567 return False | 567 return False |
| 568 | 568 |
| 569 self.server.waitForDownload = False | 569 self.server.waitForDownload = False |
| 570 self.send_response(200) | 570 self.send_response(200) |
| 571 self.send_header('Content-type', 'text/html') | 571 self.send_header('Content-type', 'text/html') |
| 572 self.send_header('Cache-Control', 'max-age=0') | 572 self.send_header('Cache-Control', 'max-age=0') |
| 573 self.end_headers() | 573 self.end_headers() |
| 574 return True | 574 return True |
| 575 | 575 |
| 576 def _ReplaceFileData(self, data, query_parameters): |
| 577 """Replaces matching substrings in a file. |
| 578 |
| 579 If the 'replace_orig' and 'replace_new' URL query parameters are present, |
| 580 a new string is returned with all occasions of the 'replace_orig' value |
| 581 replaced by the 'replace_new' value. |
| 582 |
| 583 If the parameters are not present, |data| is returned. |
| 584 """ |
| 585 query_dict = cgi.parse_qs(query_parameters) |
| 586 orig_values = query_dict.get('replace_orig', []) |
| 587 new_values = query_dict.get('replace_new', []) |
| 588 if not orig_values or not new_values: |
| 589 return data |
| 590 orig_value = orig_values[0] |
| 591 new_value = new_values[0] |
| 592 return data.replace(orig_value, new_value) |
| 593 |
| 576 def FileHandler(self): | 594 def FileHandler(self): |
| 577 """This handler sends the contents of the requested file. Wow, it's like | 595 """This handler sends the contents of the requested file. Wow, it's like |
| 578 a real webserver!""" | 596 a real webserver!""" |
| 579 | 597 |
| 580 prefix = self.server.file_root_url | 598 prefix = self.server.file_root_url |
| 581 if not self.path.startswith(prefix): | 599 if not self.path.startswith(prefix): |
| 582 return False | 600 return False |
| 583 | 601 |
| 584 # Consume a request body if present. | 602 # Consume a request body if present. |
| 585 if self.command == 'POST' or self.command == 'PUT' : | 603 if self.command == 'POST' or self.command == 'PUT' : |
| 586 self.rfile.read(int(self.headers.getheader('content-length'))) | 604 self.rfile.read(int(self.headers.getheader('content-length'))) |
| 587 | 605 |
| 588 file = self.path[len(prefix):] | 606 _, _, url_path, _, query, _ = urlparse.urlparse(self.path) |
| 589 if file.find('?') > -1: | 607 sub_path = url_path[len(prefix):] |
| 590 # Ignore the query parameters entirely. | 608 entries = sub_path.split('/') |
| 591 url, querystring = file.split('?') | 609 file_path = os.path.join(self.server.data_dir, *entries) |
| 592 else: | 610 if os.path.isdir(file_path): |
| 593 url = file | 611 file_path = os.path.join(file_path, 'index.html') |
| 594 entries = url.split('/') | |
| 595 path = os.path.join(self.server.data_dir, *entries) | |
| 596 if os.path.isdir(path): | |
| 597 path = os.path.join(path, 'index.html') | |
| 598 | 612 |
| 599 if not os.path.isfile(path): | 613 if not os.path.isfile(file_path): |
| 600 print "File not found " + file + " full path:" + path | 614 print "File not found " + sub_path + " full path:" + file_path |
| 601 self.send_error(404) | 615 self.send_error(404) |
| 602 return True | 616 return True |
| 603 | 617 |
| 604 f = open(path, "rb") | 618 f = open(file_path, "rb") |
| 605 data = f.read() | 619 data = f.read() |
| 606 f.close() | 620 f.close() |
| 607 | 621 |
| 622 data = self._ReplaceFileData(data, query) |
| 623 |
| 608 # If file.mock-http-headers exists, it contains the headers we | 624 # If file.mock-http-headers exists, it contains the headers we |
| 609 # should send. Read them in and parse them. | 625 # should send. Read them in and parse them. |
| 610 headers_path = path + '.mock-http-headers' | 626 headers_path = file_path + '.mock-http-headers' |
| 611 if os.path.isfile(headers_path): | 627 if os.path.isfile(headers_path): |
| 612 f = open(headers_path, "r") | 628 f = open(headers_path, "r") |
| 613 | 629 |
| 614 # "HTTP/1.1 200 OK" | 630 # "HTTP/1.1 200 OK" |
| 615 response = f.readline() | 631 response = f.readline() |
| 616 status_code = re.findall('HTTP/\d+.\d+ (\d+)', response)[0] | 632 status_code = re.findall('HTTP/\d+.\d+ (\d+)', response)[0] |
| 617 self.send_response(int(status_code)) | 633 self.send_response(int(status_code)) |
| 618 | 634 |
| 619 for line in f: | 635 for line in f: |
| 620 header_values = re.findall('(\S+):\s*(.*)', line) | 636 header_values = re.findall('(\S+):\s*(.*)', line) |
| 621 if len(header_values) > 0: | 637 if len(header_values) > 0: |
| 622 # "name: value" | 638 # "name: value" |
| 623 name, value = header_values[0] | 639 name, value = header_values[0] |
| 624 self.send_header(name, value) | 640 self.send_header(name, value) |
| 625 f.close() | 641 f.close() |
| 626 else: | 642 else: |
| 627 # Could be more generic once we support mime-type sniffing, but for | 643 # Could be more generic once we support mime-type sniffing, but for |
| 628 # now we need to set it explicitly. | 644 # now we need to set it explicitly. |
| 629 self.send_response(200) | 645 self.send_response(200) |
| 630 self.send_header('Content-type', self.GetMIMETypeFromName(file)) | 646 self.send_header('Content-type', self.GetMIMETypeFromName(file_path)) |
| 631 self.send_header('Content-Length', len(data)) | 647 self.send_header('Content-Length', len(data)) |
| 632 self.end_headers() | 648 self.end_headers() |
| 633 | 649 |
| 634 self.wfile.write(data) | 650 self.wfile.write(data) |
| 635 | 651 |
| 636 return True | 652 return True |
| 637 | 653 |
| 638 def RealFileWithCommonHeaderHandler(self): | 654 def RealFileWithCommonHeaderHandler(self): |
| 639 """This handler sends the contents of the requested file without the pseudo | 655 """This handler sends the contents of the requested file without the pseudo |
| 640 http head!""" | 656 http head!""" |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 'option may appear multiple times, indicating ' | 1274 'option may appear multiple times, indicating ' |
| 1259 'multiple algorithms should be enabled.'); | 1275 'multiple algorithms should be enabled.'); |
| 1260 option_parser.add_option('', '--file-root-url', default='/files/', | 1276 option_parser.add_option('', '--file-root-url', default='/files/', |
| 1261 help='Specify a root URL for files served.') | 1277 help='Specify a root URL for files served.') |
| 1262 option_parser.add_option('', '--startup-pipe', type='int', | 1278 option_parser.add_option('', '--startup-pipe', type='int', |
| 1263 dest='startup_pipe', | 1279 dest='startup_pipe', |
| 1264 help='File handle of pipe to parent process') | 1280 help='File handle of pipe to parent process') |
| 1265 options, args = option_parser.parse_args() | 1281 options, args = option_parser.parse_args() |
| 1266 | 1282 |
| 1267 sys.exit(main(options, args)) | 1283 sys.exit(main(options, args)) |
| OLD | NEW |