Use 'extensions' as field for error details (#219)

This commit is contained in:
Damir Vandic 2018-08-13 15:53:52 +02:00 committed by Christian Legnitto
parent 90b89f00ee
commit ec59766d51
4 changed files with 32 additions and 12 deletions

View file

@ -38,3 +38,9 @@
* `GraphQLType` and `ToInputValue` are now implemented for Arc<T> * `GraphQLType` and `ToInputValue` are now implemented for Arc<T>
[#212](https://github.com/graphql-rust/juniper/pull/212) [#212](https://github.com/graphql-rust/juniper/pull/212)
* Error responses no longer have a *data* field, instead, error details are stored in the *extensions* field
**Note:** while this is a breaking change, it is a necessary one to better align with the latest [GraphQL June 2018](https://facebook.github.io/graphql/June2018/#sec-Errors) specification, which defines the reserved *extensions* field for error details.
[#219](https://github.com/graphql-rust/juniper/pull/219)

View file

@ -127,14 +127,14 @@ impl Ord for ExecutionError {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct FieldError { pub struct FieldError {
message: String, message: String,
data: Value, extensions: Value,
} }
impl<T: Display> From<T> for FieldError { impl<T: Display> From<T> for FieldError {
fn from(e: T) -> FieldError { fn from(e: T) -> FieldError {
FieldError { FieldError {
message: format!("{}", e), message: format!("{}", e),
data: Value::null(), extensions: Value::null(),
} }
} }
} }
@ -157,7 +157,7 @@ impl FieldError {
/// # fn main() { } /// # fn main() { }
/// ``` /// ```
/// ///
/// The `data` parameter will be added to the `"data"` field of the error /// The `extensions` parameter will be added to the `"extensions"` field of the error
/// object in the JSON response: /// object in the JSON response:
/// ///
/// ```json /// ```json
@ -165,7 +165,7 @@ impl FieldError {
/// "errors": [ /// "errors": [
/// "message": "Could not open connection to the database", /// "message": "Could not open connection to the database",
/// "locations": [{"line": 2, "column": 4}], /// "locations": [{"line": 2, "column": 4}],
/// "data": { /// "extensions": {
/// "internal_error": "Connection refused" /// "internal_error": "Connection refused"
/// } /// }
/// ] /// ]
@ -173,10 +173,10 @@ impl FieldError {
/// ``` /// ```
/// ///
/// If the argument is `Value::null()`, no extra data will be included. /// If the argument is `Value::null()`, no extra data will be included.
pub fn new<T: Display>(e: T, data: Value) -> FieldError { pub fn new<T: Display>(e: T, extensions: Value) -> FieldError {
FieldError { FieldError {
message: format!("{}", e), message: format!("{}", e),
data: data, extensions,
} }
} }
@ -186,8 +186,8 @@ impl FieldError {
} }
#[doc(hidden)] #[doc(hidden)]
pub fn data(&self) -> &Value { pub fn extensions(&self) -> &Value {
&self.data &self.extensions
} }
} }

View file

@ -32,9 +32,9 @@ impl ser::Serialize for ExecutionError {
map.serialize_key("path")?; map.serialize_key("path")?;
map.serialize_value(self.path())?; map.serialize_value(self.path())?;
if !self.error().data().is_null() { if !self.error().extensions().is_null() {
map.serialize_key("data")?; map.serialize_key("extensions")?;
map.serialize_value(self.error().data())?; map.serialize_value(self.error().extensions())?;
} }
map.end() map.end()
@ -285,10 +285,11 @@ impl ser::Serialize for Value {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::GraphQLError; use super::{ExecutionError, GraphQLError};
use ast::InputValue; use ast::InputValue;
use serde_json::from_str; use serde_json::from_str;
use serde_json::to_string; use serde_json::to_string;
use {FieldError, Value};
#[test] #[test]
fn int() { fn int() {
@ -318,4 +319,15 @@ mod tests {
r#"[{"message":"Unknown operation"}]"# r#"[{"message":"Unknown operation"}]"#
); );
} }
#[test]
fn error_extensions() {
assert_eq!(
to_string(&ExecutionError::at_origin(FieldError::new(
"foo error",
Value::Object(indexmap!{"foo".to_string() => Value::String("bar".to_string())}),
))).unwrap(),
r#"{"message":"foo error","locations":[{"line":1,"column":1}],"path":[],"extensions":{"foo":"bar"}}"#
);
}
} }

View file

@ -98,6 +98,8 @@ extern crate serde_derive;
extern crate serde_json; extern crate serde_json;
extern crate fnv; extern crate fnv;
#[cfg_attr(test, macro_use)]
extern crate indexmap; extern crate indexmap;
#[cfg(any(test, feature = "chrono"))] #[cfg(any(test, feature = "chrono"))]