OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 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/TCP/UDP/BASIC_AUTH_PROXY/WEBSOCKET server used for | 6 """This is a simple HTTP/FTP/TCP/UDP/BASIC_AUTH_PROXY/WEBSOCKET server used for |
7 testing Chrome. | 7 testing Chrome. |
8 | 8 |
9 It supports several test URLs, as specified by the handlers in TestPageHandler. | 9 It supports several test URLs, as specified by the handlers in TestPageHandler. |
10 By default, it listens on an ephemeral port and sends the port number back to | 10 By default, it listens on an ephemeral port and sends the port number back to |
11 the originating process over a pipe. The originating process can specify an | 11 the originating process over a pipe. The originating process can specify an |
12 explicit port if necessary. | 12 explicit port if necessary. |
13 It can use https if you specify the flag --https=CERT where CERT is the path | 13 It can use https if you specify the flag --https=CERT where CERT is the path |
14 to a pem file containing the certificate and private key that should be used. | 14 to a pem file containing the certificate and private key that should be used. |
15 """ | 15 """ |
16 | 16 |
17 import base64 | 17 import base64 |
18 import BaseHTTPServer | 18 import BaseHTTPServer |
19 import cgi | 19 import cgi |
20 import hashlib | 20 import hashlib |
21 import logging | 21 import logging |
22 import minica | 22 import minica |
23 import os | 23 import os |
| 24 import json |
24 import random | 25 import random |
25 import re | 26 import re |
26 import select | 27 import select |
27 import socket | 28 import socket |
28 import SocketServer | 29 import SocketServer |
29 import struct | 30 import struct |
30 import sys | 31 import sys |
31 import threading | 32 import threading |
32 import time | 33 import time |
33 import urllib | 34 import urllib |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 self.MultipartHandler, | 276 self.MultipartHandler, |
276 self.GetSSLSessionCacheHandler, | 277 self.GetSSLSessionCacheHandler, |
277 self.SSLManySmallRecords, | 278 self.SSLManySmallRecords, |
278 self.GetChannelID, | 279 self.GetChannelID, |
279 self.CloseSocketHandler, | 280 self.CloseSocketHandler, |
280 self.RangeResetHandler, | 281 self.RangeResetHandler, |
281 self.DefaultResponseHandler] | 282 self.DefaultResponseHandler] |
282 post_handlers = [ | 283 post_handlers = [ |
283 self.EchoTitleHandler, | 284 self.EchoTitleHandler, |
284 self.EchoHandler, | 285 self.EchoHandler, |
285 self.PostOnlyFileHandler] + get_handlers | 286 self.PostOnlyFileHandler, |
| 287 self.EchoMultipartPostHandler] + get_handlers |
286 put_handlers = [ | 288 put_handlers = [ |
287 self.EchoTitleHandler, | 289 self.EchoTitleHandler, |
288 self.EchoHandler] + get_handlers | 290 self.EchoHandler] + get_handlers |
289 head_handlers = [ | 291 head_handlers = [ |
290 self.FileHandler, | 292 self.FileHandler, |
291 self.DefaultResponseHandler] | 293 self.DefaultResponseHandler] |
292 | 294 |
293 self._mime_types = { | 295 self._mime_types = { |
294 'crx' : 'application/x-chrome-extension', | 296 'crx' : 'application/x-chrome-extension', |
295 'exe' : 'application/octet-stream', | 297 'exe' : 'application/octet-stream', |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 for param in params: | 657 for param in params: |
656 self.wfile.write('%s=%s\n' % (param, params[param][0])) | 658 self.wfile.write('%s=%s\n' % (param, params[param][0])) |
657 | 659 |
658 self.wfile.write('</pre>') | 660 self.wfile.write('</pre>') |
659 | 661 |
660 self.wfile.write('<h1>Request Headers:</h1><pre>%s</pre>' % self.headers) | 662 self.wfile.write('<h1>Request Headers:</h1><pre>%s</pre>' % self.headers) |
661 | 663 |
662 self.wfile.write('</body></html>') | 664 self.wfile.write('</body></html>') |
663 return True | 665 return True |
664 | 666 |
| 667 def EchoMultipartPostHandler(self): |
| 668 """This handler echoes received multipart post data as json format.""" |
| 669 |
| 670 if not (self._ShouldHandleRequest("/echomultipartpost") or |
| 671 self._ShouldHandleRequest("/searchbyimage")): |
| 672 return False |
| 673 |
| 674 content_type, parameters = cgi.parse_header( |
| 675 self.headers.getheader('content-type')) |
| 676 if content_type == 'multipart/form-data': |
| 677 post_multipart = cgi.parse_multipart(self.rfile, parameters) |
| 678 elif content_type == 'application/x-www-form-urlencoded': |
| 679 raise Exception('POST by application/x-www-form-urlencoded is ' |
| 680 'not implemented.') |
| 681 else: |
| 682 post_multipart = {} |
| 683 |
| 684 # Since the data can be binary, we encode them by base64. |
| 685 post_multipart_base64_encoded = {} |
| 686 for field, values in post_multipart.items(): |
| 687 post_multipart_base64_encoded[field] = [base64.b64encode(value) |
| 688 for value in values] |
| 689 |
| 690 result = {'POST_multipart' : post_multipart_base64_encoded} |
| 691 |
| 692 self.send_response(200) |
| 693 self.send_header("Content-type", "text/plain") |
| 694 self.end_headers() |
| 695 self.wfile.write(json.dumps(result, indent=2, sort_keys=False)) |
| 696 return True |
| 697 |
665 def DownloadHandler(self): | 698 def DownloadHandler(self): |
666 """This handler sends a downloadable file with or without reporting | 699 """This handler sends a downloadable file with or without reporting |
667 the size (6K).""" | 700 the size (6K).""" |
668 | 701 |
669 if self.path.startswith("/download-unknown-size"): | 702 if self.path.startswith("/download-unknown-size"): |
670 send_length = False | 703 send_length = False |
671 elif self.path.startswith("/download-known-size"): | 704 elif self.path.startswith("/download-known-size"): |
672 send_length = True | 705 send_length = True |
673 else: | 706 else: |
674 return False | 707 return False |
(...skipping 1386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 '"aes128", "3des", "rc4". If omitted, all ' | 2094 '"aes128", "3des", "rc4". If omitted, all ' |
2062 'algorithms will be used. This option may ' | 2095 'algorithms will be used. This option may ' |
2063 'appear multiple times, indicating ' | 2096 'appear multiple times, indicating ' |
2064 'multiple algorithms should be enabled.'); | 2097 'multiple algorithms should be enabled.'); |
2065 self.option_parser.add_option('--file-root-url', default='/files/', | 2098 self.option_parser.add_option('--file-root-url', default='/files/', |
2066 help='Specify a root URL for files served.') | 2099 help='Specify a root URL for files served.') |
2067 | 2100 |
2068 | 2101 |
2069 if __name__ == '__main__': | 2102 if __name__ == '__main__': |
2070 sys.exit(ServerRunner().main()) | 2103 sys.exit(ServerRunner().main()) |
OLD | NEW |