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 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 return buf | 52 return buf |
53 | 53 |
54 def flush(self): | 54 def flush(self): |
55 self.file.flush() | 55 self.file.flush() |
56 | 56 |
57 def close(self): | 57 def close(self): |
58 self.file.close() | 58 self.file.close() |
59 | 59 |
60 | 60 |
61 class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | 61 class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
| 62 # Everything to be written to stdout is collected into this string. It can’t |
| 63 # be written to stdout until after the HTTP transaction is complete, because |
| 64 # stdout is a pipe being read by a test program that’s also the HTTP client. |
| 65 # The test program expects to complete the entire HTTP transaction before it |
| 66 # even starts reading this script’s stdout. If the stdout pipe buffer fills up |
| 67 # during an HTTP transaction, deadlock would result. |
| 68 raw_request = '' |
| 69 |
62 response_code = 500 | 70 response_code = 500 |
63 response_body = '' | 71 response_body = '' |
64 | 72 |
65 def handle_one_request(self): | 73 def handle_one_request(self): |
66 # Wrap the rfile in the buffering file object so that the raw header block | 74 # Wrap the rfile in the buffering file object so that the raw header block |
67 # can be written to stdout after it is parsed. | 75 # can be written to stdout after it is parsed. |
68 self.rfile = BufferedReadFile(self.rfile) | 76 self.rfile = BufferedReadFile(self.rfile) |
69 BaseHTTPServer.BaseHTTPRequestHandler.handle_one_request(self) | 77 BaseHTTPServer.BaseHTTPRequestHandler.handle_one_request(self) |
70 | 78 |
71 def do_POST(self): | 79 def do_POST(self): |
72 writer = sys.stdout | 80 RequestHandler.raw_request = self.rfile.buffer |
73 | |
74 writer.write(self.rfile.buffer) | |
75 self.rfile.buffer = '' | 81 self.rfile.buffer = '' |
76 | 82 |
77 if self.headers.get('Transfer-Encoding', '') == 'Chunked': | 83 if self.headers.get('Transfer-Encoding', '') == 'Chunked': |
78 body = self.handle_chunked_encoding() | 84 body = self.handle_chunked_encoding() |
79 else: | 85 else: |
80 length = int(self.headers.get('Content-Length', -1)) | 86 length = int(self.headers.get('Content-Length', -1)) |
81 body = self.rfile.read(length) | 87 body = self.rfile.read(length) |
82 | 88 |
| 89 RequestHandler.raw_request += body |
| 90 |
83 self.send_response(self.response_code) | 91 self.send_response(self.response_code) |
84 self.end_headers() | 92 self.end_headers() |
85 if self.response_code == 200: | 93 if self.response_code == 200: |
86 self.wfile.write(self.response_body) | 94 self.wfile.write(self.response_body) |
87 self.wfile.write('\r\n') | 95 self.wfile.write('\r\n') |
88 | 96 |
89 writer.write(body) | |
90 writer.flush() | |
91 | |
92 def handle_chunked_encoding(self): | 97 def handle_chunked_encoding(self): |
93 """This parses a "Transfer-Encoding: Chunked" body in accordance with | 98 """This parses a "Transfer-Encoding: Chunked" body in accordance with |
94 RFC 7230 §4.1. This returns the result as a string. | 99 RFC 7230 §4.1. This returns the result as a string. |
95 """ | 100 """ |
96 body = '' | 101 body = '' |
97 chunk_size = self.read_chunk_size() | 102 chunk_size = self.read_chunk_size() |
98 while chunk_size > 0: | 103 while chunk_size > 0: |
99 # Read the body. | 104 # Read the body. |
100 data = self.rfile.read(chunk_size) | 105 data = self.rfile.read(chunk_size) |
101 chunk_size -= len(data) | 106 chunk_size -= len(data) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 sys.stdout.flush() | 144 sys.stdout.flush() |
140 | 145 |
141 # Read the desired test response code as an unsigned short and the desired | 146 # Read the desired test response code as an unsigned short and the desired |
142 # response body as an 8-byte string from the parent process. | 147 # response body as an 8-byte string from the parent process. |
143 RequestHandler.response_code, RequestHandler.response_body = \ | 148 RequestHandler.response_code, RequestHandler.response_body = \ |
144 struct.unpack('=H8s', sys.stdin.read(struct.calcsize('=H8s'))) | 149 struct.unpack('=H8s', sys.stdin.read(struct.calcsize('=H8s'))) |
145 | 150 |
146 # Handle the request. | 151 # Handle the request. |
147 server.handle_request() | 152 server.handle_request() |
148 | 153 |
| 154 # Share the entire request with the test program, which will validate it. |
| 155 sys.stdout.write(RequestHandler.raw_request) |
| 156 sys.stdout.flush() |
| 157 |
149 if __name__ == '__main__': | 158 if __name__ == '__main__': |
150 Main() | 159 Main() |
OLD | NEW |