1
0
Fork 0
mirror of https://github.com/tokio-rs/axum.git synced 2025-04-26 13:56:22 +02:00

Add axum_extra::response::ErasedJson ()

This commit is contained in:
Jonas Platte 2021-11-17 22:54:02 +01:00 committed by GitHub
parent a16ea65031
commit b43b9ed69d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 1 deletions

View file

@ -10,5 +10,10 @@ readme = "README.md"
repository = "https://github.com/tokio-rs/axum"
version = "0.1.0"
[features]
erased-json = ["serde", "serde_json"]
[dependencies]
axum = { path = "../axum", version = "0.3" }
serde = { version = "1.0.130", optional = true }
serde_json = { version = "1.0.71", optional = true }

View file

@ -41,3 +41,5 @@
#![forbid(unsafe_code)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(test, allow(clippy::float_cmp))]
pub mod response;

View file

@ -0,0 +1,67 @@
use std::convert::Infallible;
use axum::{
body::{Bytes, Full},
http::{header, HeaderValue, Response, StatusCode},
response::IntoResponse,
};
use serde::Serialize;
/// A response type that holds a JSON in serialized form.
///
/// This allows returning a borrowing type from a handler, or returning different response
/// types as JSON from different branches inside a handler.
///
/// # Example
///
/// ```rust
/// # use axum::{response::IntoResponse};
/// # use axum_extra::response::ErasedJson;
/// async fn handler() -> impl IntoResponse {
/// # let condition = true;
/// # let foo = ();
/// # let bar = vec![()];
/// // ...
///
/// if condition {
/// ErasedJson::new(&foo)
/// } else {
/// ErasedJson::new(&bar)
/// }
/// }
/// ```
#[derive(Debug)]
pub struct ErasedJson(serde_json::Result<Vec<u8>>);
impl ErasedJson {
/// Create an `ErasedJson` by serializing a value.
pub fn new<T: Serialize>(val: T) -> Self {
Self(serde_json::to_vec(&val))
}
}
impl IntoResponse for ErasedJson {
type Body = Full<Bytes>;
type BodyError = Infallible;
fn into_response(self) -> Response<Self::Body> {
#[allow(clippy::declare_interior_mutable_const)]
const APPLICATION_JSON: HeaderValue = HeaderValue::from_static("application/json");
let bytes = match self.0 {
Ok(res) => res,
Err(err) => {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(header::CONTENT_TYPE, "text/plain")
.body(Full::from(err.to_string()))
.unwrap();
}
};
let mut res = Response::new(Full::from(bytes));
res.headers_mut()
.insert(header::CONTENT_TYPE, APPLICATION_JSON);
res
}
}

View file

@ -0,0 +1,7 @@
//! Additional types for generating responses.
#[cfg(feature = "erased-json")]
mod erased_json;
#[cfg(feature = "erased-json")]
pub use erased_json::ErasedJson;

View file

@ -45,7 +45,7 @@ base64 = { optional = true, version = "0.13" }
headers = { optional = true, version = "0.3" }
mime = { optional = true, version = "0.3" }
multer = { optional = true, version = "2.0.0" }
serde_json = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true, features = ["raw_value"] }
sha-1 = { optional = true, version = "0.9.6" }
tokio-tungstenite = { optional = true, version = "0.16" }