axum-extra: Make axum optional dependency (#3485)

This commit is contained in:
tottoto 2025-09-21 05:50:56 +09:00 committed by GitHub
parent 40e9d7b22a
commit d184798937
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 90 additions and 46 deletions

View File

@ -9,8 +9,16 @@ and this project adheres to [Semantic Versioning].
introduced as an implicit feature through an optional dependency which was no
longer being used ([#3298])
- **breaking:** `option_layer` now maps the `Response` body type to `axum::body::Body` ([#3469])
- **breaking:** Some new features are added which need to be opted in ([#3485]).
- `Cached` extractor requires `cached` feature.
- The handler utilities require `handler` feature.
- The middleware utilities require `middleware` feature.
- `OptionalPath` extractor requires `optional-path` feature.
- The routing utilities require `routing` feature.
- `WithRejection` extractor requires `with-rejection` feature.
[#3298]: https://github.com/tokio-rs/axum/pull/3298
[#3485]: https://github.com/tokio-rs/axum/pull/3485
# 0.11.0

View File

@ -40,6 +40,7 @@ allowed = [
default = ["tracing"]
async-read-body = ["dep:tokio-util", "tokio-util?/io", "dep:tokio"]
cached = ["dep:axum"]
file-stream = [
"dep:tokio-util",
"tokio-util?/io",
@ -54,7 +55,13 @@ cookie-private = ["cookie", "cookie?/private"]
cookie-signed = ["cookie", "cookie?/signed"]
cookie-key-expansion = ["cookie", "cookie?/key-expansion"]
erased-json = ["dep:serde_json", "dep:typed-json"]
form = ["dep:form_urlencoded", "dep:serde_html_form", "dep:serde_path_to_error"]
form = [
"dep:axum",
"dep:form_urlencoded",
"dep:serde_html_form",
"dep:serde_path_to_error",
]
handler = ["dep:axum"]
json-deserializer = ["dep:serde_json", "dep:serde_path_to_error"]
json-lines = [
"dep:serde_json",
@ -64,8 +71,11 @@ json-lines = [
"tokio-stream?/io-util",
"dep:tokio",
]
middleware = ["dep:axum"]
multipart = ["dep:multer", "dep:fastrand"]
optional-path = ["dep:axum"]
protobuf = ["dep:prost"]
routing = ["axum/original-uri"]
scheme = []
query = ["dep:form_urlencoded", "dep:serde_html_form", "dep:serde_path_to_error"]
tracing = ["axum-core/tracing", "axum/tracing", "dep:tracing"]
@ -76,13 +86,13 @@ typed-routing = [
"dep:serde_html_form",
"dep:form_urlencoded",
]
with-rejection = ["dep:axum"]
# Enabled by docs.rs because it uses all-features
# Enables upstream things linked to in docs
__private_docs = ["axum/json", "dep:serde"]
[dependencies]
axum = { path = "../axum", version = "0.8.4", default-features = false, features = ["original-uri"] }
axum-core = { path = "../axum-core", version = "0.5.2" }
bytes = "1.1.0"
futures-core = "0.3"
@ -99,6 +109,7 @@ tower-layer = "0.3"
tower-service = "0.3"
# optional dependencies
axum = { path = "../axum", version = "0.8.4", default-features = false, optional = true }
axum-macros = { path = "../axum-macros", version = "0.5.0", optional = true }
cookie = { package = "cookie", version = "0.18.0", features = ["percent-encode"], optional = true }
fastrand = { version = "2.1.0", optional = true }

View File

@ -1,8 +1,10 @@
use axum::{
body::{Body, Bytes, HttpBody},
use axum_core::{
body::Body,
response::{IntoResponse, Response},
Error,
};
use bytes::Bytes;
use http_body::Body as HttpBody;
use pin_project_lite::pin_project;
use std::{
pin::Pin,

View File

@ -92,7 +92,7 @@
use std::task::{Context, Poll};
use axum::{
use axum_core::{
extract::FromRequestParts,
response::{IntoResponse, Response},
};

View File

@ -2,7 +2,7 @@
//!
//! See [`CookieJar`], [`SignedCookieJar`], and [`PrivateCookieJar`] for more details.
use axum::{
use axum_core::{
extract::FromRequestParts,
response::{IntoResponse, IntoResponseParts, Response, ResponseParts},
};

View File

@ -1,5 +1,5 @@
use super::{cookies_from_request, set_cookies, Cookie, Key};
use axum::{
use axum_core::{
extract::{FromRef, FromRequestParts},
response::{IntoResponse, IntoResponseParts, Response, ResponseParts},
};

View File

@ -1,5 +1,5 @@
use super::{cookies_from_request, set_cookies};
use axum::{
use axum_core::{
extract::{FromRef, FromRequestParts},
response::{IntoResponse, IntoResponseParts, Response, ResponseParts},
};

View File

@ -1,5 +1,5 @@
use super::rejection::{FailedToResolveHost, HostRejection};
use axum::{
use axum_core::{
extract::{FromRequestParts, OptionalFromRequestParts},
RequestPartsExt,
};

View File

@ -1,7 +1,7 @@
use axum::extract::{FromRequest, Request};
use axum_core::__composite_rejection as composite_rejection;
use axum_core::__define_rejection as define_rejection;
use axum_core::extract::rejection::BytesRejection;
use axum_core::extract::{FromRequest, Request};
use bytes::Bytes;
use http::{header, HeaderMap};
use serde_core::Deserialize;

View File

@ -1,9 +1,15 @@
//! Additional extractors.
mod cached;
mod host;
mod optional_path;
pub mod rejection;
#[cfg(feature = "optional-path")]
mod optional_path;
#[cfg(feature = "cached")]
mod cached;
#[cfg(feature = "with-rejection")]
mod with_rejection;
#[cfg(feature = "form")]
@ -25,8 +31,16 @@ pub mod multipart;
mod scheme;
#[allow(deprecated)]
#[cfg(feature = "optional-path")]
pub use self::optional_path::OptionalPath;
pub use self::{cached::Cached, host::Host, with_rejection::WithRejection};
pub use self::host::Host;
#[cfg(feature = "cached")]
pub use self::cached::Cached;
#[cfg(feature = "with-rejection")]
pub use self::with_rejection::WithRejection;
#[cfg(feature = "cookie")]
pub use self::cookie::CookieJar;

View File

@ -2,14 +2,14 @@
//!
//! See [`Multipart`] for more details.
use axum::{
body::{Body, Bytes},
use axum_core::{
RequestExt, __composite_rejection as composite_rejection,
__define_rejection as define_rejection,
body::Body,
extract::FromRequest,
response::{IntoResponse, Response},
RequestExt,
};
use axum_core::__composite_rejection as composite_rejection;
use axum_core::__define_rejection as define_rejection;
use bytes::Bytes;
use futures_core::stream::Stream;
use http::{
header::{HeaderMap, CONTENT_TYPE},
@ -284,7 +284,7 @@ fn status_code_from_multer_error(err: &multer::Error) -> StatusCode {
}
if err
.downcast_ref::<axum::Error>()
.downcast_ref::<axum_core::Error>()
.and_then(|err| err.source())
.and_then(|err| err.downcast_ref::<http_body_util::LengthLimitError>())
.is_some()

View File

@ -1,6 +1,6 @@
use axum::extract::FromRequestParts;
use axum_core::__composite_rejection as composite_rejection;
use axum_core::__define_rejection as define_rejection;
use axum_core::extract::FromRequestParts;
use http::{request::Parts, Uri};
use serde_core::de::DeserializeOwned;

View File

@ -1,8 +1,7 @@
//! Extractor that parses the scheme of a request.
//! See [`Scheme`] for more details.
use axum::extract::FromRequestParts;
use axum_core::__define_rejection as define_rejection;
use axum_core::{__define_rejection as define_rejection, extract::FromRequestParts};
use http::{
header::{HeaderMap, FORWARDED},
request::Parts,

View File

@ -1,6 +1,6 @@
//! Newline delimited JSON extractor and response.
use axum::{
use axum_core::{
body::Body,
extract::{FromRequest, Request},
response::{IntoResponse, Response},
@ -74,7 +74,7 @@ pin_project! {
},
Extractor {
#[pin]
stream: BoxStream<'static, Result<S, axum::Error>>,
stream: BoxStream<'static, Result<S, axum_core::Error>>,
},
}
}
@ -117,9 +117,9 @@ where
let deserialized_stream =
lines_stream
.map_err(axum::Error::new)
.map_err(axum_core::Error::new)
.and_then(|value| async move {
serde_json::from_str::<T>(&value).map_err(axum::Error::new)
serde_json::from_str::<T>(&value).map_err(axum_core::Error::new)
});
Ok(Self {
@ -132,7 +132,7 @@ where
}
impl<T> Stream for JsonLines<T, AsExtractor> {
type Item = Result<T, axum::Error>;
type Item = Result<T, axum_core::Error>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match self.project().inner.project() {

View File

@ -11,6 +11,7 @@
//! ---|---|---
//! `async-read-body` | Enables the [`AsyncReadBody`](crate::body::AsyncReadBody) body | No
//! `attachment` | Enables the [`Attachment`](crate::response::Attachment) response | No
//! `cached` | Enables the [`Cached`](crate::extract::Cached) extractor | No
//! `cookie` | Enables the [`CookieJar`](crate::extract::CookieJar) extractor | No
//! `cookie-private` | Enables the [`PrivateCookieJar`](crate::extract::PrivateCookieJar) extractor | No
//! `cookie-signed` | Enables the [`SignedCookieJar`](crate::extract::SignedCookieJar) extractor | No
@ -18,15 +19,20 @@
//! `erased-json` | Enables the [`ErasedJson`](crate::response::ErasedJson) response | No
//! `error-response` | Enables the [`InternalServerError`](crate::response::InternalServerError) response | No
//! `form` | Enables the [`Form`](crate::extract::Form) extractor | No
//! `handler` | Enables the [handler] utilities | No
//! `json-deserializer` | Enables the [`JsonDeserializer`](crate::extract::JsonDeserializer) extractor | No
//! `json-lines` | Enables the [`JsonLines`](crate::extract::JsonLines) extractor and response | No
//! `middleware` | Enables the [middleware] utilities | No
//! `multipart` | Enables the [`Multipart`](crate::extract::Multipart) extractor | No
//! `optional-path` | Enables the [`OptionalPath`](crate::extract::OptionalPath) extractor | No
//! `protobuf` | Enables the [`Protobuf`](crate::protobuf::Protobuf) extractor and response | No
//! `query` | Enables the [`Query`](crate::extract::Query) extractor | No
//! `routing` | Enables the [routing] utilities | No
//! `tracing` | Log rejections from built-in extractors | Yes
//! `typed-routing` | Enables the [`TypedPath`](crate::routing::TypedPath) routing utilities | No
//! `typed-header` | Enables the [`TypedHeader`] extractor and response | No
//! `file-stream` | Enables the [`FileStream`](crate::response::FileStream) response | No
//! `with-rejection` | Enables the [`WithRejection`](crate::extract::WithRejection) extractor | No
//!
//! [`axum`]: https://crates.io/crates/axum
@ -40,11 +46,17 @@ extern crate self as axum_extra;
pub mod body;
pub mod either;
pub mod extract;
pub mod handler;
pub mod middleware;
pub mod response;
#[cfg(feature = "routing")]
pub mod routing;
#[cfg(feature = "middleware")]
pub mod middleware;
#[cfg(feature = "handler")]
pub mod handler;
#[cfg(feature = "json-lines")]
pub mod json_lines;

View File

@ -1,12 +1,12 @@
//! Protocol Buffer extractor and response.
use axum::{
use axum_core::__composite_rejection as composite_rejection;
use axum_core::__define_rejection as define_rejection;
use axum_core::{
extract::{rejection::BytesRejection, FromRequest, Request},
response::{IntoResponse, Response},
RequestExt,
};
use axum_core::__composite_rejection as composite_rejection;
use axum_core::__define_rejection as define_rejection;
use bytes::BytesMut;
use http::StatusCode;
use http_body_util::BodyExt;

View File

@ -1,4 +1,4 @@
use axum::response::IntoResponse;
use axum_core::response::IntoResponse;
use http::{header, HeaderMap, HeaderValue};
use tracing::error;
@ -79,7 +79,7 @@ impl<T> IntoResponse for Attachment<T>
where
T: IntoResponse,
{
fn into_response(self) -> axum::response::Response {
fn into_response(self) -> axum_core::response::Response {
let mut headers = HeaderMap::new();
if let Some(content_type) = self.content_type {

View File

@ -1,10 +1,8 @@
use std::sync::Arc;
use axum::{
http::{header, HeaderValue, StatusCode},
response::{IntoResponse, Response},
};
use axum_core::response::{IntoResponse, Response};
use bytes::{BufMut, Bytes, BytesMut};
use http::{header, HeaderValue, StatusCode};
use serde_core::Serialize;
/// A response type that holds a JSON in serialized form.

View File

@ -1,4 +1,4 @@
use axum::{
use axum_core::{
body,
response::{IntoResponse, Response},
BoxError,

View File

@ -60,11 +60,11 @@ macro_rules! mime_response {
#[must_use]
pub struct $ident<T>(pub T);
impl<T> axum::response::IntoResponse for $ident<T>
impl<T> axum_core::response::IntoResponse for $ident<T>
where
T: axum::response::IntoResponse,
T: axum_core::response::IntoResponse,
{
fn into_response(self) -> axum::response::Response {
fn into_response(self) -> axum_core::response::Response {
(
[(
http::header::CONTENT_TYPE,

View File

@ -1,6 +1,6 @@
//! Generate forms to use in responses.
use axum::response::{IntoResponse, Response};
use axum_core::response::{IntoResponse, Response};
use fastrand;
use http::{header, HeaderMap, StatusCode};
use mime::Mime;

View File

@ -1,6 +1,6 @@
//! Extractor and response for typed headers.
use axum::{
use axum_core::{
extract::{FromRequestParts, OptionalFromRequestParts},
response::{IntoResponse, IntoResponseParts, Response, ResponseParts},
};

View File

@ -36,7 +36,7 @@ syn = { version = "2.0", features = [
[dev-dependencies]
axum = { path = "../axum", features = ["macros"] }
axum-extra = { path = "../axum-extra", features = ["typed-routing", "cookie-private", "typed-header"] }
axum-extra = { path = "../axum-extra", features = ["typed-routing", "cookie-private", "typed-header", "routing"] }
rustversion = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

View File

@ -6,7 +6,7 @@ publish = false
[dependencies]
axum = { path = "../../axum", features = ["macros"] }
axum-extra = { path = "../../axum-extra" }
axum-extra = { path = "../../axum-extra", features = ["with-rejection"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"