Response
An HTTP response.
A response may hold an open connection while its body is still pending, so it
owns a resource until it is closed. Every method that reads the body whole --
body, text,
json -- consumes the response and
closes it; the streaming methods hand ownership of the body to the iterator
they return. Once closed, most methods raise.
The reliable way to bound that lifetime is the trailing block a request accepts, which closes the response however the block exits:
Fields
headers @ Map[Str, Str | time.DateTime][get]The response headers.
A value that parses as an HTTP-date is returned as a
time.DateTime; every other value is aStr.Example
status @ Int[get]The HTTP status code.
url @ url.Url[get]The final URL, after any redirects.
Methods
body() -> Bin
Reads the whole body as bytes.
Reading the body consumes it: body, text, json, io, chunks and
lines each take it, and a second raises StateError.
The status and headers stay readable until the response is closed.
chunks() -> Iter[Bin]
Streams the body as byte chunks of at most 64 KiB each, as
io().chunks() does, so a large response need not be held
in memory whole.
Example
get https://api.example.com/large-file do |response|
let total = 0
for chunk = response.chunks()
total = (total + chunk.len)
echo "Downloaded $total bytes"
close()
Closes the response, releasing the connection, and closes any stream
io, chunks or lines returned.
Closing an already-closed response does nothing.
events() -> Iter[Event]
Streams the body as a Server-Sent Events stream -- the shape LLM responses,
log tails and other text/event-stream feeds arrive in.
Errors
| Exception | Condition |
|---|---|
StateError |
The body was read or the response closed |
Error |
The underlying body read fails |
DataError |
The stream contains invalid UTF-8 |
Example
http.get https://api.example.com/stream do |response|
for :type :data ... = response.events()
echo "[$type] $data"
io() -> io.Io
Returns the body as a byte stream.
The stream can be passed to any function that accepts an io.Io,
such as compress.decompress. Closing the response
closes it.
A failure reading the body raises from the stream's methods as an I/O
error, not an Error.
Example
get https://example.com/data.gz do |response|
compress.decompress $response.io() do |stream|
echo (stream.read_all_str())
json() -> json.DecodeValue
Reads the whole body and parses it as JSON.
Errors
| Exception | Condition |
|---|---|
StateError |
The body was read or the response closed |
Error |
A transport or protocol failure |
DataError |
The body is not valid JSON |
Example
let response = get https://api.example.com/users
let data = response.json()
echo $data["users"][0]["name"]
lines() -> Iter[Str]
Streams the body as lines, split on \n or \r\n with the line ending
stripped.
The lines are read through an io.Buffered over
io().
Example
get https://api.example.com/logs do |response|
for line = response.lines()
if (line.contains "ERROR")
echo $line
text() -> Str
Reads the whole body as text, replacing invalid UTF-8 with U+FFFD.
Errors
| Exception | Condition |
|---|---|
StateError |
The body was read or the response closed |
Error |
A transport or protocol failure |
throw_for_status()
Raises Status when the status is outside 200..=299, and
does nothing otherwise.
This is what a request does for you unless status: :IGNORE: was passed,
so it is only needed on a response fetched with the check suppressed.