MCPcopy Create free account
hub / github.com/python-websockets/websockets / read_body

Function read_body

src/websockets/http11.py:380–438  ·  view source on GitHub ↗
(
    status_code: int,
    headers: Headers,
    read_line: Callable[[int], Generator[None, None, bytes | bytearray]],
    read_exact: Callable[[int], Generator[None, None, bytes | bytearray]],
    read_to_eof: Callable[[int], Generator[None, None, bytes | bytearray]],
)

Source from the content-addressed store, hash-verified

378
379
380def read_body(
381 status_code: int,
382 headers: Headers,
383 read_line: Callable[[int], Generator[None, None, bytes | bytearray]],
384 read_exact: Callable[[int], Generator[None, None, bytes | bytearray]],
385 read_to_eof: Callable[[int], Generator[None, None, bytes | bytearray]],
386) -> Generator[None, None, bytes | bytearray]:
387 # https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.3
388
389 # Since websockets only does GET requests (no HEAD, no CONNECT), all
390 # responses except 1xx, 204, and 304 include a message body.
391 if 100 <= status_code < 200 or status_code == 204 or status_code == 304:
392 return b""
393
394 # MultipleValuesError is sufficiently unlikely that we don't attempt to
395 # handle it when accessing headers. Instead we document that its parent
396 # class, LookupError, may be raised.
397 # Conversions from str to int are protected by sys.set_int_max_str_digits..
398
399 elif (coding := headers.get("Transfer-Encoding")) is not None:
400 if coding != "chunked":
401 raise NotImplementedError(f"transfer coding {coding} isn't supported")
402
403 body = b""
404 while True:
405 chunk_size_line = yield from parse_line(read_line)
406 raw_chunk_size = chunk_size_line.split(b";", 1)[0]
407 # Set a lower limit than default_max_str_digits; 1 EB is plenty.
408 if len(raw_chunk_size) > 15:
409 str_chunk_size = raw_chunk_size.decode(errors="backslashreplace")
410 raise SecurityError(f"chunk too large: 0x{str_chunk_size} bytes")
411 chunk_size = int(raw_chunk_size, 16)
412 if chunk_size == 0:
413 break
414 if len(body) + chunk_size > MAX_BODY_SIZE:
415 raise SecurityError(
416 f"chunk too large: {chunk_size} bytes after {len(body)} bytes"
417 )
418 body += yield from read_exact(chunk_size)
419 if (yield from read_exact(2)) != b"\r\n":
420 raise ValueError("chunk without CRLF")
421 # Read the trailer.
422 yield from parse_headers(read_line)
423 return body
424
425 elif (raw_content_length := headers.get("Content-Length")) is not None:
426 # Set a lower limit than default_max_str_digits; 1 EiB is plenty.
427 if len(raw_content_length) > 18:
428 raise SecurityError(f"body too large: {raw_content_length} bytes")
429 content_length = int(raw_content_length)
430 if content_length > MAX_BODY_SIZE:
431 raise SecurityError(f"body too large: {content_length} bytes")
432 return (yield from read_exact(content_length))
433
434 else:
435 try:
436 return (yield from read_to_eof(MAX_BODY_SIZE))
437 except RuntimeError:

Callers 1

parseMethod · 0.85

Calls 5

parse_lineFunction · 0.85
SecurityErrorClass · 0.85
parse_headersFunction · 0.85
getMethod · 0.45
decodeMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…