crux_http/testing/
response_builder.rs1use http::{HeaderValue, StatusCode};
2
3use crate::response::Response;
4
5pub struct ResponseBuilder<Body> {
14 response: Response<Body>,
15}
16
17impl ResponseBuilder<Vec<u8>> {
18 #[must_use]
20 pub fn ok() -> Self {
21 Self::with_status(200)
22 }
23
24 #[must_use]
41 pub fn with_status(status: u16) -> Self {
42 let status = StatusCode::from_u16(status).expect(
43 "ResponseBuilder::with_status called with an out-of-range code (must be 100–999)",
44 );
45 assert!(
46 !status.is_client_error() && !status.is_server_error(),
47 "ResponseBuilder::with_status called with {status}, but a Response never carries a \
48 client (4xx) or server (5xx) status — those reach the app as \
49 Err(HttpError::Http {{ .. }}). Use crux_http::testing::rejection instead."
50 );
51 let response = Response::new_with_status(status);
52 Self { response }
53 }
54}
55
56impl<Body> ResponseBuilder<Body> {
57 pub fn body<NewBody>(self, body: NewBody) -> ResponseBuilder<NewBody> {
59 let response = self.response.with_body(body);
60 ResponseBuilder { response }
61 }
62
63 #[must_use]
68 pub fn header(
69 mut self,
70 name: impl http::header::IntoHeaderName,
71 value: impl AsRef<str>,
72 ) -> Self {
73 let value = HeaderValue::from_str(value.as_ref()).expect("invalid header value");
74 self.response.insert_header(name, value);
75 self
76 }
77
78 #[must_use]
86 pub fn append_header(
87 mut self,
88 name: impl http::header::IntoHeaderName,
89 value: impl AsRef<str>,
90 ) -> Self {
91 let value = HeaderValue::from_str(value.as_ref()).expect("invalid header value");
92 self.response.append_header(name, value);
93 self
94 }
95
96 pub fn build(self) -> Response<Body> {
98 self.response
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::ResponseBuilder;
105
106 #[test]
107 fn builds_any_non_error_status() {
108 for status in [200, 201, 204, 299, 302, 304] {
109 assert_eq!(
110 ResponseBuilder::with_status(status).build().status(),
111 status
112 );
113 }
114 }
115
116 #[test]
117 #[should_panic(expected = "a Response never carries a client (4xx) or server (5xx) status")]
118 fn refuses_a_client_error_status() {
119 let _ = ResponseBuilder::with_status(409);
120 }
121
122 #[test]
123 #[should_panic(expected = "a Response never carries a client (4xx) or server (5xx) status")]
124 fn refuses_a_server_error_status() {
125 let _ = ResponseBuilder::with_status(503);
126 }
127}