#[non_exhaustive]pub struct HttpRequest {
pub method: Method,
pub url: String,
pub headers: Headers,
pub body: Option<Bytes>,
pub timeout: Option<Duration>,
}Expand description
An HTTP request built by a provider.
Debug output redacts credential headers (see Headers).
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.method: MethodMethod.
url: StringAbsolute URL.
headers: HeadersHeaders, in order.
body: Option<Bytes>Body, if any.
timeout: Option<Duration>Bound on the whole exchange, when the provider sets one. Streaming requests usually leave it unset.
Implementations§
Source§impl HttpRequest
impl HttpRequest
Sourcepub fn sensitive_header(
self,
name: impl Into<String>,
value: impl Into<String>,
) -> Self
pub fn sensitive_header( self, name: impl Into<String>, value: impl Into<String>, ) -> Self
Add a header whose value is a secret: Debug output redacts it
whatever its name. For an adapter that places a credential itself
(CredentialPlacement::Custom).
Sourcepub fn with_headers(self, headers: &Headers) -> Self
pub fn with_headers(self, headers: &Headers) -> Self
Set each of headers, replacing the request’s headers of the same
name (ignoring case) and adding the others, in order. For the
headers a provider sends with every request: the bundled providers
set their DEFAULT_USER_AGENT and the builder’s own headers
(header(name, value), validated by config::static_headers)
with it, after their protocol headers and before
apply_options, so a request’s own headers
still win.
use allama_http::{Headers, HttpRequest};
let defaults: Headers = [("user-agent", "my-app/1.0"), ("x-route", "eu")].into_iter().collect();
let request = HttpRequest::post("https://api.example.com/v1/chat", "{}")
.header("User-Agent", "allama/0.1.0")
.with_headers(&defaults);
assert_eq!(request.headers.get("user-agent"), Some("my-app/1.0"));
assert_eq!(request.headers.iter().count(), 2);Sourcepub fn apply_options(
self,
options: &RequestOptions,
slot: &CredentialSlot,
) -> Result<Self>
pub fn apply_options( self, options: &RequestOptions, slot: &CredentialSlot, ) -> Result<Self>
Apply the caller’s transport options for this request: the
HttpRequestOptions in options, typed or in their JSON form,
with the credentials addressed to slot’s scope.
Call it once the request carries every header the adapter sets,
including its configured credential, and before sending it. Every
bundled HTTP adapter calls it with the options of the request it
serves and its own CredentialSlot, so callers get the same
behaviour from first- and third-party adapters. In order, it:
- refuses, before anything is sent, a plain header that would carry a credential (see Errors);
- replaces the request’s headers with the plain headers of the same name, and adds the others;
- places the
Credential::api_keyaddressed to the slot’s scope as the slot’s placement says, removing the configured credential and every header the slot replaces. ACustomslot is left alone: the adapter signs or places its credential after this call; - adds the
Credential::headervalues addressed to the scope, each replacing the headers of the same name.
Credentials addressed to other scopes are never sent. Placed
credentials are redacted from Debug whatever the header name.
use allama::ChatRequest;
use allama_http::{Credential, CredentialPlacement, CredentialSlot, HttpRequest, HttpRequestOptions};
let slot = CredentialSlot::new("anthropic", CredentialPlacement::Header("x-api-key".into()));
let request = ChatRequest::new("m").user("Hi").with_option(
HttpRequestOptions::new()
.credential("anthropic", Credential::api_key("tenant-key"))
.credential("openai", Credential::api_key("other-account"))
.header("x-tenant-id", "acme"),
);
let http = HttpRequest::post("https://api.example.com/v1/messages", "{}")
.header("x-api-key", "provider-key")
.apply_options(&request.options, &slot)?;
assert_eq!(http.headers.get("x-api-key"), Some("tenant-key"));
assert_eq!(http.headers.get("x-tenant-id"), Some("acme"));
assert!(!format!("{http:?}").contains("other-account"));§Errors
allama::Error::InvalidRequestwhen the JSON form of the options is malformed, names a header on the exact credential list (is_credential_header), or sets credentials.- An authored
allama::Error::Configuration, before anything is sent, when a plain header is named on the exact credential list (is_credential_header) or is one the slot writes or replaces, or when the slot is required and no credential is addressed to its scope. These are the application’s bugs, not the end user’s, so they are not retried, never fall over to another provider, and map to a server error. Error text names headers and scopes, never secrets.