Skip to main content

HttpResponse

Struct HttpResponse 

Source
#[non_exhaustive]
pub struct HttpResponse { pub status: u16, pub headers: Headers, /* private fields */ }
Expand description

An HTTP response: status and headers, then a streamed body.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§status: u16

Status code.

§headers: Headers

Headers.

Implementations§

Source§

impl HttpResponse

Source

pub fn new(status: u16, headers: Headers, body: Body) -> Self

A response with a streamed body.

Source

pub fn from_bytes(status: u16, headers: Headers, body: impl Into<Bytes>) -> Self

A response with the whole body at once.

Source

pub fn is_success(&self) -> bool

Returns true for 2xx statuses.

Source

pub async fn bytes(self) -> Result<Bytes, TransportError>

Read the whole body, however large.

For a response from a server you do not control, read with bytes_limited instead: a broken or hostile server can send a body that does not fit in memory.

§Errors

The transport failed while the body was read.

Source

pub async fn text(self) -> Result<String, TransportError>

Read the whole body as text (invalid UTF-8 is replaced), however large. See bytes; prefer text_limited.

§Errors

The transport failed while the body was read.

Source

pub async fn bytes_limited(self, limit: usize) -> Result<Bytes, TransportError>

Read the whole body, failing as soon as it passes limit bytes. The bundled providers read success bodies with it, under the builder’s max_response_size (default DEFAULT_MAX_RESPONSE_SIZE).

The buffer never grows past limit: the chunk that would take it past is refused before it is copied, and the rest of the body is never read.

use allama_http::{Headers, HttpResponse, TransportErrorKind};

let response = HttpResponse::from_bytes(200, Headers::new(), "0123456789");
let err = response.bytes_limited(4).await.unwrap_err();
assert_eq!(err.kind(), TransportErrorKind::TooLarge);
assert!(matches!(err.into_error(), allama::Error::UnexpectedResponse { .. }));
§Errors
Source

pub async fn text_limited(self, limit: usize) -> Result<String, TransportError>

Read the whole body as text (invalid UTF-8 is replaced), failing as soon as it passes limit bytes, as bytes_limited does.

§Errors

See bytes_limited.

Source

pub async fn map_error( self, map: impl FnOnce(u16, &Headers, &str) -> Error, ) -> Error

The error for an error response (one that is not a success): reads the start of its body for diagnostics and maps the status, headers and body text with map, the adapter’s own classification.

Every bundled HTTP provider maps its error responses here, so these rules hold on all of them:

  • The body read is bounded. At most MAX_ERROR_BODY_SIZE bytes are read, within ERROR_BODY_TIMEOUT; the rest of the body is never read. An error keeps only the first ErrorContext::MAX_BODY_BYTES of it anyway, and a streaming request has no total deadline, so an unbounded read of a body that never ends would hang the call and grow without limit.
  • A failed read is recorded, not hidden. map gets the text read before the failure, and the failure (a transport error, or the time bound) is added to the error’s upstream message.
  • A redirect is never followed. A 3xx is the redirect_error for the response, and map is not called: an LLM API never answers a request with a redirect, and following one would send the request, credentials included, somewhere the application never configured.
use allama::Error;
use allama_http::{HttpResponse, Headers, error_context, status_error};

let map = |status: u16, headers: &Headers, body: &str| {
    status_error(status, format!("HTTP {status}"))
        .with_context(error_context(status, headers))
        .authored()
        .with_body(body.to_owned())
};

let response = HttpResponse::from_bytes(429, Headers::new(), "slow down");
let err = response.map_error(map).await;
assert!(matches!(err, Error::RateLimited { .. }));
assert_eq!(err.context().and_then(|c| c.capped_body()), Some("slow down"));

let headers = [("location", "https://elsewhere.example/v1/chat")].into_iter().collect();
let redirect = HttpResponse::from_bytes(307, headers, "");
let err = redirect.map_error(map).await;
assert!(matches!(err, Error::UnexpectedResponse { .. }));
assert!(err.to_string().contains("elsewhere.example"));
Source

pub fn into_body(self) -> Body

The body as a stream of chunks (for SSE).

Trait Implementations§

Source§

impl Debug for HttpResponse

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more