| 329 | return write |
| 330 | |
| 331 | def execute(app: WSGIApplication) -> None: |
| 332 | application_iter = app(environ, start_response) |
| 333 | try: |
| 334 | for data in application_iter: |
| 335 | write(data) |
| 336 | if not headers_sent: |
| 337 | write(b"") |
| 338 | if chunk_response: |
| 339 | self.wfile.write(b"0\r\n\r\n") |
| 340 | finally: |
| 341 | # Check for any remaining data in the read socket, and discard it. This |
| 342 | # will read past request.max_content_length, but lets the client see a |
| 343 | # 413 response instead of a connection reset failure. If we supported |
| 344 | # keep-alive connections, this naive approach would break by reading the |
| 345 | # next request line. Since we know that write (above) closes every |
| 346 | # connection we can read everything. |
| 347 | selector = selectors.DefaultSelector() |
| 348 | selector.register(self.connection, selectors.EVENT_READ) |
| 349 | total_size = 0 |
| 350 | total_reads = 0 |
| 351 | |
| 352 | # A timeout of 0 tends to fail because a client needs a small amount of |
| 353 | # time to continue sending its data. |
| 354 | while selector.select(timeout=0.01): |
| 355 | # Only read 10MB into memory at a time. |
| 356 | data = self.rfile.read(10_000_000) |
| 357 | total_size += len(data) |
| 358 | total_reads += 1 |
| 359 | |
| 360 | # Stop reading on no data, >=10GB, or 1000 reads. If a client sends |
| 361 | # more than that, they'll get a connection reset failure. |
| 362 | if not data or total_size >= 10_000_000_000 or total_reads > 1000: |
| 363 | break |
| 364 | |
| 365 | selector.close() |
| 366 | |
| 367 | if hasattr(application_iter, "close"): |
| 368 | application_iter.close() |
| 369 | |
| 370 | try: |
| 371 | execute(self.server.app) |