Skip to content

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:

get https://api.example.com/users do |response|
  echo $response.status

A response can itself be called with a block, for the same effect on one the caller already holds:

let response = get https://api.example.com/users
response do
  echo $response.status

Fields

headers @ Dict[Str, Str | time.DateTime]

The response headers.

A value that parses as an HTTP-date is returned as a time.DateTime; every other value is a Str.

Example
let response = get https://api.example.com/users
echo $response.headers["content-type"]
status @ Int

The HTTP status code.

url @ url.Url

The final URL, after any redirects.

Methods

body() -> Bin

Reads the whole body as bytes, consuming and closing the response.

chunks() -> Iter[Bin]

Streams the body as raw byte chunks, 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.

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
RuntimeError The response is already closed
Error The underlying body read fails
ValueError The stream contains invalid UTF-8

Example

http.get https://api.example.com/stream do |response|
  for :type :data ... = response.events()
    echo "[$type] $data"

json() -> json.Data

Reads the whole body and parses it as JSON, consuming and closing the response.

Available when the extension is built with its json feature.

Errors

Exception Condition
RuntimeError The response is already closed
Error A transport or protocol failure
ValueError 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.

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, consuming and closing the response.

Errors

Exception Condition
RuntimeError The response is already closed
Error A transport or protocol failure
ValueError The body is not valid UTF-8

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.