axol_http/response.rs
1use std::{any::Any, convert::Infallible};
2
3use thiserror::Error;
4
5use crate::{header::HeaderMap, status::StatusCodeError, Body, Extensions, StatusCode, Version};
6
7/// Represents an HTTP response
8///
9/// An HTTP response consists of a head and a potentially optional body. The body
10/// component is generic, enabling arbitrary types to represent the HTTP body.
11/// For example, the body could be `Vec<u8>`, a `Stream` of byte chunks, or a
12/// value that has been deserialized.
13///
14/// Typically you'll work with responses on the client side as the result of
15/// sending a `Request` and on the server you'll be generating a `Response` to
16/// send back to the client.
17///
18/// # Examples
19///
20/// Creating a `Response` to return
21///
22/// ```
23/// use axol_http::{Request, Response, StatusCode};
24///
25/// fn respond_to(req: Request<()>) -> axol_http::Result<Response<()>> {
26/// let mut builder = Response::builder()
27/// .header("Foo", "Bar")
28/// .status(StatusCode::OK);
29///
30/// if req.headers().contains_key("Another-Header") {
31/// builder = builder.header("Another-Header", "Ack");
32/// }
33///
34/// builder.body(())
35/// }
36/// ```
37///
38/// A simple 404 handler
39///
40/// ```
41/// use axol_http::{Request, Response, StatusCode};
42///
43/// fn not_found(_req: Request<()>) -> axol_http::Result<Response<()>> {
44/// Response::builder()
45/// .status(StatusCode::NOT_FOUND)
46/// .body(())
47/// }
48/// ```
49///
50/// Or otherwise inspecting the result of a request:
51///
52/// ```no_run
53/// use axol_http::{Request, Response};
54///
55/// fn get(url: &str) -> axol_http::Result<Response<()>> {
56/// // ...
57/// # panic!()
58/// }
59///
60/// let response = get("https://www.rust-lang.org/").unwrap();
61///
62/// if !response.status().is_success() {
63/// panic!("failed to get a successful response status!");
64/// }
65///
66/// if let Some(date) = response.headers().get("Date") {
67/// // we've got a `Date` header!
68/// }
69///
70/// let body = response.body();
71/// // ...
72/// ```
73///
74/// Deserialize a response of bytes via json:
75///
76/// ```
77/// # extern crate serde;
78/// # extern crate serde_json;
79/// # extern crate http;
80/// use axol_http::Response;
81/// use serde::de;
82///
83/// fn deserialize<T>(res: Response<Vec<u8>>) -> serde_json::Result<Response<T>>
84/// where for<'de> T: de::Deserialize<'de>,
85/// {
86/// let (parts, body) = res.into_parts();
87/// let body = serde_json::from_slice(&body)?;
88/// Ok(Response::from_parts(parts, body))
89/// }
90/// #
91/// # fn main() {}
92/// ```
93///
94/// Or alternatively, serialize the body of a response to json
95///
96/// ```
97/// # extern crate serde;
98/// # extern crate serde_json;
99/// # extern crate http;
100/// use axol_http::Response;
101/// use serde::ser;
102///
103/// fn serialize<T>(res: Response<T>) -> serde_json::Result<Response<Vec<u8>>>
104/// where T: ser::Serialize,
105/// {
106/// let (parts, body) = res.into_parts();
107/// let body = serde_json::to_vec(&body)?;
108/// Ok(Response::from_parts(parts, body))
109/// }
110/// #
111/// # fn main() {}
112/// ```
113#[derive(Debug, Default)]
114pub struct Response {
115 /// The response's status
116 pub status: StatusCode,
117
118 /// The response's version
119 pub version: Version,
120
121 /// The response's headers
122 pub headers: HeaderMap,
123
124 /// The response's extensions
125 pub extensions: Extensions,
126
127 /// The response's body
128 pub body: Body,
129}
130
131/// Component parts of an HTTP `Response`
132///
133/// The HTTP response head consists of a status, version, and a set of
134/// header fields.
135#[derive(Debug, Default)]
136pub struct ResponseParts {
137 /// The response's status
138 pub status: StatusCode,
139
140 /// The response's version
141 pub version: Version,
142
143 /// The response's headers
144 pub headers: HeaderMap,
145
146 /// The response's extensions
147 pub extensions: Extensions,
148}
149
150impl ResponseParts {
151 pub fn as_ref(&mut self) -> ResponsePartsRef<'_> {
152 ResponsePartsRef {
153 status: &mut self.status,
154 version: &mut self.version,
155 headers: &mut self.headers,
156 extensions: &mut self.extensions,
157 }
158 }
159}
160
161impl Response {
162 pub fn parts_mut(&mut self) -> ResponsePartsRef<'_> {
163 ResponsePartsRef {
164 status: &mut self.status,
165 version: &mut self.version,
166 headers: &mut self.headers,
167 extensions: &mut self.extensions,
168 }
169 }
170}
171
172#[derive(Debug)]
173pub struct ResponsePartsRef<'a> {
174 /// The response's status
175 pub status: &'a mut StatusCode,
176
177 /// The response's version
178 pub version: &'a mut Version,
179
180 /// The response's headers
181 pub headers: &'a mut HeaderMap,
182
183 /// The response's extensions
184 pub extensions: &'a mut Extensions,
185}
186
187impl ResponseParts {
188 /// Creates a new default instance of `ResponseParts`
189 pub fn new() -> ResponseParts {
190 Default::default()
191 }
192}
193
194#[derive(Error, Debug)]
195pub enum ResponseBuilderError {
196 #[error("")]
197 Infallible(#[from] Infallible),
198 #[error("status code error: {0}")]
199 StatusCode(#[from] StatusCodeError),
200 // #[error("http error: {0}")]
201 // Http(#[from] HttpError),
202}
203
204/// An HTTP response builder
205///
206/// This type can be used to construct an instance of `Response` through a
207/// builder-like pattern.
208#[derive(Debug)]
209pub struct Builder {
210 inner: Result<Response, ResponseBuilderError>,
211}
212
213impl Response {
214 /// Creates a new builder-style object to manufacture a `Response`
215 ///
216 /// This method returns an instance of `Builder` which can be used to
217 /// create a `Response`.
218 ///
219 /// # Examples
220 ///
221 /// ```
222 /// # use axol_http::*;
223 /// let response = Response::builder()
224 /// .status(200)
225 /// .header("X-Custom-Foo", "Bar")
226 /// .body(())
227 /// .unwrap();
228 /// ```
229 pub fn builder() -> Builder {
230 Builder::new()
231 }
232
233 /// Creates a new blank `Response` with the body
234 ///
235 /// The component ports of this response will be set to their default, e.g.
236 /// the ok status, no headers, etc.
237 ///
238 /// # Examples
239 ///
240 /// ```
241 /// # use axol_http::*;
242 /// let response = Response::new("hello world");
243 ///
244 /// assert_eq!(response.status(), StatusCode::OK);
245 /// assert_eq!(*response.body(), "hello world");
246 /// ```
247 pub fn new(body: impl Into<Body>) -> Response {
248 Self::from_parts(Default::default(), body)
249 }
250
251 /// Creates a new `Response` with the given head and body
252 ///
253 /// # Examples
254 ///
255 /// ```
256 /// # use axol_http::*;
257 /// let response = Response::new("hello world");
258 /// let (mut parts, body) = response.into_parts();
259 ///
260 /// parts.status = StatusCode::BAD_REQUEST;
261 /// let response = Response::from_parts(parts, body);
262 ///
263 /// assert_eq!(response.status(), StatusCode::BAD_REQUEST);
264 /// assert_eq!(*response.body(), "hello world");
265 /// ```
266 pub fn from_parts(parts: ResponseParts, body: impl Into<Body>) -> Response {
267 Response {
268 status: parts.status,
269 version: parts.version,
270 headers: parts.headers,
271 extensions: parts.extensions,
272 body: body.into(),
273 }
274 }
275
276 /// Consumes the response returning the head and body parts.
277 ///
278 /// # Examples
279 ///
280 /// ```
281 /// # use axol_http::*;
282 /// let response: Response<()> = Response::default();
283 /// let (parts, body) = response.into_parts();
284 /// assert_eq!(parts.status, StatusCode::OK);
285 /// ```
286 pub fn into_parts(self) -> (ResponseParts, Body) {
287 (
288 ResponseParts {
289 status: self.status,
290 version: self.version,
291 headers: self.headers,
292 extensions: self.extensions,
293 },
294 self.body,
295 )
296 }
297
298 /// Sets status code of response
299 pub fn with_status(mut self, status: StatusCode) -> Self {
300 self.status = status;
301 self
302 }
303}
304
305impl Builder {
306 /// Creates a new default instance of `Builder` to construct either a
307 /// `Head` or a `Response`.
308 ///
309 /// # Examples
310 ///
311 /// ```
312 /// # use axol_http::*;
313 ///
314 /// let response = response::Builder::new()
315 /// .status(200)
316 /// .body(())
317 /// .unwrap();
318 /// ```
319 pub fn new() -> Builder {
320 Builder::default()
321 }
322
323 /// Set the HTTP status for this response.
324 ///
325 /// This function will configure the HTTP status code of the `Response` that
326 /// will be returned from `Builder::build`.
327 ///
328 /// By default this is `200`.
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// # use axol_http::*;
334 ///
335 /// let response = Response::builder()
336 /// .status(200)
337 /// .body(())
338 /// .unwrap();
339 /// ```
340 pub fn status<T>(self, status: T) -> Builder
341 where
342 StatusCode: TryFrom<T>,
343 <StatusCode as TryFrom<T>>::Error: Into<StatusCodeError>,
344 {
345 self.and_then(move |mut head| {
346 head.status = TryFrom::try_from(status).map_err(Into::into)?;
347 Ok(head)
348 })
349 }
350
351 /// Set the HTTP version for this response.
352 ///
353 /// This function will configure the HTTP version of the `Response` that
354 /// will be returned from `Builder::build`.
355 ///
356 /// By default this is HTTP/1.1
357 ///
358 /// # Examples
359 ///
360 /// ```
361 /// # use axol_http::*;
362 ///
363 /// let response = Response::builder()
364 /// .version(Version::HTTP_2)
365 /// .body(())
366 /// .unwrap();
367 /// ```
368 pub fn version(self, version: Version) -> Builder {
369 self.and_then(move |mut head| {
370 head.version = version;
371 Ok(head)
372 })
373 }
374
375 /// Appends a header to this response builder.
376 ///
377 /// This function will append the provided key/value as a header to the
378 /// internal `HeaderMap` being constructed. Essentially this is equivalent
379 /// to calling `HeaderMap::append`.
380 ///
381 /// # Examples
382 ///
383 /// ```
384 /// # use axol_http::*;
385 /// # use axol_http::header::HeaderValue;
386 ///
387 /// let response = Response::builder()
388 /// .header("Content-Type", "text/html")
389 /// .header("X-Custom-Foo", "bar")
390 /// .header("content-length", 0)
391 /// .body(())
392 /// .unwrap();
393 /// ```
394 pub fn header(self, name: impl AsRef<str>, value: impl Into<String>) -> Builder {
395 self.and_then(move |mut head| {
396 head.headers.insert(name, value);
397 Ok(head)
398 })
399 }
400
401 /// Get header on this response builder.
402 ///
403 /// When builder has error returns None.
404 ///
405 /// # Example
406 ///
407 /// ```
408 /// # use axol_http::Response;
409 /// # use axol_http::header::HeaderValue;
410 /// let res = Response::builder()
411 /// .header("Accept", "text/html")
412 /// .header("X-Custom-Foo", "bar");
413 /// let headers = res.headers_ref().unwrap();
414 /// assert_eq!( headers["Accept"], "text/html" );
415 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
416 /// ```
417 pub fn headers_ref(&self) -> Option<&HeaderMap> {
418 self.inner.as_ref().ok().map(|h| &h.headers)
419 }
420
421 /// Get header on this response builder.
422 /// when builder has error returns None
423 ///
424 /// # Example
425 ///
426 /// ```
427 /// # use axol_http::*;
428 /// # use axol_http::header::HeaderValue;
429 /// # use axol_http::response::Builder;
430 /// let mut res = Response::builder();
431 /// {
432 /// let headers = res.headers_mut().unwrap();
433 /// headers.insert("Accept", HeaderValue::from_static("text/html"));
434 /// headers.insert("X-Custom-Foo", HeaderValue::from_static("bar"));
435 /// }
436 /// let headers = res.headers_ref().unwrap();
437 /// assert_eq!( headers["Accept"], "text/html" );
438 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
439 /// ```
440 pub fn headers_mut(&mut self) -> Option<&mut HeaderMap> {
441 self.inner.as_mut().ok().map(|h| &mut h.headers)
442 }
443
444 /// Adds an extension to this builder
445 ///
446 /// # Examples
447 ///
448 /// ```
449 /// # use axol_http::*;
450 ///
451 /// let response = Response::builder()
452 /// .extension("My Extension")
453 /// .body(())
454 /// .unwrap();
455 ///
456 /// assert_eq!(response.extensions().get::<&'static str>(),
457 /// Some(&"My Extension"));
458 /// ```
459 pub fn extension<T>(self, extension: T) -> Builder
460 where
461 T: Any + Send + Sync + 'static,
462 {
463 self.and_then(move |head| {
464 head.extensions.insert(extension);
465 Ok(head)
466 })
467 }
468
469 /// Get a reference to the extensions for this response builder.
470 ///
471 /// If the builder has an error, this returns `None`.
472 ///
473 /// # Example
474 ///
475 /// ```
476 /// # use axol_http::Response;
477 /// let res = Response::builder().extension("My Extension").extension(5u32);
478 /// let extensions = res.extensions_ref().unwrap();
479 /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension"));
480 /// assert_eq!(extensions.get::<u32>(), Some(&5u32));
481 /// ```
482 pub fn extensions_ref(&self) -> Option<&Extensions> {
483 self.inner.as_ref().ok().map(|h| &h.extensions)
484 }
485
486 /// Get a mutable reference to the extensions for this response builder.
487 ///
488 /// If the builder has an error, this returns `None`.
489 ///
490 /// # Example
491 ///
492 /// ```
493 /// # use axol_http::Response;
494 /// let mut res = Response::builder().extension("My Extension");
495 /// let mut extensions = res.extensions_mut().unwrap();
496 /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension"));
497 /// extensions.insert(5u32);
498 /// assert_eq!(extensions.get::<u32>(), Some(&5u32));
499 /// ```
500 pub fn extensions_mut(&mut self) -> Option<&mut Extensions> {
501 self.inner.as_mut().ok().map(|h| &mut h.extensions)
502 }
503
504 /// "Consumes" this builder, using the provided `body` to return a
505 /// constructed `Response`.
506 ///
507 /// # Errors
508 ///
509 /// This function may return an error if any previously configured argument
510 /// failed to parse or get converted to the internal representation. For
511 /// example if an invalid `head` was specified via `header("Foo",
512 /// "Bar\r\n")` the error will be returned when this function is called
513 /// rather than when `header` was called.
514 ///
515 /// # Examples
516 ///
517 /// ```
518 /// # use axol_http::*;
519 ///
520 /// let response = Response::builder()
521 /// .body(())
522 /// .unwrap();
523 /// ```
524 pub fn body(self, body: impl Into<Body>) -> Result<Response, ResponseBuilderError> {
525 self.inner.map(move |mut head| {
526 head.body = body.into();
527 head
528 })
529 }
530
531 // private
532
533 fn and_then<F>(self, func: F) -> Self
534 where
535 F: FnOnce(Response) -> Result<Response, ResponseBuilderError>,
536 {
537 Builder {
538 inner: self.inner.and_then(func),
539 }
540 }
541}
542
543impl Default for Builder {
544 fn default() -> Builder {
545 Builder {
546 inner: Ok(Default::default()),
547 }
548 }
549}