Skip to content

Commit a7a6778

Browse files
committed
Extract general HTTP/JSON functions from Iron integration
1 parent cac5dd1 commit a7a6778

File tree

5 files changed

+237
-271
lines changed

5 files changed

+237
-271
lines changed

src/graphiql.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
pub fn graphiql_source(graphql_endpoint_url: &str) -> String {
2+
let stylesheet_source = r#"
3+
<style>
4+
html, body, #app {
5+
height: 100%;
6+
margin: 0;
7+
overflow: hidden;
8+
width: 100%;
9+
}
10+
</style>
11+
"#;
12+
let fetcher_source = r#"
13+
<script>
14+
function graphQLFetcher(params) {
15+
return fetch(GRAPHQL_URL, {
16+
method: 'post',
17+
headers: {
18+
'Accept': 'application/json',
19+
'Content-Type': 'application/json',
20+
},
21+
body: JSON.stringify(params)
22+
}).then(function (response) {
23+
return response.text();
24+
}).then(function (body) {
25+
try {
26+
return JSON.parse(body);
27+
} catch (error) {
28+
return body;
29+
}
30+
});
31+
}
32+
ReactDOM.render(
33+
React.createElement(GraphiQL, {
34+
fetcher: graphQLFetcher,
35+
}),
36+
document.querySelector('#app'));
37+
</script>
38+
"#;
39+
40+
format!(r#"
41+
<!DOCTYPE html>
42+
<html>
43+
<head>
44+
<title>GraphQL</title>
45+
{stylesheet_source}
46+
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/graphiql/0.8.1/graphiql.css">
47+
</head>
48+
<body>
49+
<div id="app"></div>
50+
51+
<script src="//cdnjs.cloudflare.com/ajax/libs/fetch/2.0.1/fetch.js"></script>
52+
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
53+
<script src="//cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
54+
<script src="//cdnjs.cloudflare.com/ajax/libs/graphiql/0.8.1/graphiql.js"></script>
55+
<script>var GRAPHQL_URL = '{graphql_url}';</script>
56+
{fetcher_source}
57+
</body>
58+
</html>
59+
"#,
60+
graphql_url = graphql_endpoint_url,
61+
stylesheet_source = stylesheet_source,
62+
fetcher_source = fetcher_source)
63+
64+
}

src/http.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use serde::ser;
2+
use serde::ser::SerializeMap;
3+
4+
use ::{GraphQLError, Value, Variables, GraphQLType, RootNode};
5+
use ast::InputValue;
6+
use executor::ExecutionError;
7+
8+
/// The expected structure of the decoded JSON Document for either Post or Get requests.
9+
#[derive(Deserialize)]
10+
pub struct GraphQLRequest {
11+
query: String,
12+
#[serde(rename = "operationName")]
13+
operation_name: Option<String>,
14+
variables: Option<InputValue>
15+
}
16+
17+
impl GraphQLRequest {
18+
fn operation_name(&self) -> Option<&str> {
19+
self.operation_name.as_ref().map(|oper_name| &**oper_name)
20+
}
21+
22+
fn variables(&self) -> Variables {
23+
self.variables.as_ref().and_then(|iv| {
24+
iv.to_object_value().map(|o| {
25+
o.into_iter().map(|(k, v)| (k.to_owned(), v.clone())).collect()
26+
})
27+
}).unwrap_or_default()
28+
}
29+
30+
pub fn new(query: String, operation_name: Option<String>, variables: Option<InputValue>) -> GraphQLRequest {
31+
GraphQLRequest {
32+
query: query,
33+
operation_name: operation_name,
34+
variables: variables,
35+
}
36+
}
37+
38+
pub fn execute<'a, CtxT, QueryT, MutationT>(
39+
&'a self,
40+
root_node: &RootNode<QueryT, MutationT>,
41+
context: &CtxT,
42+
)
43+
-> GraphQLResponse<'a>
44+
where QueryT: GraphQLType<Context=CtxT>,
45+
MutationT: GraphQLType<Context=CtxT>,
46+
{
47+
GraphQLResponse(::execute(
48+
&self.query,
49+
self.operation_name(),
50+
root_node,
51+
&self.variables(),
52+
context,
53+
))
54+
}
55+
}
56+
57+
58+
pub struct GraphQLResponse<'a>(Result<(Value, Vec<ExecutionError>), GraphQLError<'a>>);
59+
60+
impl<'a> GraphQLResponse<'a> {
61+
pub fn is_ok(&self) -> bool {
62+
self.0.is_ok()
63+
}
64+
}
65+
66+
impl<'a> ser::Serialize for GraphQLResponse<'a> {
67+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68+
where S: ser::Serializer,
69+
{
70+
match self.0 {
71+
Ok((ref res, ref err)) => {
72+
let mut map = try!(serializer.serialize_map(None));
73+
74+
try!(map.serialize_key("data"));
75+
try!(map.serialize_value(res));
76+
77+
if !err.is_empty() {
78+
try!(map.serialize_key("errors"));
79+
try!(map.serialize_value(err));
80+
}
81+
82+
map.end()
83+
},
84+
Err(ref err) => {
85+
let mut map = try!(serializer.serialize_map(Some(1)));
86+
try!(map.serialize_key("errors"));
87+
try!(map.serialize_value(err));
88+
map.end()
89+
},
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)