Update juniper_hyper to central GraphQLBatch*
enums (#613)
This commit is contained in:
parent
c09be69b7d
commit
6b040c509b
1 changed files with 17 additions and 108 deletions
|
@ -8,8 +8,8 @@ use hyper::{
|
||||||
Body, Method, Request, Response, StatusCode,
|
Body, Method, Request, Response, StatusCode,
|
||||||
};
|
};
|
||||||
use juniper::{
|
use juniper::{
|
||||||
http::GraphQLRequest as JuniperGraphQLRequest, serde::Deserialize, DefaultScalarValue,
|
http::{GraphQLBatchRequest, GraphQLRequest as JuniperGraphQLRequest},
|
||||||
GraphQLType, GraphQLTypeAsync, InputValue, RootNode, ScalarValue,
|
GraphQLSubscriptionType, GraphQLType, GraphQLTypeAsync, InputValue, RootNode, ScalarValue,
|
||||||
};
|
};
|
||||||
use serde_json::error::Error as SerdeError;
|
use serde_json::error::Error as SerdeError;
|
||||||
use std::{error::Error, fmt, string::FromUtf8Error, sync::Arc};
|
use std::{error::Error, fmt, string::FromUtf8Error, sync::Arc};
|
||||||
|
@ -61,7 +61,7 @@ where
|
||||||
CtxT: Send + Sync + 'static,
|
CtxT: Send + Sync + 'static,
|
||||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||||
SubscriptionT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||||
QueryT::TypeInfo: Send + Sync,
|
QueryT::TypeInfo: Send + Sync,
|
||||||
MutationT::TypeInfo: Send + Sync,
|
MutationT::TypeInfo: Send + Sync,
|
||||||
SubscriptionT::TypeInfo: Send + Sync,
|
SubscriptionT::TypeInfo: Send + Sync,
|
||||||
|
@ -89,10 +89,10 @@ where
|
||||||
|
|
||||||
fn parse_get_req<S: ScalarValue>(
|
fn parse_get_req<S: ScalarValue>(
|
||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
) -> Result<GraphQLRequest<S>, GraphQLRequestError> {
|
) -> Result<GraphQLBatchRequest<S>, GraphQLRequestError> {
|
||||||
req.uri()
|
req.uri()
|
||||||
.query()
|
.query()
|
||||||
.map(|q| gql_request_from_get(q).map(GraphQLRequest::Single))
|
.map(|q| gql_request_from_get(q).map(GraphQLBatchRequest::Single))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
Err(GraphQLRequestError::Invalid(
|
Err(GraphQLRequestError::Invalid(
|
||||||
"'query' parameter is missing".to_string(),
|
"'query' parameter is missing".to_string(),
|
||||||
|
@ -102,7 +102,7 @@ fn parse_get_req<S: ScalarValue>(
|
||||||
|
|
||||||
async fn parse_post_req<S: ScalarValue>(
|
async fn parse_post_req<S: ScalarValue>(
|
||||||
body: Body,
|
body: Body,
|
||||||
) -> Result<GraphQLRequest<S>, GraphQLRequestError> {
|
) -> Result<GraphQLBatchRequest<S>, GraphQLRequestError> {
|
||||||
let chunk = hyper::body::to_bytes(body)
|
let chunk = hyper::body::to_bytes(body)
|
||||||
.await
|
.await
|
||||||
.map_err(GraphQLRequestError::BodyHyper)?;
|
.map_err(GraphQLRequestError::BodyHyper)?;
|
||||||
|
@ -110,7 +110,8 @@ async fn parse_post_req<S: ScalarValue>(
|
||||||
let input = String::from_utf8(chunk.iter().cloned().collect())
|
let input = String::from_utf8(chunk.iter().cloned().collect())
|
||||||
.map_err(GraphQLRequestError::BodyUtf8)?;
|
.map_err(GraphQLRequestError::BodyUtf8)?;
|
||||||
|
|
||||||
serde_json::from_str::<GraphQLRequest<S>>(&input).map_err(GraphQLRequestError::BodyJSONError)
|
serde_json::from_str::<GraphQLBatchRequest<S>>(&input)
|
||||||
|
.map_err(GraphQLRequestError::BodyJSONError)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn graphiql(graphql_endpoint: &str) -> Result<Response<Body>, hyper::Error> {
|
pub async fn graphiql(graphql_endpoint: &str) -> Result<Response<Body>, hyper::Error> {
|
||||||
|
@ -142,7 +143,7 @@ fn render_error(err: GraphQLRequestError) -> Response<Body> {
|
||||||
async fn execute_request<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
async fn execute_request<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
||||||
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
||||||
context: Arc<CtxT>,
|
context: Arc<CtxT>,
|
||||||
request: GraphQLRequest<S>,
|
request: GraphQLBatchRequest<S>,
|
||||||
) -> Response<Body>
|
) -> Response<Body>
|
||||||
where
|
where
|
||||||
S: ScalarValue + Send + Sync + 'static,
|
S: ScalarValue + Send + Sync + 'static,
|
||||||
|
@ -154,8 +155,9 @@ where
|
||||||
MutationT::TypeInfo: Send + Sync,
|
MutationT::TypeInfo: Send + Sync,
|
||||||
SubscriptionT::TypeInfo: Send + Sync,
|
SubscriptionT::TypeInfo: Send + Sync,
|
||||||
{
|
{
|
||||||
let (is_ok, body) = request.execute_sync(root_node, context);
|
let res = request.execute_sync(&*root_node, &context);
|
||||||
let code = if is_ok {
|
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
||||||
|
let code = if res.is_ok() {
|
||||||
StatusCode::OK
|
StatusCode::OK
|
||||||
} else {
|
} else {
|
||||||
StatusCode::BAD_REQUEST
|
StatusCode::BAD_REQUEST
|
||||||
|
@ -172,20 +174,21 @@ where
|
||||||
async fn execute_request_async<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
async fn execute_request_async<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
||||||
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
||||||
context: Arc<CtxT>,
|
context: Arc<CtxT>,
|
||||||
request: GraphQLRequest<S>,
|
request: GraphQLBatchRequest<S>,
|
||||||
) -> Response<Body>
|
) -> Response<Body>
|
||||||
where
|
where
|
||||||
S: ScalarValue + Send + Sync + 'static,
|
S: ScalarValue + Send + Sync + 'static,
|
||||||
CtxT: Send + Sync + 'static,
|
CtxT: Send + Sync + 'static,
|
||||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
||||||
SubscriptionT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync + 'static,
|
SubscriptionT: GraphQLSubscriptionType<S, Context = CtxT> + Send + Sync,
|
||||||
QueryT::TypeInfo: Send + Sync,
|
QueryT::TypeInfo: Send + Sync,
|
||||||
MutationT::TypeInfo: Send + Sync,
|
MutationT::TypeInfo: Send + Sync,
|
||||||
SubscriptionT::TypeInfo: Send + Sync,
|
SubscriptionT::TypeInfo: Send + Sync,
|
||||||
{
|
{
|
||||||
let (is_ok, body) = request.execute(root_node, context).await;
|
let res = request.execute(&*root_node, &context).await;
|
||||||
let code = if is_ok {
|
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
||||||
|
let code = if res.is_ok() {
|
||||||
StatusCode::OK
|
StatusCode::OK
|
||||||
} else {
|
} else {
|
||||||
StatusCode::BAD_REQUEST
|
StatusCode::BAD_REQUEST
|
||||||
|
@ -263,100 +266,6 @@ fn new_html_response(code: StatusCode) -> Response<Body> {
|
||||||
resp
|
resp
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde_derive::Deserialize)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
#[serde(bound = "InputValue<S>: Deserialize<'de>")]
|
|
||||||
enum GraphQLRequest<S = DefaultScalarValue>
|
|
||||||
where
|
|
||||||
S: ScalarValue,
|
|
||||||
{
|
|
||||||
Single(JuniperGraphQLRequest<S>),
|
|
||||||
Batch(Vec<JuniperGraphQLRequest<S>>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> GraphQLRequest<S>
|
|
||||||
where
|
|
||||||
S: ScalarValue,
|
|
||||||
{
|
|
||||||
fn execute_sync<'a, CtxT: 'a, QueryT, MutationT, SubscriptionT>(
|
|
||||||
self,
|
|
||||||
root_node: Arc<RootNode<'a, QueryT, MutationT, SubscriptionT, S>>,
|
|
||||||
context: Arc<CtxT>,
|
|
||||||
) -> (bool, hyper::Body)
|
|
||||||
where
|
|
||||||
S: 'a + Send + Sync,
|
|
||||||
QueryT: GraphQLType<S, Context = CtxT> + 'a,
|
|
||||||
MutationT: GraphQLType<S, Context = CtxT> + 'a,
|
|
||||||
SubscriptionT: GraphQLType<S, Context = CtxT> + 'a,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
GraphQLRequest::Single(request) => {
|
|
||||||
let res = request.execute_sync(&root_node, &context);
|
|
||||||
let is_ok = res.is_ok();
|
|
||||||
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
|
||||||
(is_ok, body)
|
|
||||||
}
|
|
||||||
GraphQLRequest::Batch(requests) => {
|
|
||||||
let results: Vec<_> = requests
|
|
||||||
.into_iter()
|
|
||||||
.map(move |request| {
|
|
||||||
let root_node = root_node.clone();
|
|
||||||
let res = request.execute_sync(&root_node, &context);
|
|
||||||
let is_ok = res.is_ok();
|
|
||||||
let body = serde_json::to_string_pretty(&res).unwrap();
|
|
||||||
(is_ok, body)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let is_ok = !results.iter().any(|&(is_ok, _)| !is_ok);
|
|
||||||
let bodies: Vec<_> = results.into_iter().map(|(_, body)| body).collect();
|
|
||||||
let body = hyper::Body::from(format!("[{}]", bodies.join(",")));
|
|
||||||
(is_ok, body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn execute<'a, CtxT: 'a, QueryT, MutationT, SubscriptionT>(
|
|
||||||
self,
|
|
||||||
root_node: Arc<RootNode<'a, QueryT, MutationT, SubscriptionT, S>>,
|
|
||||||
context: Arc<CtxT>,
|
|
||||||
) -> (bool, hyper::Body)
|
|
||||||
where
|
|
||||||
S: Send + Sync,
|
|
||||||
QueryT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
|
||||||
MutationT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
|
||||||
SubscriptionT: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
|
|
||||||
QueryT::TypeInfo: Send + Sync,
|
|
||||||
MutationT::TypeInfo: Send + Sync,
|
|
||||||
SubscriptionT::TypeInfo: Send + Sync,
|
|
||||||
CtxT: Send + Sync,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
GraphQLRequest::Single(request) => {
|
|
||||||
let res = request.execute(&*root_node, &context).await;
|
|
||||||
let is_ok = res.is_ok();
|
|
||||||
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
|
||||||
(is_ok, body)
|
|
||||||
}
|
|
||||||
GraphQLRequest::Batch(requests) => {
|
|
||||||
let futures = requests
|
|
||||||
.iter()
|
|
||||||
.map(|request| request.execute(&*root_node, &context))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let results = futures::future::join_all(futures).await;
|
|
||||||
|
|
||||||
let is_ok = results.iter().all(|res| res.is_ok());
|
|
||||||
let bodies: Vec<_> = results
|
|
||||||
.into_iter()
|
|
||||||
.map(|res| serde_json::to_string_pretty(&res).unwrap())
|
|
||||||
.collect();
|
|
||||||
let body = hyper::Body::from(format!("[{}]", bodies.join(",")));
|
|
||||||
(is_ok, body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum GraphQLRequestError {
|
enum GraphQLRequestError {
|
||||||
BodyHyper(hyper::Error),
|
BodyHyper(hyper::Error),
|
||||||
|
|
Loading…
Reference in a new issue