mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-08 00:00:24 +02:00
Accept &str for Redirect (#889)
* Accept &str for Redirect * Fix doc example * fix more docs examples * update changelog * fix changelog label Co-authored-by: David Pedersen <[email protected]>
This commit is contained in:
co-authored by
David Pedersen
parent
79501afd10
commit
3084dc10ca
@@ -45,7 +45,7 @@ pub use cookie_lib::{Cookie, Key};
|
|||||||
/// // the updated jar must be returned for the changes
|
/// // the updated jar must be returned for the changes
|
||||||
/// // to be included in the response
|
/// // to be included in the response
|
||||||
/// jar.add(Cookie::new("session_id", session_id)),
|
/// jar.add(Cookie::new("session_id", session_id)),
|
||||||
/// Redirect::to("/me".parse().unwrap()),
|
/// Redirect::to("/me"),
|
||||||
/// ))
|
/// ))
|
||||||
/// } else {
|
/// } else {
|
||||||
/// Err(StatusCode::UNAUTHORIZED)
|
/// Err(StatusCode::UNAUTHORIZED)
|
||||||
@@ -214,7 +214,7 @@ impl IntoResponse for CookieJar {
|
|||||||
/// // the updated jar must be returned for the changes
|
/// // the updated jar must be returned for the changes
|
||||||
/// // to be included in the response
|
/// // to be included in the response
|
||||||
/// jar.add(Cookie::new("session_id", session_id)),
|
/// jar.add(Cookie::new("session_id", session_id)),
|
||||||
/// Redirect::to("/me".parse().unwrap()),
|
/// Redirect::to("/me"),
|
||||||
/// ))
|
/// ))
|
||||||
/// } else {
|
/// } else {
|
||||||
/// Err(StatusCode::UNAUTHORIZED)
|
/// Err(StatusCode::UNAUTHORIZED)
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- **fixed:** Fixed several routing bugs related to nested "opaque" tower services (i.e.
|
- **fixed:** Fixed several routing bugs related to nested "opaque" tower services (i.e.
|
||||||
non-`Router` services) ([#841] and [#842])
|
non-`Router` services) ([#841] and [#842])
|
||||||
- **changed:** Update to tokio-tungstenite 0.17 ([#791])
|
- **changed:** Update to tokio-tungstenite 0.17 ([#791])
|
||||||
|
- **breaking:** `Redirect::{to, temporary, permanent}` now accept `&str` instead
|
||||||
|
of `Uri` ([#889])
|
||||||
|
|
||||||
[#644]: https://github.com/tokio-rs/axum/pull/644
|
[#644]: https://github.com/tokio-rs/axum/pull/644
|
||||||
[#665]: https://github.com/tokio-rs/axum/pull/665
|
[#665]: https://github.com/tokio-rs/axum/pull/665
|
||||||
@@ -108,6 +110,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
[#841]: https://github.com/tokio-rs/axum/pull/841
|
[#841]: https://github.com/tokio-rs/axum/pull/841
|
||||||
[#842]: https://github.com/tokio-rs/axum/pull/842
|
[#842]: https://github.com/tokio-rs/axum/pull/842
|
||||||
[#879]: https://github.com/tokio-rs/axum/pull/879
|
[#879]: https://github.com/tokio-rs/axum/pull/879
|
||||||
|
[#889]: https://github.com/tokio-rs/axum/pull/889
|
||||||
|
|
||||||
# 0.4.4 (13. January, 2022)
|
# 0.4.4 (13. January, 2022)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use axum_core::response::{IntoResponse, Response};
|
use axum_core::response::{IntoResponse, Response};
|
||||||
use http::{header::LOCATION, HeaderValue, StatusCode, Uri};
|
use http::{header::LOCATION, HeaderValue, StatusCode};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
/// Response that redirects the request to another location.
|
/// Response that redirects the request to another location.
|
||||||
@@ -14,7 +14,7 @@ use std::convert::TryFrom;
|
|||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let app = Router::new()
|
/// let app = Router::new()
|
||||||
/// .route("/old", get(|| async { Redirect::permanent("/new".parse().unwrap()) }))
|
/// .route("/old", get(|| async { Redirect::permanent("/new") }))
|
||||||
/// .route("/new", get(|| async { "Hello!" }));
|
/// .route("/new", get(|| async { "Hello!" }));
|
||||||
/// # async {
|
/// # async {
|
||||||
/// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
/// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||||
@@ -40,7 +40,7 @@ impl Redirect {
|
|||||||
/// If `uri` isn't a valid [`HeaderValue`].
|
/// If `uri` isn't a valid [`HeaderValue`].
|
||||||
///
|
///
|
||||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303
|
||||||
pub fn to(uri: Uri) -> Self {
|
pub fn to(uri: &str) -> Self {
|
||||||
Self::with_status_code(StatusCode::SEE_OTHER, uri)
|
Self::with_status_code(StatusCode::SEE_OTHER, uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ impl Redirect {
|
|||||||
/// If `uri` isn't a valid [`HeaderValue`].
|
/// If `uri` isn't a valid [`HeaderValue`].
|
||||||
///
|
///
|
||||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307
|
||||||
pub fn temporary(uri: Uri) -> Self {
|
pub fn temporary(uri: &str) -> Self {
|
||||||
Self::with_status_code(StatusCode::TEMPORARY_REDIRECT, uri)
|
Self::with_status_code(StatusCode::TEMPORARY_REDIRECT, uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ impl Redirect {
|
|||||||
/// If `uri` isn't a valid [`HeaderValue`].
|
/// If `uri` isn't a valid [`HeaderValue`].
|
||||||
///
|
///
|
||||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308
|
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308
|
||||||
pub fn permanent(uri: Uri) -> Self {
|
pub fn permanent(uri: &str) -> Self {
|
||||||
Self::with_status_code(StatusCode::PERMANENT_REDIRECT, uri)
|
Self::with_status_code(StatusCode::PERMANENT_REDIRECT, uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ impl Redirect {
|
|||||||
// use the `Location` header, namely `304 Not Modified`.
|
// use the `Location` header, namely `304 Not Modified`.
|
||||||
//
|
//
|
||||||
// We're open to adding more constructors upon request, if they make sense :)
|
// We're open to adding more constructors upon request, if they make sense :)
|
||||||
fn with_status_code(status_code: StatusCode, uri: Uri) -> Self {
|
fn with_status_code(status_code: StatusCode, uri: &str) -> Self {
|
||||||
assert!(
|
assert!(
|
||||||
status_code.is_redirection(),
|
status_code.is_redirection(),
|
||||||
"not a redirection status code"
|
"not a redirection status code"
|
||||||
@@ -81,8 +81,7 @@ impl Redirect {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
status_code,
|
status_code,
|
||||||
location: HeaderValue::try_from(uri.to_string())
|
location: HeaderValue::try_from(uri).expect("URI isn't a valid header value"),
|
||||||
.expect("URI isn't a valid header value"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-32
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
util::try_downcast,
|
util::try_downcast,
|
||||||
BoxError,
|
BoxError,
|
||||||
};
|
};
|
||||||
use http::{Request, Uri};
|
use http::Request;
|
||||||
use matchit::MatchError;
|
use matchit::MatchError;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@@ -503,10 +503,10 @@ where
|
|||||||
match self.node.at(&path) {
|
match self.node.at(&path) {
|
||||||
Ok(match_) => self.call_route(match_, req),
|
Ok(match_) => self.call_route(match_, req),
|
||||||
Err(MatchError::MissingTrailingSlash) => RouteFuture::from_response(
|
Err(MatchError::MissingTrailingSlash) => RouteFuture::from_response(
|
||||||
Redirect::permanent(with_path(req.uri(), &format!("{}/", path))).into_response(),
|
Redirect::permanent(&format!("{}/", req.uri().to_string())).into_response(),
|
||||||
),
|
),
|
||||||
Err(MatchError::ExtraTrailingSlash) => RouteFuture::from_response(
|
Err(MatchError::ExtraTrailingSlash) => RouteFuture::from_response(
|
||||||
Redirect::permanent(with_path(req.uri(), path.strip_suffix('/').unwrap()))
|
Redirect::permanent(&req.uri().to_string().strip_suffix('/').unwrap())
|
||||||
.into_response(),
|
.into_response(),
|
||||||
),
|
),
|
||||||
Err(MatchError::NotFound) => match &self.fallback {
|
Err(MatchError::NotFound) => match &self.fallback {
|
||||||
@@ -517,35 +517,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_path(uri: &Uri, new_path: &str) -> Uri {
|
|
||||||
let path_and_query = if let Some(path_and_query) = uri.path_and_query() {
|
|
||||||
let new_path = if new_path.starts_with('/') {
|
|
||||||
Cow::Borrowed(new_path)
|
|
||||||
} else {
|
|
||||||
Cow::Owned(format!("/{}", new_path))
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(query) = path_and_query.query() {
|
|
||||||
Some(
|
|
||||||
format!("{}?{}", new_path, query)
|
|
||||||
.parse::<http::uri::PathAndQuery>()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Some(new_path.parse().unwrap())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut parts = http::uri::Parts::default();
|
|
||||||
parts.scheme = uri.scheme().cloned();
|
|
||||||
parts.authority = uri.authority().cloned();
|
|
||||||
parts.path_and_query = path_and_query;
|
|
||||||
|
|
||||||
Uri::from_parts(parts).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper around `matchit::Router` that supports merging two `Router`s.
|
/// Wrapper around `matchit::Router` that supports merging two `Router`s.
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
struct Node {
|
struct Node {
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ async fn discord_auth(Extension(client): Extension<BasicClient>) -> impl IntoRes
|
|||||||
.url();
|
.url();
|
||||||
|
|
||||||
// Redirect to Discord's oauth service
|
// Redirect to Discord's oauth service
|
||||||
Redirect::to(auth_url.to_string().parse().unwrap())
|
Redirect::to(&auth_url.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid user session required. If there is none, redirect to the auth page
|
// Valid user session required. If there is none, redirect to the auth page
|
||||||
@@ -139,12 +139,12 @@ async fn logout(
|
|||||||
let session = match store.load_session(cookie.to_string()).await.unwrap() {
|
let session = match store.load_session(cookie.to_string()).await.unwrap() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
// No session active, just redirect
|
// No session active, just redirect
|
||||||
None => return Redirect::to("/".parse().unwrap()),
|
None => return Redirect::to("/"),
|
||||||
};
|
};
|
||||||
|
|
||||||
store.destroy_session(session).await.unwrap();
|
store.destroy_session(session).await.unwrap();
|
||||||
|
|
||||||
Redirect::to("/".parse().unwrap())
|
Redirect::to("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@@ -193,14 +193,14 @@ async fn login_authorized(
|
|||||||
let mut headers = HeaderMap::new();
|
let mut headers = HeaderMap::new();
|
||||||
headers.insert(SET_COOKIE, cookie.parse().unwrap());
|
headers.insert(SET_COOKIE, cookie.parse().unwrap());
|
||||||
|
|
||||||
(headers, Redirect::to("/".parse().unwrap()))
|
(headers, Redirect::to("/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AuthRedirect;
|
struct AuthRedirect;
|
||||||
|
|
||||||
impl IntoResponse for AuthRedirect {
|
impl IntoResponse for AuthRedirect {
|
||||||
fn into_response(self) -> Response {
|
fn into_response(self) -> Response {
|
||||||
Redirect::temporary("/auth/discord".parse().unwrap()).into_response()
|
Redirect::temporary("/auth/discord").into_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user