Skip to content

Commit 54cfbeb

Browse files
- Replaced rustc-serialization logic with Serde.
- Added a GraphQlIronError - Changed execute from lib.rs to execute_query
1 parent 9adc0c4 commit 54cfbeb

File tree

1 file changed

+118
-45
lines changed

1 file changed

+118
-45
lines changed

src/integrations/iron_handlers.rs

Lines changed: 118 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,19 @@ use iron::status;
77
use iron::method;
88
use iron::url::Url;
99

10-
use std::collections::BTreeMap;
10+
use std::io::Read;
11+
use std::io::Error as IoError;
12+
use std::io::ErrorKind;
13+
use std::collections::HashMap;
14+
use std::error::Error;
15+
use std::fmt;
16+
use std::boxed::Box;
1117

12-
use rustc_serialize::json::{ToJson, Json};
18+
use serde_json;
19+
use serde_json::Value as Json;
20+
use serde_json::error::Error as SerdeError;
1321

14-
use ::{InputValue, GraphQLType, RootNode, Variables, execute};
22+
use ::{InputValue, GraphQLType, RootNode, Variables, execute as execute_query};
1523

1624
/// Handler that executes GraphQL queries in the given schema
1725
///
@@ -77,59 +85,74 @@ impl<'a, CtxFactory, Query, Mutation, CtxT>
7785
}
7886

