Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use impl IntoResponse less in docs #1049

Merged
merged 1 commit into from May 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions axum-core/src/response/into_response_parts.rs
Expand Up @@ -57,7 +57,10 @@ use std::{
/// }
///
/// // We can now return `SetHeader` in responses
/// async fn handler() -> impl IntoResponse {
/// //
/// // Note that returning `impl IntoResponse` might be easier if the response has many parts to
/// // it. The return type is written out here for clarity.
/// async fn handler() -> (SetHeader<'static>, SetHeader<'static>, &'static str) {
/// (
Copy link

@bsodmike bsodmike May 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidpdrsn doesn't the Impl IntoReponse interface recurse over the tuple essentially calling .into_reponse() on each tuple element? Referring to all_the_tuples!(impl_into_response); in the source of the trait.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does yes.

/// SetHeader("server", "axum"),
/// SetHeader("x-foo", "custom"),
Expand All @@ -66,7 +69,7 @@ use std::{
/// }
///
/// // Or on its own as the whole response
/// async fn other_handler() -> impl IntoResponse {
/// async fn other_handler() -> SetHeader<'static> {
/// SetHeader("x-foo", "custom")
/// }
/// ```
Expand Down
8 changes: 4 additions & 4 deletions axum-extra/src/extract/cookie/mod.rs
Expand Up @@ -50,7 +50,7 @@ pub use cookie_lib::Key;
/// async fn create_session(
/// TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
/// jar: CookieJar,
/// ) -> impl IntoResponse {
/// ) -> Result<(CookieJar, Redirect), StatusCode> {
/// if let Some(session_id) = authorize_and_create_session(auth.token()).await {
/// Ok((
/// // the updated jar must be returned for the changes
Expand All @@ -63,7 +63,7 @@ pub use cookie_lib::Key;
/// }
/// }
///
/// async fn me(jar: CookieJar) -> impl IntoResponse {
/// async fn me(jar: CookieJar) -> Result<(), StatusCode> {
/// if let Some(session_id) = jar.get("session_id") {
/// // fetch and render user...
/// # Ok(())
Expand Down Expand Up @@ -141,7 +141,7 @@ impl CookieJar {
/// use axum_extra::extract::cookie::{CookieJar, Cookie};
/// use axum::response::IntoResponse;
///
/// async fn handle(jar: CookieJar) -> impl IntoResponse {
/// async fn handle(jar: CookieJar) -> CookieJar {
/// jar.remove(Cookie::named("foo"))
/// }
/// ```
Expand All @@ -161,7 +161,7 @@ impl CookieJar {
/// use axum_extra::extract::cookie::{CookieJar, Cookie};
/// use axum::response::IntoResponse;
///
/// async fn handle(jar: CookieJar) -> impl IntoResponse {
/// async fn handle(jar: CookieJar) -> CookieJar {
/// jar.add(Cookie::new("foo", "bar"))
/// }
/// ```
Expand Down
8 changes: 4 additions & 4 deletions axum-extra/src/extract/cookie/private.rs
Expand Up @@ -33,12 +33,12 @@ use std::{convert::Infallible, fmt, marker::PhantomData};
///
/// async fn set_secret(
/// jar: PrivateCookieJar,
/// ) -> impl IntoResponse {
/// ) -> (PrivateCookieJar, Redirect) {
/// let updated_jar = jar.add(Cookie::new("secret", "secret-data"));
/// (updated_jar, Redirect::to("/get"))
/// }
///
/// async fn get_secret(jar: PrivateCookieJar) -> impl IntoResponse {
/// async fn get_secret(jar: PrivateCookieJar) {
/// if let Some(data) = jar.get("secret") {
/// // ...
/// }
Expand Down Expand Up @@ -129,7 +129,7 @@ impl<K> PrivateCookieJar<K> {
/// use axum_extra::extract::cookie::{PrivateCookieJar, Cookie};
/// use axum::response::IntoResponse;
///
/// async fn handle(jar: PrivateCookieJar) -> impl IntoResponse {
/// async fn handle(jar: PrivateCookieJar) -> PrivateCookieJar {
/// jar.remove(Cookie::named("foo"))
/// }
/// ```
Expand All @@ -149,7 +149,7 @@ impl<K> PrivateCookieJar<K> {
/// use axum_extra::extract::cookie::{PrivateCookieJar, Cookie};
/// use axum::response::IntoResponse;
///
/// async fn handle(jar: PrivateCookieJar) -> impl IntoResponse {
/// async fn handle(jar: PrivateCookieJar) -> PrivateCookieJar {
/// jar.add(Cookie::new("foo", "bar"))
/// }
/// ```
Expand Down
8 changes: 4 additions & 4 deletions axum-extra/src/extract/cookie/signed.rs
Expand Up @@ -35,7 +35,7 @@ use std::{convert::Infallible, fmt, marker::PhantomData};
/// async fn create_session(
/// TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
/// jar: SignedCookieJar,
/// ) -> impl IntoResponse {
/// ) -> Result<(SignedCookieJar, Redirect), StatusCode> {
/// if let Some(session_id) = authorize_and_create_session(auth.token()).await {
/// Ok((
/// // the updated jar must be returned for the changes
Expand All @@ -48,7 +48,7 @@ use std::{convert::Infallible, fmt, marker::PhantomData};
/// }
/// }
///
/// async fn me(jar: SignedCookieJar) -> impl IntoResponse {
/// async fn me(jar: SignedCookieJar) -> Result<(), StatusCode> {
/// if let Some(session_id) = jar.get("session_id") {
/// // fetch and render user...
/// # Ok(())
Expand Down Expand Up @@ -148,7 +148,7 @@ impl<K> SignedCookieJar<K> {
/// use axum_extra::extract::cookie::{SignedCookieJar, Cookie};
/// use axum::response::IntoResponse;
///
/// async fn handle(jar: SignedCookieJar) -> impl IntoResponse {
/// async fn handle(jar: SignedCookieJar) -> SignedCookieJar {
/// jar.remove(Cookie::named("foo"))
/// }
/// ```
Expand All @@ -168,7 +168,7 @@ impl<K> SignedCookieJar<K> {
/// use axum_extra::extract::cookie::{SignedCookieJar, Cookie};
/// use axum::response::IntoResponse;
///
/// async fn handle(jar: SignedCookieJar) -> impl IntoResponse {
/// async fn handle(jar: SignedCookieJar) -> SignedCookieJar {
/// jar.add(Cookie::new("foo", "bar"))
/// }
/// ```
Expand Down
2 changes: 1 addition & 1 deletion axum-extra/src/response/erased_json.rs
Expand Up @@ -15,7 +15,7 @@ use serde::Serialize;
/// ```rust
/// # use axum::{response::IntoResponse};
/// # use axum_extra::response::ErasedJson;
/// async fn handler() -> impl IntoResponse {
/// async fn handler() -> ErasedJson {
/// # let condition = true;
/// # let foo = ();
/// # let bar = vec![()];
Expand Down
7 changes: 4 additions & 3 deletions axum/src/body/stream_body.rs
Expand Up @@ -32,10 +32,11 @@ pin_project! {
/// body::StreamBody,
/// response::IntoResponse,
/// };
/// use futures::stream;
/// use futures::stream::{self, Stream};
/// use std::io;
///
/// async fn handler() -> impl IntoResponse {
/// let chunks: Vec<Result<_, std::io::Error>> = vec![
/// async fn handler() -> StreamBody<impl Stream<Item = io::Result<&'static str>>> {
/// let chunks: Vec<io::Result<_>> = vec![
/// Ok("Hello,"),
/// Ok(" "),
/// Ok("world!"),
Expand Down
4 changes: 3 additions & 1 deletion axum/src/docs/extract.md
Expand Up @@ -316,7 +316,9 @@ use axum::{
};
use serde_json::{json, Value};

async fn handler(result: Result<Json<Value>, JsonRejection>) -> impl IntoResponse {
async fn handler(
result: Result<Json<Value>, JsonRejection>,
) -> Result<Json<Value>, (StatusCode, String)> {
match result {
// if the client sent valid JSON then we're good
Ok(Json(payload)) => Ok(Json(json!({ "payload": payload }))),
Expand Down
6 changes: 3 additions & 3 deletions axum/src/docs/method_routing/fallback.md
Expand Up @@ -15,7 +15,7 @@ let handler = get(|| async {}).fallback(fallback.into_service());

let app = Router::new().route("/", handler);

async fn fallback(method: Method, uri: Uri) -> impl IntoResponse {
async fn fallback(method: Method, uri: Uri) -> (StatusCode, String) {
(StatusCode::NOT_FOUND, format!("`{}` not allowed for {}", method, uri))
}
# async {
Expand Down Expand Up @@ -44,8 +44,8 @@ let two = post(|| async {})

let method_route = one.merge(two);

async fn fallback_one() -> impl IntoResponse {}
async fn fallback_two() -> impl IntoResponse {}
async fn fallback_one() -> impl IntoResponse { /* ... */ }
async fn fallback_two() -> impl IntoResponse { /* ... */ }
# let app = axum::Router::new().route("/", method_route);
# async {
# hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
Expand Down
4 changes: 2 additions & 2 deletions axum/src/docs/middleware.md
Expand Up @@ -383,15 +383,15 @@ use axum::{
Router,
http::{Request, StatusCode},
routing::get,
response::IntoResponse,
response::{IntoResponse, Response},
middleware::{self, Next},
extract::Extension,
};

#[derive(Clone)]
struct CurrentUser { /* ... */ }

async fn auth<B>(mut req: Request<B>, next: Next<B>) -> impl IntoResponse {
async fn auth<B>(mut req: Request<B>, next: Next<B>) -> Result<Response, StatusCode> {
let auth_header = req.headers()
.get(http::header::AUTHORIZATION)
.and_then(|header| header.to_str().ok());
Expand Down
41 changes: 38 additions & 3 deletions axum/src/docs/response.md
Expand Up @@ -133,7 +133,7 @@ async fn all_the_things(uri: Uri) -> impl IntoResponse {
(
// set status code
StatusCode::NOT_FOUND,
// headers ith an array
// headers with an array
[("x-custom", "custom")],
// some extensions
Extension(Foo("foo")),
Expand Down Expand Up @@ -165,11 +165,11 @@ Use [`Response`](crate::response::Response) for more low level control:
use axum::{
Json,
response::{IntoResponse, Response},
body::Full,
body::{Full, Bytes},
http::StatusCode,
};

async fn response() -> impl IntoResponse {
async fn response() -> Response<Full<Bytes>> {
Response::builder()
.status(StatusCode::NOT_FOUND)
.header("x-foo", "custom header")
Expand All @@ -178,6 +178,41 @@ async fn response() -> impl IntoResponse {
}
```

# Returning different response types

If you need to return multiple response types, and `Result<T, E>` isn't appropriate, you can call
`.into_response()` to turn things into `axum::response::Response`:

```rust
use axum::{
response::{IntoResponse, Redirect, Response},
http::StatusCode,
};

async fn handle() -> Response {
if something() {
"All good!".into_response()
} else if something_else() {
(
StatusCode::INTERNAL_SERVER_ERROR,
"Something went wrong...",
).into_response()
} else {
Redirect::to("/").into_response()
}
}

fn something() -> bool {
// ...
# true
}

fn something_else() -> bool {
// ...
# true
}
```

[`IntoResponse`]: crate::response::IntoResponse
[`IntoResponseParts`]: crate::response::IntoResponseParts
[`StatusCode`]: http::StatusCode
2 changes: 1 addition & 1 deletion axum/src/docs/routing/fallback.md
Expand Up @@ -15,7 +15,7 @@ let app = Router::new()
.route("/foo", get(|| async { /* ... */ }))
.fallback(fallback.into_service());

async fn fallback(uri: Uri) -> impl IntoResponse {
async fn fallback(uri: Uri) -> (StatusCode, String) {
(StatusCode::NOT_FOUND, format!("No route for {}", uri))
}
# async {
Expand Down
2 changes: 1 addition & 1 deletion axum/src/extension.rs
Expand Up @@ -59,7 +59,7 @@ use tower_service::Service;
/// response::IntoResponse,
/// };
///
/// async fn handler() -> impl IntoResponse {
/// async fn handler() -> (Extension<Foo>, &'static str) {
/// (
/// Extension(Foo("foo")),
/// "Hello, World!"
Expand Down
8 changes: 4 additions & 4 deletions axum/src/extract/ws.rs
Expand Up @@ -6,13 +6,13 @@
//! use axum::{
//! extract::ws::{WebSocketUpgrade, WebSocket},
//! routing::get,
//! response::IntoResponse,
//! response::{IntoResponse, Response},
//! Router,
//! };
//!
//! let app = Router::new().route("/ws", get(handler));
//!
//! async fn handler(ws: WebSocketUpgrade) -> impl IntoResponse {
//! async fn handler(ws: WebSocketUpgrade) -> Response {
//! ws.on_upgrade(handle_socket)
//! }
//!
Expand Down Expand Up @@ -148,13 +148,13 @@ impl WebSocketUpgrade {
/// use axum::{
/// extract::ws::{WebSocketUpgrade, WebSocket},
/// routing::get,
/// response::IntoResponse,
/// response::{IntoResponse, Response},
/// Router,
/// };
///
/// let app = Router::new().route("/ws", get(handler));
///
/// async fn handler(ws: WebSocketUpgrade) -> impl IntoResponse {
/// async fn handler(ws: WebSocketUpgrade) -> Response {
/// ws.protocols(["graphql-ws", "graphql-transport-ws"])
/// .on_upgrade(|socket| async {
/// // ...
Expand Down
6 changes: 3 additions & 3 deletions axum/src/handler/mod.rs
Expand Up @@ -126,7 +126,7 @@ pub trait Handler<T, B = Body>: Clone + Send + Sized + 'static {
/// use tower::make::Shared;
/// use std::net::SocketAddr;
///
/// async fn handler(method: Method, uri: Uri) -> impl IntoResponse {
/// async fn handler(method: Method, uri: Uri) -> (StatusCode, String) {
/// (StatusCode::NOT_FOUND, format!("Nothing to see at {} {}", method, uri))
/// }
///
Expand Down Expand Up @@ -157,7 +157,7 @@ pub trait Handler<T, B = Body>: Clone + Send + Sized + 'static {
/// };
/// use std::net::SocketAddr;
///
/// async fn handler(method: Method, uri: Uri, body: String) -> impl IntoResponse {
/// async fn handler(method: Method, uri: Uri, body: String) -> String {
/// format!("received `{} {}` with body `{:?}`", method, uri, body)
/// }
///
Expand Down Expand Up @@ -188,7 +188,7 @@ pub trait Handler<T, B = Body>: Clone + Send + Sized + 'static {
/// };
/// use std::net::SocketAddr;
///
/// async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> impl IntoResponse {
/// async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String {
/// format!("Hello {}", addr)
/// }
///
Expand Down
16 changes: 8 additions & 8 deletions axum/src/middleware/from_fn.rs
Expand Up @@ -34,11 +34,11 @@ use tower_service::Service;
/// Router,
/// http::{Request, StatusCode},
/// routing::get,
/// response::IntoResponse,
/// response::{IntoResponse, Response},
/// middleware::{self, Next},
/// };
///
/// async fn auth<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse {
/// async fn auth<B>(req: Request<B>, next: Next<B>) -> Result<Response, StatusCode> {
/// let auth_header = req.headers()
/// .get(http::header::AUTHORIZATION)
/// .and_then(|header| header.to_str().ok());
Expand Down Expand Up @@ -71,7 +71,7 @@ use tower_service::Service;
/// Router,
/// http::{Request, StatusCode},
/// routing::get,
/// response::IntoResponse,
/// response::{IntoResponse, Response},
/// middleware::{self, Next}
/// };
///
Expand All @@ -82,9 +82,9 @@ use tower_service::Service;
/// req: Request<B>,
/// next: Next<B>,
/// state: State,
/// ) -> impl IntoResponse {
/// ) -> Response {
/// // ...
/// # ()
/// # ().into_response()
/// }
///
/// let state = State { /* ... */ };
Expand All @@ -105,7 +105,7 @@ use tower_service::Service;
/// extract::Extension,
/// http::{Request, StatusCode},
/// routing::get,
/// response::IntoResponse,
/// response::{IntoResponse, Response},
/// middleware::{self, Next},
/// };
/// use tower::ServiceBuilder;
Expand All @@ -116,11 +116,11 @@ use tower_service::Service;
/// async fn my_middleware<B>(
/// req: Request<B>,
/// next: Next<B>,
/// ) -> impl IntoResponse {
/// ) -> Response {
/// let state: &State = req.extensions().get().unwrap();
///
/// // ...
/// # ()
/// # ().into_response()
/// }
///
/// let state = State { /* ... */ };
Expand Down