pub fn error_context(status: u16, headers: &Headers) -> ErrorContextExpand description
The diagnostic context of an HTTP error response, read from its status and headers:
status;request_idfromx-request-idorrequest-id;retry_afterfromRetry-Afterorretry-after-ms(seeHeaders::retry_after);server_retry_directivefromx-should-retry: trueorfalse; any other value is no directive.
Every bundled HTTP provider builds its error context here, so a header
rule added later reaches third-party providers that call it too. Attach
it with Error::with_context, which merges: it sets the fields read
here, keeps the others, and never changes the
message origin. A provider that names its request id
or retry hint header differently sets that field after attaching this
context (with_request_id, with_retry_after), so a standard header
does not overwrite it.
use allama::Error;
use allama_http::{Headers, error_context, error_envelope, status_error};
fn map_http_error(status: u16, headers: &Headers, body: &str) -> Error {
let error = status_error(status, format!("HTTP {status}"));
error_envelope(body)
.unwrap_or_default()
.apply(error.with_context(error_context(status, headers)).authored())
.with_body(body.to_owned())
}
let headers: Headers = [
("x-request-id", "req_1"),
("retry-after", "2"),
("x-should-retry", "false"),
]
.into_iter()
.collect();
let err = map_http_error(429, &headers, r#"{"error": {"message": "slow down"}}"#);
assert_eq!(err.status(), Some(429));
assert_eq!(err.request_id(), Some("req_1"));
assert_eq!(err.retry_after(), Some(std::time::Duration::from_secs(2)));
assert_eq!(err.server_retry_directive(), Some(false));
assert_eq!(err.upstream_message(), Some("slow down"));