ASGI response sending — translates chirp Response types to ASGI messages.
Handles both standard single-body responses and chunked streaming responses.
server.sender
| Name | Type | Default | Description |
|---|---|---|---|
type
|
|
— | |
qualified_name
|
|
— | |
element_type
|
|
— | |
description
|
|
— | |
source_file
|
|
— | |
line_number
|
|
— | |
is_autodoc
|
|
— | |
autodoc_element
|
|
— | |
_autodoc_template
|
|
— | |
_autodoc_url_path
|
|
— | |
_autodoc_page_type
|
|
— | |
title
|
|
— | |
doc_content_hash
|
|
— |
Symbols on this page
Whether an HTTP status code permits a response body.
Structural view of the response objects the early-hint helpers read.
BothResponseand
StreamingResponse expose headersas a
tuple of(name, value)pairs; the…
True when aLink header value carries a 103-worthy rel=token.
Parses only therelparameter(s); a single Link header may declare more than…
CollectLinkheaders eligible for a 103 Early Hints frame.
Reads theLinkheaders already present on response(the header convention — no new…
Emit a preliminary103 Early Hintsstart frame, if warranted.
pounce 0.8.0 surfaces 103 purely as a status convention on
http.response.start: it never…
Translate a chirp Response into ASGI send() calls.
Send a streaming response via chunked transfer encoding.
Sends headers immediately, then each chunk as an ASGI body
message withmore_body=True. Closes with…
Format a POSIX timestamp as an RFC 7231 IMF-fixdate string.
Return True if anIf-Rangevalidator still matches the representation.
Per RFC 9110 §13.1.5 the value is eitheran entity-tag or an HTTP-date. An…
Parse a singlebytes=Range spec.
Send aFileResponsefrom disk with conditional-GET / Range support.
Streams the body inchunk_sizereads off the event loop via
run_sync() (matching…
Cache-Control header value, defaulting when not set on the response.
_body_allowed
function
def _body_allowed(status: int) -> bool
Whether an HTTP status code permits a response body.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
status
|
int
|
— |
_HasHeaders
class
Structural view of the response objects the early-hint helpers read.
BothResponseand
StreamingResponse expose headersas a
tuple of(name, value)pairs; the early-hint collector only needs that.
_is_early_hint_link
function
def _is_early_hint_link(value: str) -> bool
True when aLink header value carries a 103-worthy rel=token.
Parses only therelparameter(s); a single Link header may declare more
than one relation (rel="preconnect dns-prefetch") so each token is
checked. Matching is case-insensitive per RFC 8288.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
value
|
str
|
— |
_early_hint_headers
function
def _early_hint_headers(response: _HasHeaders) -> list[tuple[bytes, bytes]]
CollectLinkheaders eligible for a 103 Early Hints frame.
Reads theLinkheaders already present on response (the header
convention — no new public surface) and returns the latin-1-encoded
(b"link", value) pairs whose rel=is asset-preload-class. Returns an
empty list when nothing is eligible, in which case no 103 frame is emitted.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
response
|
_HasHeaders
|
— |
_maybe_send_early_hints
function
async
async def _maybe_send_early_hints(response: _HasHeaders, send: Send) -> None
Emit a preliminary103 Early Hintsstart frame, if warranted.
pounce 0.8.0 surfaces 103 purely as a status convention on
http.response.start: it never auto-derives the hint from the final
response'sLinkheaders (the H1/H2/H3 bridges only special-case
status == 103). So Chirp must explicitly send the interim frame before
the final start. The sameLinkheaders remain on the final response —
RFC 8297 treats the 103 hint as advisory and the canonicalLinkheader
still belongs on the final message.
The interim frame carries no body and does not flip pounce's
response_started, so the final response flows normally over H1/H2/H3.
On the buffering sync path pounce raisesNeedsAsyncErrorfor any 1xx
start and re-runs the request on the async worker, so this is safe there too.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
response
|
_HasHeaders
|
— | |
send
|
Send
|
— |
send_response
function
async
async def send_response(response: Response, send: Send, *, request_id: str | None = None) -> None
Translate a chirp Response into ASGI send() calls.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
response
|
Response
|
— | |
send
|
Send
|
— | |
request_id
|
str | None
|
None
|
send_streaming_response
function
async
async def send_streaming_response(response: StreamingResponse, send: Send, *, debug: bool = False, request_id: str | None = None) -> None
Send a streaming response via chunked transfer encoding.
Sends headers immediately, then each chunk as an ASGI body
message withmore_body=True. Closes with an empty body.
On mid-stream error, emits an HTML comment and closes.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
response
|
StreamingResponse
|
— | |
send
|
Send
|
— | |
debug
|
bool
|
False
|
|
request_id
|
str | None
|
None
|
_format_http_date
function
def _format_http_date(timestamp: float) -> str
Format a POSIX timestamp as an RFC 7231 IMF-fixdate string.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
timestamp
|
float
|
— |
_if_range_matches
function
def _if_range_matches(if_range: str, etag: str, last_modified: str) -> bool
Return True if anIf-Rangevalidator still matches the representation.
Per RFC 9110 §13.1.5 the value is either an entity-tag or an HTTP-date.
An entity-tag is compared with the strong comparison function (a weak
validator on either side never matches), and an HTTP-date matches only when
it is byte-for-byte the currentLast-Modifiedvalue. When the validator
no longer matches the caller must ignoreRangeand serve the full 200
representation.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
if_range
|
str
|
— | |
etag
|
str
|
— | |
last_modified
|
str
|
— |
_parse_single_range
function
def _parse_single_range(range_header: str, size: int) -> tuple[int, int] | bool | None
Parse a singlebytes=Range spec.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
range_header
|
str
|
— | |
size
|
int
|
— |
send_file_response
function
async
async def send_file_response(response: FileResponse, send: Send, *, request: Any = None, is_head: bool = False, request_id: str | None = None) -> None
Send aFileResponsefrom disk with conditional-GET / Range support.
Streams the body inchunk_sizereads off the event loop via
run_sync() (matching the data/cache to_thread precedent).
Files smaller thanstream_thresholdare read in a single shot to keep
small-file latency unchanged; larger files stream chunk-by-chunk so worker
RSS stays bounded.
HonoursIf-None-Match(weak compare, takes precedence) and
If-Modified-Since -> 304, and a single byte Range-> 206 (416 when
unsatisfiable) whenresponse.conditionalis True.
On mid-stream IO error the stream is closed without an HTML error body — you cannot inject markup into a half-sent binary payload.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
response
|
FileResponse
|
— | |
send
|
Send
|
— | |
request
|
Any
|
None
|
|
is_head
|
bool
|
False
|
|
request_id
|
str | None
|
None
|
_cache_control_or_default
function
def _cache_control_or_default(response: FileResponse) -> bytes
Cache-Control header value, defaulting when not set on the response.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
response
|
FileResponse
|
— |
View source · /home/runner/work/chirp/chirp/site/../src/chirp/server/sender.py:1