under/response.rs
1use std::convert::TryFrom;
2
3#[derive(Debug)]
4#[must_use]
5/// An HTTP response.
6///
7/// An HTTP Response consists of a head (a status code and some headers), and
8/// a body (which may be empty). This type offers convenient helpers for
9/// constructing HTTP responses for you for common use-cases.
10///
11/// # Examples
12///
13/// ```rust
14/// use under::{Request, Response, HttpEntity};
15///
16/// // Here, we're defining an endpoint for our server.
17/// async fn handle_get(request: Request) -> Result<Response, anyhow::Error> {
18/// let target = request.fragment_str("target").unwrap_or("world");
19/// Ok(Response::text(format!("hello, {}", target)))
20/// }
21///
22/// # #[tokio::main]
23/// # async fn main() -> Result<(), anyhow::Error> {
24/// let mut http = under::http();
25/// http
26/// .at("/hello").get(handle_get)
27/// .at("/hello/{target}").get(handle_get);
28/// http.prepare();
29/// let mut response = http.handle(Request::get("/hello")?).await?;
30/// assert_eq!(response.status(), http::StatusCode::OK);
31/// let body = response.data(512).into_text().await?;
32/// assert_eq!(body, "hello, world");
33/// # Ok(())
34/// # }
35/// ```
36pub struct Response(http::Response<hyper::Body>);
37
38macro_rules! forward {
39 () => {};
40 (
41 $(#[$m:meta])* $v:vis fn $name:ident(&self $(, $pn:ident: $pt:ty)*) -> $ret:ty;
42 $($tail:tt)*
43 ) => {
44 $(#[$m])* $v fn $name(&self $(, $pn: $pt)*) -> $ret {
45 (self.0).$name($($pn),*)
46 }
47
48 forward! { $($tail)* }
49 };
50
51 (
52 $(#[$m:meta])* $v:vis fn $name:ident(&mut self $(, $pn:ident: $pt:ty)*) -> $ret:ty;
53 $($tail:tt)*
54 ) => {
55 $(#[$m])* $v fn $name(&mut self $(, $pn: $pt)*) -> $ret {
56 (self.0).$name($($pn),*)
57 }
58
59 forward! { $($tail)* }
60 }
61}
62
63impl Response {
64 /// Creates an empty response with a status code of 200.
65 ///
66 /// See [`Response::empty_status`] for more information.
67 ///
68 /// # Example
69 /// ```rust
70 /// # use under::*;
71 /// let response = Response::empty_200();
72 /// assert_eq!(response.status(), http::StatusCode::OK);
73 /// ```
74 pub fn empty_200() -> Self {
75 Self::empty_status(http::StatusCode::OK)
76 }
77
78 /// Creates an empty response with a status code of 204.
79 ///
80 /// See [`Response::empty_status`] for more information.
81 ///
82 /// # Examples
83 /// ```rust
84 /// # use under::*;
85 /// let response = Response::empty_204();
86 /// assert_eq!(response.status(), http::StatusCode::NO_CONTENT);
87 /// ```
88 pub fn empty_204() -> Self {
89 Response::empty_status(http::StatusCode::NO_CONTENT)
90 }
91
92 /// Creates an empty response with a status code of 404.
93 ///
94 /// See [`Response::empty_status`] for more information.
95 ///
96 /// # Examples
97 /// ```rust
98 /// # use under::*;
99 /// let response = Response::empty_404();
100 /// assert_eq!(response.status(), http::StatusCode::NOT_FOUND);
101 /// ```
102 pub fn empty_404() -> Self {
103 Response::empty_status(http::StatusCode::NOT_FOUND)
104 }
105
106 /// Creates an empty response with a status code of 500.
107 ///
108 /// See [`Response::empty_status`] for more information.
109 ///
110 /// # Examples
111 /// ```rust
112 /// # use under::*;
113 /// let response = Response::empty_500();
114 /// assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR);
115 /// ```
116 pub fn empty_500() -> Self {
117 Response::empty_status(http::StatusCode::INTERNAL_SERVER_ERROR)
118 }
119
120 /// Creates a redirect (using See Other) to the given location.
121 ///
122 /// # Errors
123 /// This attempts to convert the location into a [`http::HeaderValue`];
124 /// however, the conversion may fail (for reasons specified on
125 /// [`http::HeaderValue::from_str`]). It may also fail to construct the
126 /// underlying response.
127 ///
128 /// # Examples
129 /// ```rust
130 /// # use under::*;
131 /// let response = Response::see_other("/foo").unwrap();
132 /// assert_eq!(response.status(), http::StatusCode::SEE_OTHER);
133 /// ```
134 pub fn see_other<T>(location: T) -> Result<Self, http::Error>
135 where
136 http::HeaderValue: TryFrom<T>,
137 <http::HeaderValue as TryFrom<T>>::Error: Into<http::Error>,
138 {
139 Ok(Response(
140 http::Response::builder()
141 .status(http::StatusCode::SEE_OTHER)
142 .header(http::header::LOCATION, location)
143 .body(hyper::Body::empty())?,
144 ))
145 }
146
147 /// Creates a permanent redirect to the given location.
148 ///
149 /// # Errors
150 /// This attempts to convert the location into a
151 /// [`http::HeaderValue`]; however, the conversion may fail (for
152 /// reasons specified on [`http::HeaderValue::from_str`]). It may also
153 /// fail to construct the underlying response.
154 ///
155 /// # Examples
156 /// ```rust
157 /// # use under::*;
158 /// let response = Response::permanent_redirect("/foo").unwrap();
159 /// assert_eq!(response.status(), http::StatusCode::PERMANENT_REDIRECT);
160 /// ```
161 pub fn permanent_redirect<T>(location: T) -> Result<Self, http::Error>
162 where
163 http::HeaderValue: TryFrom<T>,
164 <http::HeaderValue as TryFrom<T>>::Error: Into<http::Error>,
165 {
166 Ok(Response(
167 http::Response::builder()
168 .status(http::StatusCode::PERMANENT_REDIRECT)
169 .header(http::header::LOCATION, location)
170 .body(hyper::Body::empty())?,
171 ))
172 }
173
174 /// Creates a temporary redirect to the given location.
175 ///
176 /// # Errors
177 /// This attempts to convert the location into a
178 /// [`http::HeaderValue`]; however, the conversion may fail (for
179 /// reasons specified on [`http::HeaderValue::from_str`]). It may also
180 /// fail to construct the underlying response.
181 ///
182 /// # Examples
183 /// ```rust
184 /// # use under::*;
185 /// let response = Response::temporary_redirect("/foo").unwrap();
186 /// assert_eq!(response.status(), http::StatusCode::TEMPORARY_REDIRECT);
187 /// ```
188 pub fn temporary_redirect<T>(location: T) -> Result<Self, http::Error>
189 where
190 http::HeaderValue: TryFrom<T>,
191 <http::HeaderValue as TryFrom<T>>::Error: Into<http::Error>,
192 {
193 Ok(Response(
194 http::Response::builder()
195 .status(http::StatusCode::TEMPORARY_REDIRECT)
196 .header(http::header::LOCATION, location)
197 .body(hyper::Body::empty())?,
198 ))
199 }
200
201 /// Creates a response with an empty body and a set status. The
202 /// Content-Type is not set.
203 ///
204 /// # Examples
205 /// ```rust
206 /// # use under::*;
207 /// let response = Response::empty_status(http::StatusCode::NOT_FOUND);
208 /// assert_eq!(response.status(), http::StatusCode::NOT_FOUND);
209 /// ```
210 #[allow(clippy::missing_panics_doc)]
211 pub fn empty_status(status: http::StatusCode) -> Self {
212 // This shouldn't panic, as the headers are garenteed to be valid.
213 Response(
214 http::Response::builder()
215 .status(status)
216 .body(hyper::Body::empty())
217 .unwrap(),
218 )
219 }
220
221 /// Creates a response with the given text body. The returned response
222 /// has a `Content-Type` of `text/plain; charset=utf-8`.
223 ///
224 /// # Examples
225 /// ```rust
226 /// # use under::*;
227 /// let response = Response::text("hello, world");
228 /// ```
229 #[allow(clippy::missing_panics_doc)]
230 pub fn text<V: Into<String>>(body: V) -> Self {
231 // This shouldn't panic, as the headers are garenteed to be valid.
232 Response(
233 http::Response::builder()
234 .header(http::header::CONTENT_TYPE, "text/plain; charset=utf-8")
235 .body(body.into().into())
236 .unwrap(),
237 )
238 }
239
240 /// Creates a response with the given JSON body. The returned response
241 /// has a `Content-Type` of `application/json; charset=utf-8`.
242 ///
243 /// # Errors
244 /// This errors if the underlying JSON serialization fails; and it will
245 /// return that exact error.
246 ///
247 /// # Examples
248 /// ```rust
249 /// # use under::*;
250 /// let response = Response::json(&serde_json::json!({ "hello": "world" }))?;
251 /// # Ok::<(), anyhow::Error>(())
252 /// ```
253 #[cfg(feature = "json")]
254 #[allow(clippy::missing_panics_doc)]
255 pub fn json<V: serde::Serialize>(body: &V) -> Result<Self, serde_json::Error> {
256 let value = serde_json::to_string(body)?;
257 // This shouldn't panic, as the value is a valid JSON string, and the
258 // headers are garenteed to be valid.
259 Ok(Response(
260 http::Response::builder()
261 .header(
262 http::header::CONTENT_TYPE,
263 "application/json; charset=utf-8",
264 )
265 .body(value.into())
266 .unwrap(),
267 ))
268 }
269
270 /// Sets the current responses's status code.
271 ///
272 /// # Examples
273 /// ```rust
274 /// # use under::*;
275 /// let mut response = Response::empty_404();
276 /// response.set_status(http::StatusCode::OK);
277 /// assert_eq!(response.status(), http::StatusCode::OK);
278 /// ```
279 pub fn set_status<S: Into<http::StatusCode>>(&mut self, status: S) {
280 *self.0.status_mut() = status.into();
281 }
282
283 /// Returns a response with the new status code.
284 ///
285 /// # Examples
286 /// ```rust
287 /// # use under::*;
288 /// let response = Response::empty_404();
289 /// let response = response.with_status(http::StatusCode::OK);
290 /// assert_eq!(response.status(), http::StatusCode::OK);
291 /// ```
292 pub fn with_status<S: Into<http::StatusCode>>(mut self, status: S) -> Self {
293 *self.0.status_mut() = status.into();
294 Response(self.0)
295 }
296
297 /// Returns state information provided by the
298 /// [`crate::middleware::StateMiddleware`] middleware. This is a
299 /// shortcut to retrieving the [`crate::middleware::State`]
300 /// extension from the response.
301 ///
302 /// # Examples
303 /// ```rust
304 /// # use under::*;
305 /// use under::middleware::State;
306 /// let mut response = Response::empty_200();
307 /// response.extensions_mut().insert(State(123u32));
308 /// assert_eq!(response.state::<u32>(), Some(&123u32));
309 /// ```
310 pub fn state<T: Send + Sync + 'static>(&self) -> Option<&T> {
311 self.ext::<crate::middleware::State<T>>().map(|v| &v.0)
312 }
313
314 /// Retrieves a specific extension from the extensions map. This is
315 /// the same as calling [`Self::extensions`].`get` wit the given
316 /// type parameter.
317 ///
318 /// # Examples
319 /// ```rust
320 /// # use under::*;
321 /// let mut response = Response::empty_200();
322 /// assert_eq!(response.ext::<u32>(), None);
323 /// ```
324 pub fn ext<T: Send + Sync + 'static>(&self) -> Option<&T> {
325 self.extensions().get::<T>()
326 }
327
328 /// Retrieves a mutable reference to the specific extension from the
329 /// extensions map. This is the same as calling
330 /// [`Self::extensions_mut`].`get_mut` with the given type
331 /// parameter.
332 ///
333 /// # Examples
334 /// ```rust
335 /// # use under::*;
336 /// let mut response = Response::empty_200();
337 /// assert_eq!(response.ext_mut::<u32>(), None);
338 /// ```
339 pub fn ext_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
340 self.extensions_mut().get_mut::<T>()
341 }
342
343 /// Sets the value of the specific extension in the extensions map.
344 /// This is the same as calling [`Self::extensions_mut`].`insert`
345 /// with the given parameter.
346 ///
347 /// # Examples
348 /// ```rust
349 /// # use under::*;
350 /// let mut response = Response::empty_200();
351 /// response.set_ext(123u32);
352 /// assert_eq!(response.ext::<u32>(), Some(&123u32));
353 /// ```
354 pub fn set_ext<T: Send + Sync + 'static>(&mut self, value: T) -> &mut Self {
355 self.extensions_mut().insert(value);
356 self
357 }
358
359 /// Sets the value of the specific extension in the extensions map,
360 /// consuming `self`, and then returning the new value. This is
361 /// the same as calling [`Self::set_ext`], but it consumes `self`.
362 ///
363 /// # Examples
364 /// ```rust
365 /// # use under::*;
366 /// let response = Response::empty_200();
367 /// let response = response.with_ext(123u32);
368 /// assert_eq!(response.ext::<u32>(), Some(&123u32));
369 /// ```
370 pub fn with_ext<T: Send + Sync + 'static>(mut self, value: T) -> Self {
371 self.set_ext(value);
372 self
373 }
374
375 /// Removes the specific extension from the extensions map. This is
376 /// the same as calling [`Self::extensions_mut`].`remove` with the
377 /// given type parameter.
378 ///
379 /// # Examples
380 /// ```rust
381 /// # use under::*;
382 /// let mut response = Response::empty_200()
383 /// .with_ext(123u32);
384 /// assert_eq!(response.ext::<u32>(), Some(&123u32));
385 /// response.remove_ext::<u32>();
386 /// assert_eq!(response.ext::<u32>(), None);
387 /// ```
388 pub fn remove_ext<T: Send + Sync + 'static>(&mut self) -> Option<T> {
389 self.extensions_mut().remove::<T>()
390 }
391
392 /// Removes the specific extension from the extensions map,
393 /// consuming `self`, and then returning the removed value. This
394 /// is the same as calling [`Self::remove_ext`], but it consumes
395 /// `self`.
396 ///
397 /// # Examples
398 /// ```rust
399 /// # use under::*;
400 /// let response = Response::empty_200()
401 /// .with_ext(123u32);
402 /// assert_eq!(response.ext::<u32>(), Some(&123u32));
403 /// let response = response.without_ext::<u32>();
404 /// assert_eq!(response.ext::<u32>(), None);
405 /// ```
406 pub fn without_ext<T: Send + Sync + 'static>(mut self) -> Self {
407 self.remove_ext::<T>();
408 self
409 }
410
411 forward! {
412 /// Returns the [`http::StatusCode`].
413 ///
414 /// # Examples
415 ///
416 /// ```rust
417 /// # use under::*;
418 /// let response = Response::default();
419 /// assert_eq!(response.status(), http::StatusCode::OK);
420 /// ```
421 pub fn status(&self) -> http::StatusCode;
422 /// Returns a reference to the associated extensions.
423 ///
424 /// # Examples
425 ///
426 /// ```rust
427 /// # use under::*;
428 /// let response = Response::default();
429 /// assert!(response.extensions().get::<i32>().is_none());
430 /// ```
431 pub fn extensions(&self) -> &http::Extensions;
432 /// Returns a mutable reference to the associated extensions.
433 ///
434 /// # Examples
435 ///
436 /// ```rust
437 /// # use under::*;
438 /// let mut response = Response::default();
439 /// response.extensions_mut().insert("hello");
440 /// assert_eq!(response.extensions().get(), Some(&"hello"));
441 /// ```
442 pub fn extensions_mut(&mut self) -> &mut http::Extensions;
443 /// Returns a reference to the associated header field map.
444 ///
445 /// # Examples
446 ///
447 /// ```rust
448 /// # use under::*;
449 /// let response = Response::default();
450 /// assert!(response.headers().is_empty());
451 /// ```
452 pub fn headers(&self) -> &http::HeaderMap<http::HeaderValue>;
453 /// Returns a mutable reference to the associated header field map.
454 ///
455 /// # Examples
456 ///
457 /// ```
458 /// # use under::*;
459 /// # use http::header::*;
460 /// let mut response = Response::default();
461 /// response.headers_mut().insert(HOST, HeaderValue::from_static("world"));
462 /// assert!(!response.headers().is_empty());
463 /// ```
464 pub fn headers_mut(&mut self) -> &mut http::HeaderMap<http::HeaderValue>;
465 }
466}
467
468impl crate::HttpEntity for Response {
469 #[inline]
470 fn body_mut(&mut self) -> &mut hyper::Body {
471 self.0.body_mut()
472 }
473 #[inline]
474 fn headers(&self) -> &http::HeaderMap<http::HeaderValue> {
475 self.0.headers()
476 }
477 #[inline]
478 fn headers_mut(&mut self) -> &mut http::HeaderMap<http::HeaderValue> {
479 self.0.headers_mut()
480 }
481}
482
483impl Default for Response {
484 fn default() -> Self {
485 Response(
486 http::Response::builder()
487 .body(hyper::Body::empty())
488 .unwrap(),
489 )
490 }
491}
492
493impl From<http::Response<hyper::Body>> for Response {
494 fn from(hy: http::Response<hyper::Body>) -> Self {
495 Response(hy)
496 }
497}
498
499impl From<Response> for http::Response<hyper::Body> {
500 fn from(this: Response) -> Self {
501 this.0
502 }
503}
504
505impl std::borrow::Borrow<http::Response<hyper::Body>> for Response {
506 fn borrow(&self) -> &http::Response<hyper::Body> {
507 &self.0
508 }
509}
510
511impl std::borrow::BorrowMut<http::Response<hyper::Body>> for Response {
512 fn borrow_mut(&mut self) -> &mut http::Response<hyper::Body> {
513 &mut self.0
514 }
515}
516
517/// Converts the current type into a [`crate::Response`].
518///
519/// This assumes that the conversion into a response is fallible
520/// (as it often is). This is used instead of `TryFrom` because
521/// `TryFrom<Result<T, E>>` is not implemented for `Result<T, E>`.
522///
523/// This uses `anyhow::Error` as the error type for a few reasons:
524///
525/// 1. [`anyhow::Error`] does not implement [`std::error::Error`].
526/// 2. [`std::convert::Infallible`]/[`!`] does not implement
527/// `Into<T>`/`From<T>`.
528/// 3. I can't figure out how to reconcile the two such that
529/// `IntoResponse` can be implemented for `Result<R, E>` where
530/// `R: IntoResponse`; especially if `R` is `Response`, as the
531/// `IntoResponse` implementation for that would have the error
532/// type be `Infallible`.
533pub trait IntoResponse {
534 /// Converts the current type into a response.
535 ///
536 /// # Errors
537 /// This can error if the conversion into a response fails.
538 /// This can fail if the current type is a `Result`, or if
539 /// e.g. the response fails to serialize.
540 fn into_response(self) -> Result<Response, anyhow::Error>;
541}
542
543impl IntoResponse for Response {
544 fn into_response(self) -> Result<Response, anyhow::Error> {
545 Ok(self)
546 }
547}
548
549impl<R, E> IntoResponse for Result<R, E>
550where
551 R: IntoResponse,
552 E: Into<anyhow::Error>,
553{
554 fn into_response(self) -> Result<Response, anyhow::Error> {
555 self.map_err(Into::into)
556 .and_then(|r| r.into_response().map_err(Into::into))
557 }
558}
559
560impl IntoResponse for std::convert::Infallible {
561 fn into_response(self) -> Result<Response, anyhow::Error> {
562 match self {}
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569
570 #[test]
571 fn convert_response() {
572 let response = Response::empty_500();
573
574 assert!(Ok::<_, std::convert::Infallible>(response)
575 .into_response()
576 .is_ok());
577 }
578}