Add ExtensionsAlreadyExtracted to PathRejection (#619)

* Add `ExtensionsAlreadyExtracted` to `PathRejection`

* format imports

* changelog
This commit is contained in:
David Pedersen 2021-12-12 23:51:18 +01:00 committed by GitHub
parent ecf3359980
commit c50b55384c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 5 deletions

View file

@ -12,10 +12,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **fixed:** `sse::Event` is more strict about what field values it supports, disallowing any SSE
events that break the specification (such as field values containing carriage returns) ([#599])
- **added:** `axum::AddExtension::layer` ([#607])
- **fixed:** Make `Path` fail with `ExtensionsAlreadyExtracted` if another extractor (such as
`Request`) has previously taken the request extensions. Thus `PathRejection` now contains a
variant with `ExtensionsAlreadyExtracted`. This is not a breaking change since `PathRejection` is
marked as `#[non_exhaustive]` ([#619])
[#599]: https://github.com/tokio-rs/axum/pull/599
[#600]: https://github.com/tokio-rs/axum/pull/600
[#607]: https://github.com/tokio-rs/axum/pull/607
[#619]: https://github.com/tokio-rs/axum/pull/619
# 0.4.2 (06. December, 2021)

View file

@ -3,6 +3,7 @@
mod de;
use super::rejection::ExtensionsAlreadyExtracted;
use crate::{
body::{boxed, Full},
extract::{rejection::*, FromRequest, RequestParts},
@ -163,10 +164,11 @@ where
type Rejection = PathRejection;
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
let params = match req
let ext = req
.extensions_mut()
.and_then(|ext| ext.get::<Option<UrlParams>>())
{
.ok_or_else::<Self::Rejection, _>(|| ExtensionsAlreadyExtracted::default().into())?;
let params = match ext.get::<Option<UrlParams>>() {
Some(Some(UrlParams(Ok(params)))) => Cow::Borrowed(params),
Some(Some(UrlParams(Err(InvalidUtf8InPathParam { key })))) => {
let err = PathDeserializationError {
@ -401,10 +403,10 @@ impl std::error::Error for FailedToDeserializePathParams {}
#[cfg(test)]
mod tests {
use http::StatusCode;
use super::*;
use crate::{routing::get, test_helpers::*, Router};
use http::{Request, StatusCode};
use hyper::Body;
use std::collections::HashMap;
#[tokio::test]
@ -508,4 +510,15 @@ mod tests {
let res = client.get("/foo").send().await;
assert_eq!(res.status(), StatusCode::OK);
}
#[tokio::test]
async fn when_extensions_are_missing() {
let app = Router::new().route("/:key", get(|_: Request<Body>, _: Path<String>| async {}));
let client = TestClient::new(app);
let res = client.get("/foo").send().await;
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
assert_eq!(res.text().await, "Extensions taken by other extractor");
}
}

View file

@ -163,6 +163,7 @@ composite_rejection! {
pub enum PathRejection {
FailedToDeserializePathParams,
MissingPathParams,
ExtensionsAlreadyExtracted,
}
}