diff --git a/src/graphiql.rs b/src/graphiql.rs
new file mode 100644
index 00000000..75faf9ac
--- /dev/null
+++ b/src/graphiql.rs
@@ -0,0 +1,64 @@
+pub fn graphiql_source(graphql_endpoint_url: &str) -> String {
+ let stylesheet_source = r#"
+
+ "#;
+ let fetcher_source = r#"
+
+ "#;
+
+ format!(r#"
+
+
+
+ GraphQL
+ {stylesheet_source}
+
+
+
+
+
+
+
+
+
+
+ {fetcher_source}
+
+
+"#,
+ graphql_url = graphql_endpoint_url,
+ stylesheet_source = stylesheet_source,
+ fetcher_source = fetcher_source)
+
+}
\ No newline at end of file
diff --git a/src/http.rs b/src/http.rs
new file mode 100644
index 00000000..62c8b167
--- /dev/null
+++ b/src/http.rs
@@ -0,0 +1,92 @@
+use serde::ser;
+use serde::ser::SerializeMap;
+
+use ::{GraphQLError, Value, Variables, GraphQLType, RootNode};
+use ast::InputValue;
+use executor::ExecutionError;
+
+/// The expected structure of the decoded JSON Document for either Post or Get requests.
+#[derive(Deserialize)]
+pub struct GraphQLRequest {
+ query: String,
+ #[serde(rename = "operationName")]
+ operation_name: Option,
+ variables: Option
+}
+
+impl GraphQLRequest {
+ fn operation_name(&self) -> Option<&str> {
+ self.operation_name.as_ref().map(|oper_name| &**oper_name)
+ }
+
+ fn variables(&self) -> Variables {
+ self.variables.as_ref().and_then(|iv| {
+ iv.to_object_value().map(|o| {
+ o.into_iter().map(|(k, v)| (k.to_owned(), v.clone())).collect()
+ })
+ }).unwrap_or_default()
+ }
+
+ pub fn new(query: String, operation_name: Option, variables: Option) -> GraphQLRequest {
+ GraphQLRequest {
+ query: query,
+ operation_name: operation_name,
+ variables: variables,
+ }
+ }
+
+ pub fn execute<'a, CtxT, QueryT, MutationT>(
+ &'a self,
+ root_node: &RootNode,
+ context: &CtxT,
+ )
+ -> GraphQLResponse<'a>
+ where QueryT: GraphQLType,
+ MutationT: GraphQLType,
+ {
+ GraphQLResponse(::execute(
+ &self.query,
+ self.operation_name(),
+ root_node,
+ &self.variables(),
+ context,
+ ))
+ }
+}
+
+
+pub struct GraphQLResponse<'a>(Result<(Value, Vec), GraphQLError<'a>>);
+
+impl<'a> GraphQLResponse<'a> {
+ pub fn is_ok(&self) -> bool {
+ self.0.is_ok()
+ }
+}
+
+impl<'a> ser::Serialize for GraphQLResponse<'a> {
+ fn serialize(&self, serializer: S) -> Result
+ where S: ser::Serializer,
+ {
+ match self.0 {
+ Ok((ref res, ref err)) => {
+ let mut map = try!(serializer.serialize_map(None));
+
+ try!(map.serialize_key("data"));
+ try!(map.serialize_value(res));
+
+ if !err.is_empty() {
+ try!(map.serialize_key("errors"));
+ try!(map.serialize_value(err));
+ }
+
+ map.end()
+ },
+ Err(ref err) => {
+ let mut map = try!(serializer.serialize_map(Some(1)));
+ try!(map.serialize_key("errors"));
+ try!(map.serialize_value(err));
+ map.end()
+ },
+ }
+ }
+}
diff --git a/src/integrations/iron_handlers.rs b/src/integrations/iron_handlers.rs
index 494cfbd8..72ff6ed1 100644
--- a/src/integrations/iron_handlers.rs
+++ b/src/integrations/iron_handlers.rs
@@ -7,17 +7,14 @@ use iron::method;
use urlencoded::{UrlEncodedQuery, UrlDecodingError};
use std::io::Read;
-use std::io::Error as IoError;
-use std::io::ErrorKind;
use std::error::Error;
use std::fmt;
-use std::boxed::Box;
use serde_json;
use serde_json::error::Error as SerdeError;
-use ::{InputValue, GraphQLType, RootNode, execute};
-use super::serde::{WrappedGraphQLResult, GraphQLQuery};
+use ::{InputValue, GraphQLType, RootNode};
+use ::http;
/// Handler that executes GraphQL queries in the given schema
///
@@ -45,45 +42,29 @@ pub struct GraphiQLHandler {
}
-/// Get queries are allowed to repeat the same key more than once.
-fn check_for_repeat_keys(params: &Vec) -> Result<(), IronError> {
- if params.len() > 1 {
- let error = IronError::new(
- Box::new(GraphQlIronError::IO(IoError::new(ErrorKind::InvalidData,
- "Was able parse a query string \
- but a duplicate uri key was \
- found."))),
- (status::BadRequest, "Duplicate uri key was found."));
- Err(error)
+fn get_single_value(mut values: Vec) -> IronResult {
+ if values.len() == 1 {
+ Ok(values.remove(0))
}
else {
- Ok(())
+ Err(GraphQLIronError::InvalidData("Duplicate URL query parameter").into())
}
}
-fn parse_url_param(param: Option>) -> Result