diff --git a/changelog/master.md b/changelog/master.md index 573c6fdd..68fcb404 100644 --- a/changelog/master.md +++ b/changelog/master.md @@ -38,3 +38,9 @@ * `GraphQLType` and `ToInputValue` are now implemented for Arc [#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) diff --git a/juniper/src/executor/mod.rs b/juniper/src/executor/mod.rs index 7b13299b..f6d62779 100644 --- a/juniper/src/executor/mod.rs +++ b/juniper/src/executor/mod.rs @@ -127,14 +127,14 @@ impl Ord for ExecutionError { #[derive(Debug, PartialEq)] pub struct FieldError { message: String, - data: Value, + extensions: Value, } impl From for FieldError { fn from(e: T) -> FieldError { FieldError { message: format!("{}", e), - data: Value::null(), + extensions: Value::null(), } } } @@ -157,7 +157,7 @@ impl FieldError { /// # 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: /// /// ```json @@ -165,7 +165,7 @@ impl FieldError { /// "errors": [ /// "message": "Could not open connection to the database", /// "locations": [{"line": 2, "column": 4}], - /// "data": { + /// "extensions": { /// "internal_error": "Connection refused" /// } /// ] @@ -173,10 +173,10 @@ impl FieldError { /// ``` /// /// If the argument is `Value::null()`, no extra data will be included. - pub fn new(e: T, data: Value) -> FieldError { + pub fn new(e: T, extensions: Value) -> FieldError { FieldError { message: format!("{}", e), - data: data, + extensions, } } @@ -186,8 +186,8 @@ impl FieldError { } #[doc(hidden)] - pub fn data(&self) -> &Value { - &self.data + pub fn extensions(&self) -> &Value { + &self.extensions } } diff --git a/juniper/src/integrations/serde.rs b/juniper/src/integrations/serde.rs index 98fdd76b..e79dc850 100644 --- a/juniper/src/integrations/serde.rs +++ b/juniper/src/integrations/serde.rs @@ -32,9 +32,9 @@ impl ser::Serialize for ExecutionError { map.serialize_key("path")?; map.serialize_value(self.path())?; - if !self.error().data().is_null() { - map.serialize_key("data")?; - map.serialize_value(self.error().data())?; + if !self.error().extensions().is_null() { + map.serialize_key("extensions")?; + map.serialize_value(self.error().extensions())?; } map.end() @@ -285,10 +285,11 @@ impl ser::Serialize for Value { #[cfg(test)] mod tests { - use super::GraphQLError; + use super::{ExecutionError, GraphQLError}; use ast::InputValue; use serde_json::from_str; use serde_json::to_string; + use {FieldError, Value}; #[test] fn int() { @@ -318,4 +319,15 @@ mod tests { 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"}}"# + ); + } } diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs index a1d88f6e..cc88103c 100644 --- a/juniper/src/lib.rs +++ b/juniper/src/lib.rs @@ -98,6 +98,8 @@ extern crate serde_derive; extern crate serde_json; extern crate fnv; + +#[cfg_attr(test, macro_use)] extern crate indexmap; #[cfg(any(test, feature = "chrono"))]