Module response
Expand description
Set a header on the response.
The header value to be set may be provided as a fixed value when the
middleware is constructed, or determined dynamically based on the response
by a closure. See the MakeHeaderValue
trait for details.
§Example
Setting a header from a fixed value provided when the middleware is constructed:
use rama_http::layer::set_header::SetResponseHeaderLayer;
use rama_http::{Body, Request, Response, header::{self, HeaderValue}};
use rama_core::service::service_fn;
use rama_core::{Context, Service, Layer};
use rama_core::error::BoxError;
let mut svc = (
// Layer that sets `Content-Type: text/html` on responses.
//
// `if_not_present` will only insert the header if it does not already
// have a value.
SetResponseHeaderLayer::if_not_present(
header::CONTENT_TYPE,
HeaderValue::from_static("text/html"),
),
).layer(render_html);
let request = Request::new(Body::empty());
let response = svc.serve(Context::default(), request).await?;
assert_eq!(response.headers()["content-type"], "text/html");
Setting a header based on a value determined dynamically from the response:
use rama_core::error::BoxError;
use rama_core::service::service_fn;
use rama_core::{Context, Layer, Service};
use rama_http::dep::http_body::Body as _;
use rama_http::layer::set_header::SetResponseHeaderLayer;
use rama_http::{
header::{self, HeaderValue},
Body, Request, Response,
};
#[tokio::main]
async fn main() -> Result<(), BoxError> {
let render_html = service_fn(|_request: Request| async move {
Ok::<_, std::convert::Infallible>(Response::new(Body::from("1234567890")))
});
let svc = (
// Layer that sets `Content-Length` if the body has a known size.
// Bodies with streaming responses wont have a known size.
//
// `overriding` will insert the header and override any previous values it
// may have.
SetResponseHeaderLayer::overriding_fn(
header::CONTENT_LENGTH,
|response: Response| async move {
let value = if let Some(size) = response.body().size_hint().exact() {
// If the response body has a known size, returning `Some` will
// set the `Content-Length` header to that value.
Some(HeaderValue::from_str(&size.to_string()).unwrap())
} else {
// If the response body doesn't have a known size, return `None`
// to skip setting the header on this response.
None
};
(response, value)
},
),
)
.layer(render_html);
let request = Request::new(Body::empty());
let response = svc.serve(Context::default(), request).await?;
assert_eq!(response.headers()["content-length"], "10");
Ok(())
}
Setting a header based on the incoming Context and response combined.
use rama_core::{service::service_fn, Context, Service};
use rama_http::{
layer::set_header::{response::BoxMakeHeaderValueFn, SetResponseHeader},
Body, HeaderName, HeaderValue, IntoResponse, Request, Response,
};
use std::convert::Infallible;
#[tokio::main]
async fn main() {
#[derive(Debug, Clone)]
struct RequestID(String);
#[derive(Debug, Clone)]
struct Success;
let svc = SetResponseHeader::overriding_fn(
service_fn(|| async {
let mut res = ().into_response();
res.extensions_mut().insert(Success);
Ok::<_, Infallible>(res)
}),
HeaderName::from_static("x-used-request-id"),
|ctx: Context<()>| async move {
let factory = ctx.get::<RequestID>().cloned().map(|id| {
BoxMakeHeaderValueFn::new(move |res: Response| async move {
let header_value = res.extensions().get::<Success>().map(|_| {
HeaderValue::from_str(id.0.as_str()).unwrap()
});
(res, header_value)
})
});
(ctx, factory)
},
);
const FAKE_USER_ID: &str = "abc123";
let mut ctx = Context::default();
ctx.insert(RequestID(FAKE_USER_ID.to_owned()));
let res = svc.serve(ctx, Request::new(Body::empty())).await.unwrap();
let mut values = res
.headers()
.get_all(HeaderName::from_static("x-used-request-id"))
.iter();
assert_eq!(values.next().unwrap(), FAKE_USER_ID);
assert_eq!(values.next(), None);
}
Structs§
- The public wrapper type for [
MakeHeaderValueFactoryFn
]. - The public wrapper type for [
MakeHeaderValueFn
]. - Middleware that sets a header on the response.
- Layer that applies
SetResponseHeader
which adds a response header.
Traits§
- Trait for producing header values, created by a
MakeHeaderValueFactory
. - Trait for preparing a maker (
MakeHeaderValue
) that will be used to actually create theHeaderValue
when desired.