Nous.Providers.HTTP (nous v0.13.3)
View SourceShared HTTP utilities for all LLM providers.
Provides both non-streaming (Req) and streaming (Finch) HTTP capabilities with provider-agnostic SSE (Server-Sent Events) parsing.
Usage
# Non-streaming request
{:ok, body} = HTTP.post(url, body, headers)
# Streaming request (returns lazy stream)
{:ok, stream} = HTTP.stream(url, body, headers)
Enum.each(stream, &process_event/1)SSE Parsing
SSE events follow the Server-Sent Events spec (https://html.spec.whatwg.org/multipage/server-sent-events.html):
- Events are separated by double newlines (
\n\n) - Each event contains field lines like
data: {...} - Multiple
data:fields are concatenated with newlines [DONE]signals stream completion (OpenAI convention)
Summary
Functions
Build authorization header for API key auth (Anthropic style).
Build authorization header for Bearer token auth (OpenAI style).
Parse an SSE buffer into events.
Parse a single SSE event.
Make a non-streaming POST request.
Make a streaming POST request with SSE parsing.
Functions
Build authorization header for API key auth (Anthropic style).
Returns empty list for nil or empty string values.
Build authorization header for Bearer token auth (OpenAI style).
Returns empty list for nil, empty string, or "not-needed" values.
Parse an SSE buffer into events.
Returns {events, remaining_buffer} where events is a list of parsed
JSON maps, {:stream_done, reason} tuples, or {:parse_error, reason} tuples.
Handles edge cases:
- Empty events (ignored)
- Whitespace-only events (ignored)
- Malformed JSON (emits
{:parse_error, reason}) - Multiple data fields per event (concatenated per spec)
- Comment lines (ignored)
- Buffer overflow protection
Examples
iex> parse_sse_buffer("data: {\"text\": \"hi\"}\n\n")
{[%{"text" => "hi"}], ""}
iex> parse_sse_buffer("data: partial")
{[], "data: partial"}
iex> parse_sse_buffer("data: [DONE]\n\n")
{[{:stream_done, "stop"}], ""}
@spec parse_sse_event(String.t()) :: map() | {:stream_done, String.t()} | {:parse_error, term()} | nil
Parse a single SSE event.
Returns parsed JSON map, {:stream_done, reason}, {:parse_error, reason}, or nil.
Handles per SSE spec:
data:fields (with or without space after colon)- Multiple
data:fields concatenated with newlines :prefix for comments (ignored)event:,id:,retry:fields (ignored for now)- Empty lines within events
Examples
iex> parse_sse_event("data: {\"key\": \"value\"}")
%{"key" => "value"}
iex> parse_sse_event("data: [DONE]")
{:stream_done, "stop"}
iex> parse_sse_event(": this is a comment")
nil
iex> parse_sse_event("")
nil
Make a non-streaming POST request.
Returns {:ok, body} or {:error, reason}.
Options
:timeout- Request timeout in ms (default: 60_000)
Error Reasons
%{status: integer(), body: term()}- HTTP error response%Mint.TransportError{}- Network error%JSON.DecodeError{}- JSON decode error
Make a streaming POST request with SSE parsing.
Returns {:ok, stream} where stream is an Enumerable of parsed events.
Events are maps with string keys (parsed JSON) or {:stream_done, reason} tuples.
Options
:timeout- Request timeout in ms (default: 60_000):finch_name- Finch pool name (default: Nous.Finch):stream_parser- Module for parsing the stream buffer (default: SSE parsing). Must implementparse_buffer/1returning{events, remaining_buffer}. SeeNous.Providers.HTTP.JSONArrayParserfor an example.
Error Handling
The stream will emit {:stream_error, reason} on errors and then halt.