mirror of
https://github.com/tokio-rs/axum.git
synced 2025-03-08 08:56:24 +01:00
parent
6a82dd75ea
commit
a6b3e09827
6 changed files with 12 additions and 232 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -28,13 +28,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `routing::EmptyRouterFuture` moved to `routing::future::EmptyRouterFuture` ([#133](https://github.com/tokio-rs/axum/pull/133))
|
||||
- `routing::RouteFuture` moved to `routing::future::RouteFuture` ([#133](https://github.com/tokio-rs/axum/pull/133))
|
||||
- `service::BoxResponseBodyFuture` moved to `service::future::BoxResponseBodyFuture` ([#133](https://github.com/tokio-rs/axum/pull/133))
|
||||
- The following types no longer implement `Copy` ([#132](https://github.com/tokio-rs/axum/pull/132)):
|
||||
- The following types no longer implement `Copy` ([#132](https://github.com/tokio-rs/axum/pull/132))
|
||||
- `EmptyRouter`
|
||||
- `ExtractorMiddleware`
|
||||
- `ExtractorMiddlewareLayer`
|
||||
- Replace `axum::body::BoxStdError` with `axum::Error`, which supports downcasting ([#150](https://github.com/tokio-rs/axum/pull/150))
|
||||
- `WebSocket` now uses `axum::Error` as its error type ([#150](https://github.com/tokio-rs/axum/pull/150))
|
||||
- `RequestParts` changes:
|
||||
- `RequestParts` changes ([#153](https://github.com/tokio-rs/axum/pull/153))
|
||||
- `method` new returns an `&http::Method`
|
||||
- `method_mut` new returns an `&mut http::Method`
|
||||
- `take_method` has been removed
|
||||
|
@ -42,9 +42,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `uri_mut` new returns an `&mut http::Uri`
|
||||
- `take_uri` has been removed
|
||||
- These rejections have been removed as they're no longer used
|
||||
- `MethodAlreadyExtracted`
|
||||
- `UriAlreadyExtracted`
|
||||
- `VersionAlreadyExtracted`
|
||||
- `MethodAlreadyExtracted` ([#153](https://github.com/tokio-rs/axum/pull/153))
|
||||
- `UriAlreadyExtracted` ([#153](https://github.com/tokio-rs/axum/pull/153))
|
||||
- `VersionAlreadyExtracted` ([#153](https://github.com/tokio-rs/axum/pull/153))
|
||||
- `UrlParamsRejection`
|
||||
- `InvalidUrlParam`
|
||||
- Removed `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead
|
||||
|
||||
# 0.1.3 (06. August, 2021)
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
//!
|
||||
//! async fn handler(
|
||||
//! // Extract captured parameters from the URL
|
||||
//! params: extract::UrlParamsMap,
|
||||
//! params: extract::Path<HashMap<String, String>>,
|
||||
//! // Parse query string into a `HashMap`
|
||||
//! query_params: extract::Query<HashMap<String, String>>,
|
||||
//! // Buffer the request body into a `Bytes`
|
||||
|
@ -266,8 +266,6 @@ mod query;
|
|||
mod raw_query;
|
||||
mod request_parts;
|
||||
mod tuple;
|
||||
mod url_params;
|
||||
mod url_params_map;
|
||||
|
||||
#[doc(inline)]
|
||||
#[allow(deprecated)]
|
||||
|
@ -281,8 +279,6 @@ pub use self::{
|
|||
query::Query,
|
||||
raw_query::RawQuery,
|
||||
request_parts::{Body, BodyStream},
|
||||
url_params::UrlParams,
|
||||
url_params_map::UrlParamsMap,
|
||||
};
|
||||
#[doc(no_inline)]
|
||||
pub use crate::Json;
|
||||
|
|
|
@ -82,9 +82,7 @@ define_rejection! {
|
|||
define_rejection! {
|
||||
#[status = INTERNAL_SERVER_ERROR]
|
||||
#[body = "No url params found for matched route. This is a bug in axum. Please open an issue"]
|
||||
/// Rejection type for [`UrlParamsMap`](super::UrlParamsMap) and
|
||||
/// [`UrlParams`](super::UrlParams) if you try and extract the URL params
|
||||
/// more than once.
|
||||
/// Rejection type used if you try and extract the URL params more than once.
|
||||
pub struct MissingRouteParams;
|
||||
}
|
||||
|
||||
|
@ -110,44 +108,6 @@ define_rejection! {
|
|||
pub struct InvalidFormContentType;
|
||||
}
|
||||
|
||||
/// Rejection type for [`UrlParams`](super::UrlParams) if the capture route
|
||||
/// param didn't have the expected type.
|
||||
#[derive(Debug)]
|
||||
pub struct InvalidUrlParam {
|
||||
type_name: &'static str,
|
||||
}
|
||||
|
||||
impl InvalidUrlParam {
|
||||
pub(super) fn new<T>() -> Self {
|
||||
InvalidUrlParam {
|
||||
type_name: std::any::type_name::<T>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InvalidUrlParam {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Invalid URL param. Expected something of type `{}`",
|
||||
self.type_name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for InvalidUrlParam {}
|
||||
|
||||
impl IntoResponse for InvalidUrlParam {
|
||||
type Body = Full<Bytes>;
|
||||
type BodyError = Infallible;
|
||||
|
||||
fn into_response(self) -> http::Response<Self::Body> {
|
||||
let mut res = http::Response::new(Full::from(self.to_string()));
|
||||
*res.status_mut() = http::StatusCode::BAD_REQUEST;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Rejection type for [`Path`](super::Path) if the capture route
|
||||
/// param didn't have the expected type.
|
||||
#[derive(Debug)]
|
||||
|
@ -269,17 +229,6 @@ composite_rejection! {
|
|||
}
|
||||
}
|
||||
|
||||
composite_rejection! {
|
||||
/// Rejection used for [`UrlParams`](super::UrlParams).
|
||||
///
|
||||
/// Contains one variant for each way the [`UrlParams`](super::UrlParams) extractor
|
||||
/// can fail.
|
||||
pub enum UrlParamsRejection {
|
||||
InvalidUrlParam,
|
||||
MissingRouteParams,
|
||||
}
|
||||
}
|
||||
|
||||
composite_rejection! {
|
||||
/// Rejection used for [`Path`](super::Path).
|
||||
///
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
use super::{rejection::*, FromRequest, RequestParts};
|
||||
use async_trait::async_trait;
|
||||
use std::{ops::Deref, str::FromStr};
|
||||
|
||||
/// Extractor that will get captures from the URL and parse them.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use axum::{extract::UrlParams, prelude::*};
|
||||
/// use uuid::Uuid;
|
||||
///
|
||||
/// async fn users_teams_show(
|
||||
/// UrlParams(params): UrlParams<(Uuid, Uuid)>,
|
||||
/// ) {
|
||||
/// let user_id: Uuid = params.0;
|
||||
/// let team_id: Uuid = params.1;
|
||||
///
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// let app = route("/users/:user_id/team/:team_id", get(users_teams_show));
|
||||
/// # async {
|
||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
///
|
||||
/// Note that you can only have one URL params extractor per handler. If you
|
||||
/// have multiple it'll response with `500 Internal Server Error`.
|
||||
#[derive(Debug)]
|
||||
#[deprecated(since = "0.1.3", note = "Use `axum::extract::Path` instead.")]
|
||||
pub struct UrlParams<T>(pub T);
|
||||
|
||||
macro_rules! impl_parse_url {
|
||||
() => {};
|
||||
|
||||
( $head:ident, $($tail:ident),* $(,)? ) => {
|
||||
#[async_trait]
|
||||
#[allow(deprecated)]
|
||||
impl<B, $head, $($tail,)*> FromRequest<B> for UrlParams<($head, $($tail,)*)>
|
||||
where
|
||||
$head: FromStr + Send,
|
||||
$( $tail: FromStr + Send, )*
|
||||
B: Send,
|
||||
{
|
||||
type Rejection = UrlParamsRejection;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
let params = if let Some(params) = req
|
||||
.extensions_mut()
|
||||
.and_then(|ext| {
|
||||
ext.get_mut::<Option<crate::routing::UrlParams>>()
|
||||
})
|
||||
{
|
||||
if let Some(params) = params {
|
||||
params.0.clone()
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
} else {
|
||||
return Err(MissingRouteParams.into())
|
||||
};
|
||||
|
||||
if let [(_, $head), $((_, $tail),)*] = &*params {
|
||||
let $head = if let Ok(x) = $head.as_str().parse::<$head>() {
|
||||
x
|
||||
} else {
|
||||
return Err(InvalidUrlParam::new::<$head>().into());
|
||||
};
|
||||
|
||||
$(
|
||||
let $tail = if let Ok(x) = $tail.as_str().parse::<$tail>() {
|
||||
x
|
||||
} else {
|
||||
return Err(InvalidUrlParam::new::<$tail>().into());
|
||||
};
|
||||
)*
|
||||
|
||||
Ok(UrlParams(($head, $($tail,)*)))
|
||||
} else {
|
||||
Err(MissingRouteParams.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_parse_url!($($tail,)*);
|
||||
};
|
||||
}
|
||||
|
||||
impl_parse_url!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> Deref for UrlParams<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
use super::{rejection::*, FromRequest, RequestParts};
|
||||
use crate::util::ByteStr;
|
||||
use async_trait::async_trait;
|
||||
use std::{collections::HashMap, str::FromStr};
|
||||
|
||||
/// Extractor that will get captures from the URL.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use axum::prelude::*;
|
||||
///
|
||||
/// async fn users_show(params: extract::UrlParamsMap) {
|
||||
/// let id: Option<&str> = params.get("id");
|
||||
///
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// let app = route("/users/:id", get(users_show));
|
||||
/// # async {
|
||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||
/// # };
|
||||
/// ```
|
||||
///
|
||||
/// Note that you can only have one URL params extractor per handler. If you
|
||||
/// have multiple it'll response with `500 Internal Server Error`.
|
||||
#[derive(Debug)]
|
||||
#[deprecated(since = "0.1.3", note = "Use `axum::extract::Path` instead.")]
|
||||
pub struct UrlParamsMap(HashMap<ByteStr, ByteStr>);
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl UrlParamsMap {
|
||||
/// Look up the value for a key.
|
||||
pub fn get(&self, key: &str) -> Option<&str> {
|
||||
self.0.get(&ByteStr::new(key)).map(|s| s.as_str())
|
||||
}
|
||||
|
||||
/// Look up the value for a key and parse it into a value of type `T`.
|
||||
pub fn get_typed<T>(&self, key: &str) -> Option<Result<T, T::Err>>
|
||||
where
|
||||
T: FromStr,
|
||||
{
|
||||
self.get(key).map(str::parse)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[allow(deprecated)]
|
||||
impl<B> FromRequest<B> for UrlParamsMap
|
||||
where
|
||||
B: Send,
|
||||
{
|
||||
type Rejection = MissingRouteParams;
|
||||
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
if let Some(params) = req
|
||||
.extensions_mut()
|
||||
.and_then(|ext| ext.get_mut::<Option<crate::routing::UrlParams>>())
|
||||
{
|
||||
if let Some(params) = params {
|
||||
Ok(Self(params.0.iter().cloned().collect()))
|
||||
} else {
|
||||
Ok(Self(Default::default()))
|
||||
}
|
||||
} else {
|
||||
Err(MissingRouteParams)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -830,8 +830,9 @@ where
|
|||
///
|
||||
/// ```
|
||||
/// use axum::{routing::nest, prelude::*};
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// async fn users_get(params: extract::UrlParamsMap) {
|
||||
/// async fn users_get(extract::Path(params): extract::Path<HashMap<String, String>>) {
|
||||
/// // Both `version` and `id` were captured even though `users_api` only
|
||||
/// // explicitly captures `id`.
|
||||
/// let version = params.get("version");
|
||||
|
|
Loading…
Add table
Reference in a new issue