Check if the body size exceeds limits imposed by stream_large_bodies or body_size_limit. Returns `True` if the body size exceeds body_size_limit and further processing should be stopped.
(self, request: bool)
| 566 | yield SendHttp(ResponseEndOfMessage(self.stream_id), self.context.client) |
| 567 | |
| 568 | def check_body_size(self, request: bool) -> layer.CommandGenerator[bool]: |
| 569 | """ |
| 570 | Check if the body size exceeds limits imposed by stream_large_bodies or body_size_limit. |
| 571 | |
| 572 | Returns `True` if the body size exceeds body_size_limit and further processing should be stopped. |
| 573 | """ |
| 574 | if not ( |
| 575 | self.context.options.stream_large_bodies |
| 576 | or self.context.options.body_size_limit |
| 577 | ): |
| 578 | return False |
| 579 | |
| 580 | # Step 1: Determine the expected body size. This can either come from a known content-length header, |
| 581 | # or from the amount of currently buffered bytes (e.g. for chunked encoding). |
| 582 | response = not request |
| 583 | expected_size: int | None |
| 584 | # the 'late' case: we already started consuming the body |
| 585 | if request and self.request_body_buf: |
| 586 | expected_size = len(self.request_body_buf) |
| 587 | elif response and self.response_body_buf: |
| 588 | expected_size = len(self.response_body_buf) |
| 589 | else: |
| 590 | # the 'early' case: we have not started consuming the body |
| 591 | try: |
| 592 | expected_size = expected_http_body_size( |
| 593 | self.flow.request, self.flow.response if response else None |
| 594 | ) |
| 595 | except ValueError: # pragma: no cover |
| 596 | # we just don't stream/kill malformed content-length headers. |
| 597 | expected_size = None |
| 598 | |
| 599 | if expected_size is None or expected_size <= 0: |
| 600 | return False |
| 601 | |
| 602 | # Step 2: Do we need to abort this? |
| 603 | max_total_size = human.parse_size(self.context.options.body_size_limit) |
| 604 | if max_total_size is not None and expected_size > max_total_size: |
| 605 | if request and not self.request_body_buf: |
| 606 | yield HttpRequestHeadersHook(self.flow) |
| 607 | if response and not self.response_body_buf: |
| 608 | yield HttpResponseHeadersHook(self.flow) |
| 609 | |
| 610 | err_msg = f"{'Request' if request else 'Response'} body exceeds mitmproxy's body_size_limit." |
| 611 | err_code = ( |
| 612 | ErrorCode.REQUEST_TOO_LARGE if request else ErrorCode.RESPONSE_TOO_LARGE |
| 613 | ) |
| 614 | |
| 615 | self.flow.error = flow.Error(err_msg) |
| 616 | yield HttpErrorHook(self.flow) |
| 617 | yield SendHttp( |
| 618 | ResponseProtocolError(self.stream_id, err_msg, err_code), |
| 619 | self.context.client, |
| 620 | ) |
| 621 | self.client_state = self.state_errored |
| 622 | if response: |
| 623 | yield SendHttp( |
| 624 | RequestProtocolError(self.stream_id, err_msg, err_code), |
| 625 | self.context.server, |
no test coverage detected