Skip to main content

HttpRequestOptions

Struct HttpRequestOptions 

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

Transport options for one request: HTTP headers and credentials to send with it.

Attach them to a ChatRequest, EmbeddingRequest or DecisionRequest like any options. Every bundled HTTP adapter applies them with HttpRequest::apply_options, and so should third-party ones. Use them for gateway tags (tenant, route, trace, a request id), and for per-tenant credentials:

use allama::ChatRequest;
use allama_http::{Credential, HttpRequestOptions};

let request = ChatRequest::new("gpt-4o-mini").user("Hi").with_option(
    HttpRequestOptions::new()
        .header("x-tenant-id", "acme")
        .credential("openai", Credential::api_key("sk-tenant-key")),
);

§From a wrapper

Header and credential injection happen at the transport, and these options are how a wrapper reaches it: a wrapper sees the portable request, never the HTTP request (ADR 0013). A wrapper that tags every call, with a request id header for example, adds its header to the options the request already carries, through ChatRequest::option_mut, so the caller’s headers and credentials survive; a fresh HttpRequestOptions given to with_option would replace them.

use allama::ChatRequest;
use allama_http::{Credential, HttpRequestOptions};

fn tag(request: &ChatRequest, request_id: &str) -> ChatRequest {
    let mut request = request.clone();
    match request.option_mut::<HttpRequestOptions>() {
        Some(options) => options.headers.insert("x-request-id", request_id),
        None => {
            let options = HttpRequestOptions::new().header("x-request-id", request_id);
            request = request.with_option(options);
        }
    }
    request
}

let request = ChatRequest::new("m").user("Hi").with_option(
    HttpRequestOptions::new().credential("openai", Credential::api_key("sk-tenant")),
);
let tagged = tag(&request, "req-1");
let options = tagged.option::<HttpRequestOptions>().unwrap();
assert_eq!(options.headers.get("x-request-id"), Some("req-1"));
assert!(options.credential_for("openai").is_some(), "the caller's key survives");

§Headers

A header given here replaces every header of the same name (ignoring case) that the adapter set; headers with other names are added. A plain header never carries a credential: one named on the exact credential list (is_credential_header), or one the adapter’s CredentialSlot writes or replaces, is refused before anything is sent.

§Credentials

credential addresses a Credential to a credential scope: the account it belongs to. Only the adapter whose CredentialSlot has that scope sends it, so in a fallback chain each provider gets its own key and no other. Bundled adapters default their scope to their provider name (openai, anthropic, groq, …), each crate publishes it as DEFAULT_CREDENTIAL_SCOPE, and their builders change it with credential_scope.

  • The scope’s Credential::api_key replaces the key the adapter was configured with. An adapter configured with a key still sends its own key when no credential is addressed to its scope, so a mistyped scope falls back to the configured key; an adapter built without a key refuses such a request instead.
  • A Credential::header is added to requests for its scope, replacing a configured header of the same name.

Two accounts of one provider in a fallback chain need two scopes: by default they share one, and both would send the same key.

Which hops are protected: plain headers are refused by each adapter as it sends, so a plain header that only one adapter owns (x-nimbus-key) still reaches the providers tried before it in a fallback chain. Only the exact credential list protects every hop. Send third-party keys as a Credential::header addressed to their scope.

§Secrets stay in the process

  • Debug output redacts credentials and credential headers (the names is_sensitive_header matches), as for Headers.
  • Serialization omits credentials and the headers on the exact credential list (is_credential_header), so a serialized request, a RecordingProvider exchange, or a fixture never holds them. A request rebuilt from one carries no credentials. Two requests that differ only in credentials compare equal.
  • The JSON form (with_options_json("allama-http", ..)) rejects them with Error::InvalidRequest: JSON options are exported and printed as given. Set credentials with the typed value.

Every other header is a plain header, exported and accepted in the JSON form as given, even one whose name only looks like a credential (Idempotency-Key, x-gateway-token): an idempotency key must survive a recording and a replay. Debug still redacts those by name. A secret belongs in a Credential::header, never in a plain header.

Adapters never put header values on tracing spans.

§JSON form

{"headers": {"x-tenant-id": "acme"}} under OPTIONS_NAMESPACE. A header given more than once is exported once, with its values joined by ", ".

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.
§headers: Headers

Headers to send, in order. Each replaces the adapter’s headers of the same name.

Implementations§

Source§

impl HttpRequestOptions

Source

pub fn new() -> Self

No options.

Source

pub fn header(self, name: impl Into<String>, value: impl Into<String>) -> Self

Add a header to send.

A header that carries a credential is refused when the request is sent; use credential for those.

Source

pub fn credential( self, scope: impl Into<String>, credential: Credential, ) -> Self

Address credential to the credential scope scope.

It replaces the scope’s earlier credential of the same kind: its Credential::api_key, or its Credential::header of the same name.

Source

pub fn credential_for(&self, scope: &str) -> Option<&Credential>

The credential addressed to scope that the adapter places itself: its Credential::api_key (header credentials are added by HttpRequest::apply_options).

An adapter with a CredentialPlacement::Custom slot reads its credential here, after apply_options.

Source

pub fn credentials(&self) -> impl Iterator<Item = (&str, &Credential)>

Every credential, with the scope it is addressed to, in order.

Trait Implementations§

Source§

impl Clone for HttpRequestOptions

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for HttpRequestOptions

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for HttpRequestOptions

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for HttpRequestOptions

Reads the JSON form, which takes no credentials.

Source§

fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>

Deserialize this value from the given Serde deserializer. Read more
Source§

impl ProviderOptions for HttpRequestOptions

Source§

const NAMESPACE: &'static str = OPTIONS_NAMESPACE

Namespace of the JSON form, e.g. "openai".
Source§

impl Serialize for HttpRequestOptions

Writes the plain headers; credentials and the headers on the exact credential list are omitted.

Source§

fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>

Serialize this value into the given Serde serializer. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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