juniper_tower/
lib.rs

1#[macro_use]
2extern crate tower_web;
3
4use http::StatusCode;
5use tokio::prelude::*;
6
7use juniper::GraphQLType;
8use juniper::RootNode;
9
10#[derive(Debug, Extract, Deserialize)]
11pub struct GraphQLRequest {
12    #[serde(flatten)]
13    gq: juniper::http::GraphQLRequest,
14}
15
16#[derive(Debug, Response, Serialize)]
17pub struct GraphQLResponse {
18    #[serde(flatten)]
19    inner: serde_json::Value,
20
21    #[web(header)]
22    status: u16,
23}
24
25pub fn graphiql_source(
26    graphql_endpoint_url: &str,
27) -> impl Future<Item = String, Error = ()> + Send {
28    future::ok(juniper::graphiql::graphiql_source(graphql_endpoint_url))
29}
30
31impl GraphQLRequest {
32    pub fn execute<CtxT, QueryT, MutationT>(
33        &self,
34        root_node: &RootNode<QueryT, MutationT>,
35        context: &CtxT,
36    ) -> impl Future<Item = GraphQLResponse, Error = ()>
37    where
38        QueryT: GraphQLType<Context = CtxT>,
39        MutationT: GraphQLType<Context = CtxT>,
40    {
41        let response = self.gq.execute(root_node, context);
42        let status = if response.is_ok() {
43            StatusCode::OK
44        } else {
45            StatusCode::BAD_REQUEST
46        };
47        let json = serde_json::to_value(&response).unwrap();
48        future::ok(GraphQLResponse {
49            inner: json,
50            status: status.into(),
51        })
52    }
53}