Remove UrlParamsMap and UrlParams (#154)

Use `extract::Path` instead.
This commit is contained in:
David Pedersen 2021-08-07 21:22:08 +02:00 committed by GitHub
parent 6a82dd75ea
commit a6b3e09827
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 12 additions and 232 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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).
///

View file

@ -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
}
}

View file

@ -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)
}
}
}

View file

@ -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");