7987
fn handle_post(&self, req: &mut Request) -> IronResult<Response> {
80-
let json_data = itry!(Json::from_reader(&mut req.body));
81-
82-
let json_obj = match json_data {
83-
Json::Object(o) => o,
84-
_ => return Ok(Response::with((status::BadRequest, "No JSON object was decoded"))),
85-
};
86-
87-
let mut query = None;
88-
let mut variables = Variables::new();
89-
90-
for (k, v) in json_obj {
91-
if k == "query" {
92-
query = v.as_string().map(|s| s.to_owned());
88+
let mut request_payload = String::new();
89+
itry!(req.body.read_to_string(&mut request_payload));
90+
let json_data =
91+
match serde_json::from_str::<Json>(&*request_payload) {
92+
Ok(json) => json,
93+
Err(err) => {
94+
let error = IronError::new(
95+
Box::new(GraphQlIronError::Serde(err)),
96+
(status::BadRequest, "No JSON object was decoded."));
97+
return Err(error)
98+
}
99+
};
100+
match json_data {
101+
Json::Object(json_obj) => {
102+
let mut query = None;
103+
let mut variables = Variables::new();
104+
for (k, v) in json_obj {
105+
if k == "query" {
106+
query = v.as_str().map(|query| query.to_owned());
107+
}
108+
else if k == "variables" {
109+
variables = InputValue::from_json(v).to_object_value()
110+
.map(|o| o.into_iter().map(|(k, v)| (k.to_owned(), v.clone())).collect())
111+
.unwrap_or_default();
112+
}
113+
}
114+
let query = iexpect!(query);
115+
self.execute(req, &query, &variables)
93116
}
94-
else if k == "variables" {
95-
variables = InputValue::from_json(v).to_object_value()
96-
.map(|o| o.into_iter().map(|(k, v)| (k.to_owned(), v.clone())).collect())
97-
.unwrap_or_default();
117+
_ => {
118+
let error = IronError::new(
119+
Box::new(GraphQlIronError::IO(IoError::new(ErrorKind::InvalidData,
120+
"Was able parse a JSON item but it\
121+
was not an object as expected."))),
122+
(status::BadRequest, "No JSON object was decoded."));
123+
Err(error)
98124
}
99125
}
100-
101-
let query = iexpect!(query);
102-
103-
self.execute(req, &query, &variables)
104126
}
105127

106128
fn execute(&self, req: &mut Request, query: &str, variables: &Variables) -> IronResult<Response> {
107129
let context = (self.context_factory)(req);
108-
let result = execute(query, None, &self.root_node, variables, &context);
109-
130+
let result = execute_query(query, None, &self.root_node, variables, &context);
110131
let content_type = "application/json".parse::<Mime>().unwrap();
111-
let mut map = BTreeMap::new();
132+
let mut map = HashMap::new();
112133

113134
match result {
114135
Ok((result, errors)) => {
115-
map.insert("data".to_owned(), result.to_json());
136+
let response_data = serde_json::to_value(result)
137+
.expect("Failed to convert response data to JSON.");
138+
map.insert("data".to_owned(), response_data);
116139

117140
if !errors.is_empty() {
118-
map.insert("errors".to_owned(), errors.to_json());
141+
let response_data = serde_json::to_value(errors)
142+
.expect("Failed to convert the errors to JSON.");
143+
map.insert("errors".to_owned(), response_data);
119144
}
120-
121-
let data = Json::Object(map);
122-
let json = data.pretty();
123-
124-
Ok(Response::with((content_type, status::Ok, json.to_string())))
145+
let data = serde_json::to_value(map).expect("Failed to convert response to JSON");
146+
let json = serde_json::to_string_pretty(&data).expect("Failed to convert response to JSON.");
147+
Ok(Response::with((content_type, status::Ok, json)))
125148
}
126-
127149
Err(err) => {
128-
map.insert("errors".to_owned(), err.to_json());
129-
130-
let data = Json::Object(map);
131-
let json = data.pretty();
132-
150+
let response_data = serde_json::to_value(err)
151+
.expect("Failed to convert error data to JSON.");
152+
map.insert("errors".to_owned(), response_data);
153+
let data = serde_json::to_value(map).expect("Failed to convert response to JSON");
154+
let json = serde_json::to_string_pretty(&data)
155+
.expect("Failed to convert response to JSON");
133156
Ok(Response::with((content_type, status::BadRequest, json.to_string())))
134157
}
135158
}
@@ -236,11 +259,61 @@ impl Handler for GraphiQLHandler {
236259
}
237260
}
238261

262+
/// A general error allowing the developer to see the underlying issue.
263+
pub enum GraphQlIronError {
264+
///Captures any errors that were caused by Serde.
265+
Serde(SerdeError),
266+
/// Captures any error related the IO.
267+
IO(IoError)
268+
}
269+
270+
impl fmt::Display for GraphQlIronError {
271+
fn fmt(&self, mut f: &mut fmt::Formatter) -> fmt::Result {
272+
match *self {
273+
GraphQlIronError::Serde(ref err) => fmt::Display::fmt(err, &mut f),
274+
GraphQlIronError::IO(ref err) => fmt::Display::fmt(err, &mut f),
275+
}
276+
}
277+
}
278+
279+
impl fmt::Debug for GraphQlIronError {
280+
fn fmt(&self, mut f: &mut fmt::Formatter) -> fmt::Result {
281+
match *self {
282+
GraphQlIronError::Serde(ref err) => fmt::Debug::fmt(err, &mut f),
283+
GraphQlIronError::IO(ref err) => fmt::Debug::fmt(err, &mut f),
284+
}
285+
}
286+
}
287+
288+
impl Error for GraphQlIronError {
289+
fn description(&self) -> &str {
290+
match *self {
291+
GraphQlIronError::Serde(ref err) => {
292+
err.description()
293+
},
294+
GraphQlIronError::IO(ref err) => {
295+
err.description()
296+
}
297+
}
298+
}
299+
300+
fn cause(&self) -> Option<&Error> {
301+
match *self {
302+
GraphQlIronError::Serde(ref err) => {
303+
err.cause()
304+
}
305+
GraphQlIronError::IO(ref err) => {
306+
err.cause()
307+
}
308+
}
309+
}
310+
}
311+
239312

240313
#[cfg(test)]
241314
mod tests {
242-
use rustc_serialize::json::Json;
243-
315+
use serde_json::Value as Json;
316+
use serde_json;
244317
use iron::prelude::*;
245318
use iron::status;
246319
use iron::headers;
@@ -267,7 +340,7 @@ mod tests {
267340
fn unwrap_json_response(resp: Response) -> Json {
268341
let result = response::extract_body_to_string(resp);
269342

270-
Json::from_str(&result).expect("Could not parse JSON object")
343+
serde_json::from_str::<Json>(&result).expect("Could not parse JSON object")
271344
}
272345

273346
#[test]
@@ -286,7 +359,7 @@ mod tests {
286359

287360
assert_eq!(
288361
json,
289-
Json::from_str(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
362+
serde_json::from_str::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
290363
.expect("Invalid JSON constant in test"));
291364
}
292365

@@ -307,7 +380,7 @@ mod tests {
307380

308381
assert_eq!(
309382
json,
310-
Json::from_str(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
383+
serde_json::from_str::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
311384
.expect("Invalid JSON constant in test"));
312385
}
313386

0 commit comments

Comments
 (0)