use super::{rejection::*, take_body, Extension, FromRequest, RequestParts}; use async_trait::async_trait; use bytes::Bytes; use futures_util::stream::Stream; use http::{HeaderMap, Method, Request, Uri, Version}; use std::{ convert::Infallible, pin::Pin, task::{Context, Poll}, }; use tower::BoxError; #[async_trait] impl FromRequest for Request where B: Send, { type Rejection = RequestAlreadyExtracted; async fn from_request(req: &mut RequestParts) -> Result { let RequestParts { method: _, uri: _, version: _, headers, extensions, body, } = req; let all_parts = extensions.as_ref().zip(body.as_ref()).zip(headers.as_ref()); if all_parts.is_some() { Ok(req.into_request()) } else { Err(RequestAlreadyExtracted) } } } #[async_trait] impl FromRequest for Body where B: Send, { type Rejection = BodyAlreadyExtracted; async fn from_request(req: &mut RequestParts) -> Result { let body = take_body(req)?; Ok(Self(body)) } } #[async_trait] impl FromRequest for Method where B: Send, { type Rejection = Infallible; async fn from_request(req: &mut RequestParts) -> Result { Ok(req.method().clone()) } } #[async_trait] impl FromRequest for Uri where B: Send, { type Rejection = Infallible; async fn from_request(req: &mut RequestParts) -> Result { Ok(req.uri().clone()) } } /// Extractor that gets the request URI for a nested service. /// /// This is necessary since [`Uri`](http::Uri), when used as an extractor, will /// always be the full URI. /// /// # Example /// /// ``` /// use axum::{prelude::*, extract::NestedUri, http::Uri}; /// /// let api_routes = route( /// "/users", /// get(|uri: Uri, NestedUri(nested_uri): NestedUri| async { /// // `uri` is `/api/users` /// // `nested_uri` is `/users` /// }), /// ); /// /// let app = nest("/api", api_routes); /// # async { /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` #[derive(Debug, Clone)] pub struct NestedUri(pub Uri); #[async_trait] impl FromRequest for NestedUri where B: Send, { type Rejection = NotNested; async fn from_request(req: &mut RequestParts) -> Result { let uri = Extension::::from_request(req) .await .map_err(|_| NotNested)? .0; Ok(uri) } } #[async_trait] impl FromRequest for Version where B: Send, { type Rejection = Infallible; async fn from_request(req: &mut RequestParts) -> Result { Ok(req.version()) } } #[async_trait] impl FromRequest for HeaderMap where B: Send, { type Rejection = HeadersAlreadyExtracted; async fn from_request(req: &mut RequestParts) -> Result { req.take_headers().ok_or(HeadersAlreadyExtracted) } } /// Extractor that extracts the request body as a [`Stream`]. /// /// # Example /// /// ```rust,no_run /// use axum::prelude::*; /// use futures::StreamExt; /// /// async fn handler(mut stream: extract::BodyStream) { /// while let Some(chunk) = stream.next().await { /// // ... /// } /// } /// /// let app = route("/users", get(handler)); /// # async { /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` /// /// [`Stream`]: https://docs.rs/futures/latest/futures/stream/trait.Stream.html #[derive(Debug)] pub struct BodyStream(B); impl Stream for BodyStream where B: http_body::Body + Unpin, { type Item = Result; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { Pin::new(&mut self.0).poll_data(cx) } } #[async_trait] impl FromRequest for BodyStream where B: http_body::Body + Unpin + Send, { type Rejection = BodyAlreadyExtracted; async fn from_request(req: &mut RequestParts) -> Result { let body = take_body(req)?; let stream = BodyStream(body); Ok(stream) } } /// Extractor that extracts the request body. /// /// # Example /// /// ```rust,no_run /// use axum::prelude::*; /// use futures::StreamExt; /// /// async fn handler(extract::Body(body): extract::Body) { /// // ... /// } /// /// let app = route("/users", get(handler)); /// # async { /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` #[derive(Debug, Default, Clone)] pub struct Body(pub B); #[async_trait] impl FromRequest for Bytes where B: http_body::Body + Send, B::Data: Send, B::Error: Into, { type Rejection = BytesRejection; async fn from_request(req: &mut RequestParts) -> Result { let body = take_body(req)?; let bytes = hyper::body::to_bytes(body) .await .map_err(FailedToBufferBody::from_err)?; Ok(bytes) } } #[async_trait] impl FromRequest for String where B: http_body::Body + Send, B::Data: Send, B::Error: Into, { type Rejection = StringRejection; async fn from_request(req: &mut RequestParts) -> Result { let body = take_body(req)?; let bytes = hyper::body::to_bytes(body) .await .map_err(FailedToBufferBody::from_err)? .to_vec(); let string = String::from_utf8(bytes).map_err(InvalidUtf8::from_err)?; Ok(string) } }