Skip to main content

Response

Struct Response 

Source
pub struct Response {
    pub status: StatusCode,
    pub headers: HeaderMap,
    pub body: Body,
}
Expand description

A fully-buffered HTTP response: status line, headers, and an in-memory body.

The three fields are public so middleware can post-process a response (for example inserting a header). Construct one with Response::new (status only), Response::text (a text/plain body), or Response::bytes (an arbitrary content type), then refine it with the chainable with_status and with_header builders. Most handlers return an IntoResponse value instead of building this directly.

use churust_core::Response;
use http::StatusCode;

let res = Response::text("created").with_status(StatusCode::CREATED);
assert_eq!(res.status, StatusCode::CREATED);
assert_eq!(res.body.as_slice(), Some(&b"created"[..]));

Fields§

§status: StatusCode

The HTTP status code of the response.

§headers: HeaderMap

The response headers.

§body: Body

The response body — buffered bytes or a lazy stream.

Implementations§

Source§

impl Response

Source

pub fn new(status: StatusCode) -> Self

Create an empty-bodied response with the given status and no headers.

use churust_core::Response;
use http::StatusCode;

let res = Response::new(StatusCode::NO_CONTENT);
assert_eq!(res.status, StatusCode::NO_CONTENT);
assert!(res.body.is_empty());
Source

pub fn text(body: impl Into<String>) -> Self

Create a 200 OK response with a text/plain; charset=utf-8 body.

use churust_core::Response;
use http::StatusCode;

let res = Response::text("hello");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(
    res.headers.get(http::header::CONTENT_TYPE).unwrap(),
    "text/plain; charset=utf-8"
);
Source

pub fn bytes(content_type: &'static str, body: impl Into<Bytes>) -> Self

Create a 200 OK response with a raw byte body and an explicit Content-Type. Use this for non-text payloads (JSON, images, etc.); the content_type must be a 'static string.

use churust_core::Response;

let res = Response::bytes("application/octet-stream", vec![1u8, 2, 3]);
assert_eq!(res.body.as_slice(), Some(&[1u8, 2, 3][..]));
assert_eq!(
    res.headers.get(http::header::CONTENT_TYPE).unwrap(),
    "application/octet-stream"
);
Source

pub fn stream(content_type: &'static str, body: Body) -> Self

Create a 200 OK response whose body is produced lazily from stream, with an explicit Content-Type. Use for large or dynamic payloads.

use churust_core::{Body, Response};
use bytes::Bytes;

let chunks = futures_util::stream::iter(vec![Ok::<_, std::io::Error>(Bytes::from("hi"))]);
let res = Response::stream("text/plain", Body::from_stream(chunks));
assert!(res.body.as_bytes().is_none());
Source

pub fn with_status(self, status: StatusCode) -> Self

Override the status code, returning self for chaining.

use churust_core::Response;
use http::StatusCode;

let res = Response::text("teapot").with_status(StatusCode::IM_A_TEAPOT);
assert_eq!(res.status, StatusCode::IM_A_TEAPOT);

Append a Set-Cookie header.

Appends rather than replaces, so several cookies each get their own header — which is what the spec requires; folding them into one comma- separated value does not work in practice.

Source

pub fn with_header(self, name: HeaderName, value: HeaderValue) -> Self

Insert (or replace) a header, returning self for chaining.

use churust_core::Response;
use http::{header::LOCATION, HeaderValue};

let res = Response::new(http::StatusCode::FOUND)
    .with_header(LOCATION, HeaderValue::from_static("/login"));
assert_eq!(res.headers.get(LOCATION).unwrap(), "/login");
Source

pub fn vary_on(&mut self, field: &str)

Add a field name to Vary without disturbing what is already there.

Middleware that varies its output on a request header has to say so, and more than one layer can want to. Each has to merge rather than overwrite: a plugin that inserted its own field alone erased the other’s, and a shared cache then served a response keyed on the wrong thing — compressed bytes handed to a client that never said it could decode them, or one origin’s response handed to another.

Merging is here, in one place, because the merge is only correct if every layer does it the same way: field names are case-insensitive, so the comparison is too, and the value is appended in lower case so a response passing through several layers reads as one consistent list rather than a mixture. Two implementations agreeing by convention is what this replaces.

Already-present fields and a Vary: * — which varies on everything — are left alone.

use churust_core::Response;

let mut res = Response::text("ok");
res.vary_on("accept-encoding");
res.vary_on("Origin");
assert_eq!(res.headers.get("vary").unwrap(), "accept-encoding, origin");

// Asking twice changes nothing, whatever the spelling.
res.vary_on("ORIGIN");
assert_eq!(res.headers.get("vary").unwrap(), "accept-encoding, origin");

Trait Implementations§

Source§

impl Debug for Response

Source§

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

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

impl IntoResponse for Response

Source§

fn into_response(self) -> Response

Consume self and produce the Response to send.

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

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