mirror of https://github.com/rwf2/Rocket.git
Replace 'SerdeError' with 'JsonError' in 'Json' data guard.
The new 'JsonError' type allows users to inspect the raw string that failed to parse as a given JSON value. Resolves #772.
This commit is contained in:
parent
1a3fd1d237
commit
74007815a0
|
@ -1,5 +1,5 @@
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::io::Read;
|
use std::io::{self, Read};
|
||||||
|
|
||||||
use rocket::outcome::{Outcome, IntoOutcome};
|
use rocket::outcome::{Outcome, IntoOutcome};
|
||||||
use rocket::request::Request;
|
use rocket::request::Request;
|
||||||
|
@ -11,24 +11,6 @@ use serde::{Serialize, Serializer};
|
||||||
use serde::de::{Deserialize, DeserializeOwned, Deserializer};
|
use serde::de::{Deserialize, DeserializeOwned, Deserializer};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
pub use serde_json::error::Error as SerdeError;
|
|
||||||
|
|
||||||
/// Like [`from_reader`] but eagerly reads the content of the reader to a string
|
|
||||||
/// and delegates to `from_str`.
|
|
||||||
///
|
|
||||||
/// [`from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html
|
|
||||||
fn from_reader_eager<R, T>(mut reader: R) -> serde_json::Result<T>
|
|
||||||
where R: Read, T: DeserializeOwned
|
|
||||||
{
|
|
||||||
let mut s = String::with_capacity(512);
|
|
||||||
if let Err(io_err) = reader.read_to_string(&mut s) {
|
|
||||||
// Error::io is private to serde_json. Do not use outside of Rocket.
|
|
||||||
return Err(SerdeError::io(io_err));
|
|
||||||
}
|
|
||||||
|
|
||||||
serde_json::from_str(&s)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The JSON type: implements `FromData` and `Responder`, allowing you to easily
|
/// The JSON type: implements `FromData` and `Responder`, allowing you to easily
|
||||||
/// consume and respond with JSON.
|
/// consume and respond with JSON.
|
||||||
///
|
///
|
||||||
|
@ -99,13 +81,39 @@ impl<T> Json<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like [`from_reader`] but eagerly reads the content of the reader to a string
|
||||||
|
/// and delegates to `from_str`.
|
||||||
|
///
|
||||||
|
/// [`from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html
|
||||||
|
fn from_reader_eager<R, T>(mut reader: R) -> Result<T, JsonError>
|
||||||
|
where R: Read, T: DeserializeOwned
|
||||||
|
{
|
||||||
|
let mut s = String::with_capacity(512);
|
||||||
|
reader.read_to_string(&mut s).map_err(JsonError::Io)?;
|
||||||
|
|
||||||
|
serde_json::from_str(&s).map_err(|e| JsonError::Parse(s, e))
|
||||||
|
}
|
||||||
|
|
||||||
/// Default limit for JSON is 1MB.
|
/// Default limit for JSON is 1MB.
|
||||||
const LIMIT: u64 = 1 << 20;
|
const LIMIT: u64 = 1 << 20;
|
||||||
|
|
||||||
impl<T: DeserializeOwned> FromData for Json<T> {
|
/// An error returned by the [`Json`] data guard when incoming data fails to
|
||||||
type Error = SerdeError;
|
/// serialize as JSON.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum JsonError {
|
||||||
|
/// An I/O error occurred while reading the incoming request data.
|
||||||
|
Io(io::Error),
|
||||||
|
/// The client's data was received successfully but failed to parse as valid
|
||||||
|
/// JSON or as the requested type. The `String` value in `.0` is the raw
|
||||||
|
/// data received from the user, while the `Error` in `.1` is the
|
||||||
|
/// deserialization error from `serde`.
|
||||||
|
Parse(String, serde_json::error::Error),
|
||||||
|
}
|
||||||
|
|
||||||
fn from_data(request: &Request, data: Data) -> data::Outcome<Self, SerdeError> {
|
impl<T: DeserializeOwned> FromData for Json<T> {
|
||||||
|
type Error = JsonError;
|
||||||
|
|
||||||
|
fn from_data(request: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
|
||||||
if !request.content_type().map_or(false, |ct| ct.is_json()) {
|
if !request.content_type().map_or(false, |ct| ct.is_json()) {
|
||||||
error_!("Content-Type is not JSON.");
|
error_!("Content-Type is not JSON.");
|
||||||
return Outcome::Forward(data);
|
return Outcome::Forward(data);
|
||||||
|
@ -122,8 +130,8 @@ impl<T: DeserializeOwned> FromData for Json<T> {
|
||||||
/// Serializes the wrapped value into JSON. Returns a response with Content-Type
|
/// Serializes the wrapped value into JSON. Returns a response with Content-Type
|
||||||
/// JSON and a fixed-size body with the serialized value. If serialization
|
/// JSON and a fixed-size body with the serialized value. If serialization
|
||||||
/// fails, an `Err` of `Status::InternalServerError` is returned.
|
/// fails, an `Err` of `Status::InternalServerError` is returned.
|
||||||
impl<T: Serialize> Responder<'static> for Json<T> {
|
impl<'a, T: Serialize> Responder<'a> for Json<T> {
|
||||||
fn respond_to(self, req: &Request) -> response::Result<'static> {
|
fn respond_to(self, req: &Request) -> response::Result<'a> {
|
||||||
serde_json::to_string(&self.0).map(|string| {
|
serde_json::to_string(&self.0).map(|string| {
|
||||||
content::Json(string).respond_to(req).unwrap()
|
content::Json(string).respond_to(req).unwrap()
|
||||||
}).map_err(|e| {
|
}).map_err(|e| {
|
||||||
|
|
|
@ -65,7 +65,7 @@ pub extern crate tera;
|
||||||
pub mod json;
|
pub mod json;
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
pub use json::{Json, SerdeError, JsonValue};
|
pub use json::{Json, JsonError, JsonValue};
|
||||||
|
|
||||||
#[cfg(feature = "msgpack")]
|
#[cfg(feature = "msgpack")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
Loading…
Reference in New Issue