OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # coding: utf-8 | 2 # coding: utf-8 |
3 | 3 |
4 # Copyright 2014 The Crashpad Authors. All rights reserved. | 4 # Copyright 2014 The Crashpad Authors. All rights reserved. |
5 # | 5 # |
6 # Licensed under the Apache License, Version 2.0 (the "License"); | 6 # Licensed under the Apache License, Version 2.0 (the "License"); |
7 # you may not use this file except in compliance with the License. | 7 # you may not use this file except in compliance with the License. |
8 # You may obtain a copy of the License at | 8 # You may obtain a copy of the License at |
9 # | 9 # |
10 # http://www.apache.org/licenses/LICENSE-2.0 | 10 # http://www.apache.org/licenses/LICENSE-2.0 |
11 # | 11 # |
12 # Unless required by applicable law or agreed to in writing, software | 12 # Unless required by applicable law or agreed to in writing, software |
13 # distributed under the License is distributed on an "AS IS" BASIS, | 13 # distributed under the License is distributed on an "AS IS" BASIS, |
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 # See the License for the specific language governing permissions and | 15 # See the License for the specific language governing permissions and |
16 # limitations under the License. | 16 # limitations under the License. |
17 | 17 |
18 """A one-shot testing webserver. | 18 """A one-shot testing webserver. |
19 | 19 |
20 When invoked, this server will write an integer to stdout, indiciating on which | 20 When invoked, this server will write a short integer to stdout, indiciating on |
21 port the server is listening. It will then read one integer from stdin, | 21 which port the server is listening. It will then read one integer from stdin, |
22 indiciating the response code to set for a request. The server will process | 22 indiciating the response code to be sent in response to a request. It also reads |
23 one HTTP request, writing it out entirely to stdout, and will then terminate. | 23 8 characters from stdin, which, after having "\r\n" appended, will form the |
| 24 response body in a successful response (one with code 200). The server will |
| 25 process one HTTP request, deliver the prearranged response to the client, and |
| 26 write the entire request to stdout. It will then terminate. |
24 | 27 |
25 This server is written in Python since it provides a simple HTTP stack, and | 28 This server is written in Python since it provides a simple HTTP stack, and |
26 because parsing Chunked encoding is safer and easier in a memory-safe language. | 29 because parsing Chunked encoding is safer and easier in a memory-safe language. |
27 This could easily have been written in C++ instead. | 30 This could easily have been written in C++ instead. |
28 """ | 31 """ |
29 | 32 |
30 import BaseHTTPServer | 33 import BaseHTTPServer |
31 import struct | 34 import struct |
32 import sys | 35 import sys |
33 | 36 |
(...skipping 16 matching lines...) Expand all Loading... |
50 | 53 |
51 def flush(self): | 54 def flush(self): |
52 self.file.flush() | 55 self.file.flush() |
53 | 56 |
54 def close(self): | 57 def close(self): |
55 self.file.close() | 58 self.file.close() |
56 | 59 |
57 | 60 |
58 class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | 61 class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
59 response_code = 500 | 62 response_code = 500 |
| 63 response_body = '' |
60 | 64 |
61 def handle_one_request(self): | 65 def handle_one_request(self): |
62 # Wrap the rfile in the buffering file object so that the raw header block | 66 # Wrap the rfile in the buffering file object so that the raw header block |
63 # can be written to stdout after it is parsed. | 67 # can be written to stdout after it is parsed. |
64 self.rfile = BufferedReadFile(self.rfile) | 68 self.rfile = BufferedReadFile(self.rfile) |
65 BaseHTTPServer.BaseHTTPRequestHandler.handle_one_request(self) | 69 BaseHTTPServer.BaseHTTPRequestHandler.handle_one_request(self) |
66 | 70 |
67 def do_POST(self): | 71 def do_POST(self): |
68 writer = sys.stdout | 72 writer = sys.stdout |
69 | 73 |
70 writer.write(self.rfile.buffer) | 74 writer.write(self.rfile.buffer) |
71 self.rfile.buffer = '' | 75 self.rfile.buffer = '' |
72 | 76 |
73 if self.headers.get('Transfer-Encoding', '') == 'Chunked': | 77 if self.headers.get('Transfer-Encoding', '') == 'Chunked': |
74 body = self.handle_chunked_encoding() | 78 body = self.handle_chunked_encoding() |
75 else: | 79 else: |
76 length = int(self.headers.get('Content-Length', -1)) | 80 length = int(self.headers.get('Content-Length', -1)) |
77 body = self.rfile.read(length) | 81 body = self.rfile.read(length) |
78 | 82 |
79 self.send_response(self.response_code) | 83 self.send_response(self.response_code) |
80 self.end_headers() | 84 self.end_headers() |
| 85 if self.response_code == 200: |
| 86 self.wfile.write(self.response_body) |
| 87 self.wfile.write('\r\n') |
81 | 88 |
82 writer.write(body) | 89 writer.write(body) |
83 writer.flush() | 90 writer.flush() |
84 | 91 |
85 def handle_chunked_encoding(self): | 92 def handle_chunked_encoding(self): |
86 """This parses a "Transfer-Encoding: Chunked" body in accordance with | 93 """This parses a "Transfer-Encoding: Chunked" body in accordance with |
87 RFC 7230 §4.1. This returns the result as a string. | 94 RFC 7230 §4.1. This returns the result as a string. |
88 """ | 95 """ |
89 body = '' | 96 body = '' |
90 chunk_size = self.read_chunk_size() | 97 chunk_size = self.read_chunk_size() |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 import os, msvcrt | 131 import os, msvcrt |
125 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) | 132 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) |
126 | 133 |
127 # Start the server. | 134 # Start the server. |
128 server = BaseHTTPServer.HTTPServer(('127.0.0.1', 0), RequestHandler) | 135 server = BaseHTTPServer.HTTPServer(('127.0.0.1', 0), RequestHandler) |
129 | 136 |
130 # Write the port as an unsigned short to the parent process. | 137 # Write the port as an unsigned short to the parent process. |
131 sys.stdout.write(struct.pack('=H', server.server_address[1])) | 138 sys.stdout.write(struct.pack('=H', server.server_address[1])) |
132 sys.stdout.flush() | 139 sys.stdout.flush() |
133 | 140 |
134 # Read the desired test response code as an unsigned short from the parent | 141 # Read the desired test response code as an unsigned short and the desired |
135 # process. | 142 # response body as an 8-byte string from the parent process. |
136 RequestHandler.response_code = \ | 143 RequestHandler.response_code, RequestHandler.response_body = \ |
137 struct.unpack('=H', sys.stdin.read(struct.calcsize('=H')))[0] | 144 struct.unpack('=H8s', sys.stdin.read(struct.calcsize('=H8s'))) |
138 | 145 |
139 # Handle the request. | 146 # Handle the request. |
140 server.handle_request() | 147 server.handle_request() |
141 | 148 |
142 if __name__ == '__main__': | 149 if __name__ == '__main__': |
143 Main() | 150 Main() |
OLD | NEW |