mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-03 00:00:07 +02:00
Backport changes from main to v0.6.x (#2141)
Co-authored-by: David Pedersen <[email protected]>
This commit is contained in:
co-authored by
David Pedersen
parent
a25ed293d7
commit
68333b2fcf
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning].
|
|||||||
|
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
- None.
|
- **added:** `Clone` implementation for `ErasedJson` ([#2142])
|
||||||
|
|
||||||
|
[#2142]: https://github.com/tokio-rs/axum/pull/2142
|
||||||
|
|
||||||
# 0.7.6 (02. August, 2023)
|
# 0.7.6 (02. August, 2023)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
http::{header, HeaderValue, StatusCode},
|
http::{header, HeaderValue, StatusCode},
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
@@ -29,21 +31,29 @@ use serde::Serialize;
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "erased-json")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "erased-json")))]
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct ErasedJson(serde_json::Result<Bytes>);
|
pub struct ErasedJson(Result<Bytes, Arc<serde_json::Error>>);
|
||||||
|
|
||||||
impl ErasedJson {
|
impl ErasedJson {
|
||||||
/// Create an `ErasedJson` by serializing a value with the compact formatter.
|
/// Create an `ErasedJson` by serializing a value with the compact formatter.
|
||||||
pub fn new<T: Serialize>(val: T) -> Self {
|
pub fn new<T: Serialize>(val: T) -> Self {
|
||||||
let mut bytes = BytesMut::with_capacity(128);
|
let mut bytes = BytesMut::with_capacity(128);
|
||||||
Self(serde_json::to_writer((&mut bytes).writer(), &val).map(|_| bytes.freeze()))
|
let result = match serde_json::to_writer((&mut bytes).writer(), &val) {
|
||||||
|
Ok(()) => Ok(bytes.freeze()),
|
||||||
|
Err(e) => Err(Arc::new(e)),
|
||||||
|
};
|
||||||
|
Self(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an `ErasedJson` by serializing a value with the pretty formatter.
|
/// Create an `ErasedJson` by serializing a value with the pretty formatter.
|
||||||
pub fn pretty<T: Serialize>(val: T) -> Self {
|
pub fn pretty<T: Serialize>(val: T) -> Self {
|
||||||
let mut bytes = BytesMut::with_capacity(128);
|
let mut bytes = BytesMut::with_capacity(128);
|
||||||
Self(serde_json::to_writer_pretty((&mut bytes).writer(), &val).map(|_| bytes.freeze()))
|
let result = match serde_json::to_writer_pretty((&mut bytes).writer(), &val) {
|
||||||
|
Ok(()) => Ok(bytes.freeze()),
|
||||||
|
Err(e) => Err(Arc::new(e)),
|
||||||
|
};
|
||||||
|
Self(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- **added:** `WebSocketUpgrade::write_buffer_size` and `WebSocketUpgrade::max_write_buffer_size`
|
- **added:** `WebSocketUpgrade::write_buffer_size` and `WebSocketUpgrade::max_write_buffer_size`
|
||||||
- **changed:** Deprecate `WebSocketUpgrade::max_send_queue`
|
- **changed:** Deprecate `WebSocketUpgrade::max_send_queue`
|
||||||
- **change:** Update tokio-tungstenite to 0.20
|
- **change:** Update tokio-tungstenite to 0.20
|
||||||
|
- **added:** Implement `Handler` for `T: IntoResponse` ([#2140])
|
||||||
|
|
||||||
|
[#2140]: https://github.com/tokio-rs/axum/pull/2140
|
||||||
|
|
||||||
# 0.6.19 (17. July, 2023)
|
# 0.6.19 (17. July, 2023)
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,31 @@ pub use self::service::HandlerService;
|
|||||||
/// {}
|
/// {}
|
||||||
/// ```
|
/// ```
|
||||||
#[doc = include_str!("../docs/debugging_handler_type_errors.md")]
|
#[doc = include_str!("../docs/debugging_handler_type_errors.md")]
|
||||||
|
///
|
||||||
|
/// # Handlers that aren't functions
|
||||||
|
///
|
||||||
|
/// The `Handler` trait is also implemented for `T: IntoResponse`. That allows easily returning
|
||||||
|
/// fixed data for routes:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use axum::{
|
||||||
|
/// Router,
|
||||||
|
/// routing::{get, post},
|
||||||
|
/// Json,
|
||||||
|
/// http::StatusCode,
|
||||||
|
/// };
|
||||||
|
/// use serde_json::json;
|
||||||
|
///
|
||||||
|
/// let app = Router::new()
|
||||||
|
/// // respond with a fixed string
|
||||||
|
/// .route("/", get("Hello, World!"))
|
||||||
|
/// // or return some mock data
|
||||||
|
/// .route("/users", post((
|
||||||
|
/// StatusCode::CREATED,
|
||||||
|
/// Json(json!({ "id": 1, "username": "alice" })),
|
||||||
|
/// )));
|
||||||
|
/// # let _: Router = app;
|
||||||
|
/// ```
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
nightly_error_messages,
|
nightly_error_messages,
|
||||||
rustc_on_unimplemented(
|
rustc_on_unimplemented(
|
||||||
@@ -231,6 +256,24 @@ macro_rules! impl_handler {
|
|||||||
|
|
||||||
all_the_tuples!(impl_handler);
|
all_the_tuples!(impl_handler);
|
||||||
|
|
||||||
|
mod private {
|
||||||
|
// Marker type for `impl<T: IntoResponse> Handler for T`
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
|
pub enum IntoResponseHandler {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S, B> Handler<private::IntoResponseHandler, S, B> for T
|
||||||
|
where
|
||||||
|
T: IntoResponse + Clone + Send + 'static,
|
||||||
|
B: Send + 'static,
|
||||||
|
{
|
||||||
|
type Future = std::future::Ready<Response>;
|
||||||
|
|
||||||
|
fn call(self, _req: Request<B>, _state: S) -> Self::Future {
|
||||||
|
std::future::ready(self.into_response())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A [`Service`] created from a [`Handler`] by applying a Tower middleware.
|
/// A [`Service`] created from a [`Handler`] by applying a Tower middleware.
|
||||||
///
|
///
|
||||||
/// Created with [`Handler::layer`]. See that method for more details.
|
/// Created with [`Handler::layer`]. See that method for more details.
|
||||||
|
|||||||
@@ -1026,3 +1026,14 @@ async fn connect_going_to_default_fallback() {
|
|||||||
let body = hyper::body::to_bytes(res).await.unwrap();
|
let body = hyper::body::to_bytes(res).await.unwrap();
|
||||||
assert!(body.is_empty());
|
assert!(body.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[crate::test]
|
||||||
|
async fn impl_handler_for_into_response() {
|
||||||
|
let app = Router::new().route("/things", post((StatusCode::CREATED, "thing created")));
|
||||||
|
|
||||||
|
let client = TestClient::new(app);
|
||||||
|
|
||||||
|
let res = client.post("/things").send().await;
|
||||||
|
assert_eq!(res.status(), StatusCode::CREATED);
|
||||||
|
assert_eq!(res.text().await, "thing created");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user