Replace http::GQLRequest with Request
This commit is contained in:
parent
a8e7608c9e
commit
8796c5e1a7
|
@ -41,10 +41,10 @@ impl FromRequest for GQLRequest {
|
||||||
let config = req.app_data::<Self::Config>().cloned().unwrap_or_default();
|
let config = req.app_data::<Self::Config>().cloned().unwrap_or_default();
|
||||||
|
|
||||||
if req.method() == Method::GET {
|
if req.method() == Method::GET {
|
||||||
let res = web::Query::<async_graphql::http::GQLRequest>::from_query(req.query_string());
|
let res = web::Query::<async_graphql::Request>::from_query(req.query_string());
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let gql_request = res?;
|
let gql_request = res?;
|
||||||
Ok(GQLRequest(gql_request.into_inner().into()))
|
Ok(GQLRequest(gql_request.into_inner()))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let content_type = req
|
let content_type = req
|
||||||
|
|
|
@ -199,7 +199,7 @@ impl<'q> FromQuery<'q> for GQLRequest {
|
||||||
let decoded = value.url_decode().map_err(|e| e.to_string())?;
|
let decoded = value.url_decode().map_err(|e| e.to_string())?;
|
||||||
let json_value = serde_json::from_str::<serde_json::Value>(&decoded)
|
let json_value = serde_json::from_str::<serde_json::Value>(&decoded)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
variables = Variables::parse_from_json(json_value).into();
|
variables = Variables::from_json(json_value).into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#![allow(clippy::needless_doctest_main)]
|
#![allow(clippy::needless_doctest_main)]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
use async_graphql::http::{GQLRequest, MultipartOptions};
|
use async_graphql::http::MultipartOptions;
|
||||||
use async_graphql::{resolver_utils::ObjectType, Schema, SubscriptionType};
|
use async_graphql::{resolver_utils::ObjectType, Schema, SubscriptionType};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -103,7 +103,7 @@ impl<State: Clone + Send + Sync + 'static> RequestExt<State> for Request<State>
|
||||||
opts: MultipartOptions,
|
opts: MultipartOptions,
|
||||||
) -> tide::Result<async_graphql::Request> {
|
) -> tide::Result<async_graphql::Request> {
|
||||||
if self.method() == Method::Get {
|
if self.method() == Method::Get {
|
||||||
Ok(self.query::<GQLRequest>()?.into())
|
Ok(self.query::<async_graphql::Request>()?)
|
||||||
} else {
|
} else {
|
||||||
let content_type = self
|
let content_type = self
|
||||||
.header(&headers::CONTENT_TYPE)
|
.header(&headers::CONTENT_TYPE)
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
#![allow(clippy::needless_doctest_main)]
|
#![allow(clippy::needless_doctest_main)]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
use async_graphql::http::{GQLRequest, MultipartOptions};
|
use async_graphql::http::MultipartOptions;
|
||||||
use async_graphql::{resolver_utils::ObjectType, Data, FieldResult, Schema, SubscriptionType};
|
use async_graphql::{
|
||||||
|
resolver_utils::ObjectType, Data, FieldResult, Request, Schema, SubscriptionType,
|
||||||
|
};
|
||||||
use futures::io::ErrorKind;
|
use futures::io::ErrorKind;
|
||||||
use futures::{select, TryStreamExt};
|
use futures::{select, TryStreamExt};
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
|
@ -112,9 +114,9 @@ where
|
||||||
opts: Arc<MultipartOptions>,
|
opts: Arc<MultipartOptions>,
|
||||||
schema| async move {
|
schema| async move {
|
||||||
if method == Method::GET {
|
if method == Method::GET {
|
||||||
let request: GQLRequest = serde_urlencoded::from_str(&query)
|
let request: Request = serde_urlencoded::from_str(&query)
|
||||||
.map_err(|err| warp::reject::custom(BadRequest(err.into())))?;
|
.map_err(|err| warp::reject::custom(BadRequest(err.into())))?;
|
||||||
Ok::<_, Rejection>((schema, async_graphql::Request::from(request)))
|
Ok::<_, Rejection>((schema, request))
|
||||||
} else {
|
} else {
|
||||||
let request = async_graphql::http::receive_body(
|
let request = async_graphql::http::receive_body(
|
||||||
content_type,
|
content_type,
|
||||||
|
|
|
@ -6,18 +6,19 @@ use crate::parser::types::{
|
||||||
use crate::schema::SchemaEnv;
|
use crate::schema::SchemaEnv;
|
||||||
use crate::{FieldResult, InputValueType, Lookahead, Pos, Positioned, QueryError, Result, Value};
|
use crate::{FieldResult, InputValueType, Lookahead, Pos, Positioned, QueryError, Result, Value};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use serde::ser::SerializeSeq;
|
use serde::ser::{SerializeSeq, Serializer};
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Variables of a query.
|
/// Variables of a query.
|
||||||
#[derive(Debug, Clone, Default, Serialize)]
|
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
pub struct Variables(pub BTreeMap<Name, Value>);
|
pub struct Variables(pub BTreeMap<Name, Value>);
|
||||||
|
|
||||||
impl Display for Variables {
|
impl Display for Variables {
|
||||||
|
@ -31,18 +32,34 @@ impl Display for Variables {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Variables {
|
impl Variables {
|
||||||
/// Parse variables from JSON object.
|
/// Get the variables from a GraphQL value.
|
||||||
///
|
///
|
||||||
/// If the value is not a map, or the keys of map are not valid GraphQL names, then an empty
|
/// If the value is not a map, then no variables will be returned.
|
||||||
/// `Variables` instance will be returned.
|
#[must_use]
|
||||||
pub fn parse_from_json(value: serde_json::Value) -> Self {
|
pub fn from_value(value: Value) -> Self {
|
||||||
if let Ok(Value::Object(obj)) = Value::from_json(value) {
|
match value {
|
||||||
Self(obj)
|
Value::Object(obj) => Self(obj),
|
||||||
} else {
|
_ => Self::default(),
|
||||||
Default::default()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the values from a JSON value.
|
||||||
|
///
|
||||||
|
/// If the value is not a map or the keys of a map are not valid GraphQL names, then no
|
||||||
|
/// variables will be returned.
|
||||||
|
#[must_use]
|
||||||
|
pub fn from_json(value: serde_json::Value) -> Self {
|
||||||
|
Value::from_json(value)
|
||||||
|
.map(Self::from_value)
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the variables as a GraphQL value.
|
||||||
|
#[must_use]
|
||||||
|
pub fn into_value(self) -> Value {
|
||||||
|
Value::Object(self.0)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn variable_path(&mut self, path: &str) -> Option<&mut Value> {
|
pub(crate) fn variable_path(&mut self, path: &str) -> Option<&mut Value> {
|
||||||
let mut parts = path.strip_prefix("variables.")?.split('.');
|
let mut parts = path.strip_prefix("variables.")?.split('.');
|
||||||
|
|
||||||
|
@ -60,17 +77,31 @@ impl Variables {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Variables> for Value {
|
||||||
|
fn from(variables: Variables) -> Self {
|
||||||
|
variables.into_value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Schema/Context data.
|
/// Schema/Context data.
|
||||||
|
///
|
||||||
|
/// This is a type map, allowing you to store anything inside it.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Data(FnvHashMap<TypeId, Box<dyn Any + Sync + Send>>);
|
pub struct Data(FnvHashMap<TypeId, Box<dyn Any + Sync + Send>>);
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
#[allow(missing_docs)]
|
/// Insert data.
|
||||||
pub fn insert<D: Any + Send + Sync>(&mut self, data: D) {
|
pub fn insert<D: Any + Send + Sync>(&mut self, data: D) {
|
||||||
self.0.insert(TypeId::of::<D>(), Box::new(data));
|
self.0.insert(TypeId::of::<D>(), Box::new(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for Data {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
f.debug_tuple("Data").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Context for `SelectionSet`
|
/// Context for `SelectionSet`
|
||||||
pub type ContextSelectionSet<'a> = ContextBase<'a, &'a Positioned<SelectionSet>>;
|
pub type ContextSelectionSet<'a> = ContextBase<'a, &'a Positioned<SelectionSet>>;
|
||||||
|
|
||||||
|
|
|
@ -8,38 +8,9 @@ pub use graphiql_source::graphiql_source;
|
||||||
pub use multipart::{receive_multipart, MultipartOptions};
|
pub use multipart::{receive_multipart, MultipartOptions};
|
||||||
pub use playground_source::{playground_source, GraphQLPlaygroundConfig};
|
pub use playground_source::{playground_source, GraphQLPlaygroundConfig};
|
||||||
|
|
||||||
use crate::{Data, ParseRequestError, Request, Variables};
|
use crate::{ParseRequestError, Request};
|
||||||
use futures::io::AsyncRead;
|
use futures::io::AsyncRead;
|
||||||
use futures::AsyncReadExt;
|
use futures::AsyncReadExt;
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
/// Deserializable GraphQL Request object
|
|
||||||
#[derive(Deserialize, Clone, PartialEq, Debug)]
|
|
||||||
pub struct GQLRequest {
|
|
||||||
/// Query source
|
|
||||||
pub query: String,
|
|
||||||
|
|
||||||
/// Operation name for this query
|
|
||||||
#[serde(rename = "operationName")]
|
|
||||||
pub operation_name: Option<String>,
|
|
||||||
|
|
||||||
/// Variables for this query
|
|
||||||
pub variables: Option<serde_json::Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<GQLRequest> for Request {
|
|
||||||
fn from(request: GQLRequest) -> Self {
|
|
||||||
Self {
|
|
||||||
query: request.query,
|
|
||||||
operation_name: request.operation_name,
|
|
||||||
variables: request
|
|
||||||
.variables
|
|
||||||
.map(Variables::parse_from_json)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
ctx_data: Data::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Receive a GraphQL request from a content type and body.
|
/// Receive a GraphQL request from a content type and body.
|
||||||
pub async fn receive_body(
|
pub async fn receive_body(
|
||||||
|
@ -54,60 +25,6 @@ pub async fn receive_body(
|
||||||
body.read_to_end(&mut data)
|
body.read_to_end(&mut data)
|
||||||
.await
|
.await
|
||||||
.map_err(ParseRequestError::Io)?;
|
.map_err(ParseRequestError::Io)?;
|
||||||
Ok(serde_json::from_slice::<GQLRequest>(&data)
|
Ok(serde_json::from_slice::<Request>(&data).map_err(ParseRequestError::InvalidRequest)?)
|
||||||
.map_err(ParseRequestError::InvalidRequest)?
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_request() {
|
|
||||||
let request: GQLRequest = serde_json::from_value(json! ({
|
|
||||||
"query": "{ a b c }"
|
|
||||||
}))
|
|
||||||
.unwrap();
|
|
||||||
assert!(request.variables.is_none());
|
|
||||||
assert!(request.operation_name.is_none());
|
|
||||||
assert_eq!(request.query, "{ a b c }");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_request_with_operation_name() {
|
|
||||||
let request: GQLRequest = serde_json::from_value(json! ({
|
|
||||||
"query": "{ a b c }",
|
|
||||||
"operationName": "a"
|
|
||||||
}))
|
|
||||||
.unwrap();
|
|
||||||
assert!(request.variables.is_none());
|
|
||||||
assert_eq!(request.operation_name.as_deref(), Some("a"));
|
|
||||||
assert_eq!(request.query, "{ a b c }");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_request_with_variables() {
|
|
||||||
let request: GQLRequest = serde_json::from_value(json! ({
|
|
||||||
"query": "{ a b c }",
|
|
||||||
"variables": {
|
|
||||||
"v1": 100,
|
|
||||||
"v2": [1, 2, 3],
|
|
||||||
"v3": "str",
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
request.variables,
|
|
||||||
Some(json!({
|
|
||||||
"v1": 100,
|
|
||||||
"v2": [1, 2, 3],
|
|
||||||
"v3": "str",
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
assert!(request.operation_name.is_none());
|
|
||||||
assert_eq!(request.query, "{ a b c }");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::http::GQLRequest;
|
|
||||||
use crate::{ParseRequestError, Request};
|
use crate::{ParseRequestError, Request};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::io::AsyncRead;
|
use futures::io::AsyncRead;
|
||||||
|
@ -66,9 +65,8 @@ pub async fn receive_multipart(
|
||||||
Some("operations") => {
|
Some("operations") => {
|
||||||
let request_str = field.text().await?;
|
let request_str = field.text().await?;
|
||||||
request = Some(
|
request = Some(
|
||||||
serde_json::from_str::<GQLRequest>(&request_str)
|
serde_json::from_str::<Request>(&request_str)
|
||||||
.map_err(ParseRequestError::InvalidRequest)?
|
.map_err(ParseRequestError::InvalidRequest)?,
|
||||||
.into(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some("map") => {
|
Some("map") => {
|
||||||
|
|
|
@ -1,14 +1,29 @@
|
||||||
use crate::parser::types::UploadValue;
|
use crate::parser::types::UploadValue;
|
||||||
use crate::{Data, Value, Variables};
|
use crate::{Data, Value, Variables};
|
||||||
|
use serde::Deserialize;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
/// GraphQL query request
|
/// GraphQL request.
|
||||||
|
///
|
||||||
|
/// This can be deserialized from a structure of the query string, the operation name and the
|
||||||
|
/// variables. The names are all in `camelCase` (e.g. `operationName`).
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
pub(crate) query: String,
|
/// The query source of the request.
|
||||||
pub(crate) operation_name: Option<String>,
|
pub query: String,
|
||||||
pub(crate) variables: Variables,
|
/// The operation name of the request.
|
||||||
pub(crate) ctx_data: Data,
|
#[serde(default, rename = "operationName")]
|
||||||
|
pub operation_name: Option<String>,
|
||||||
|
/// The variables of the request.
|
||||||
|
#[serde(default)]
|
||||||
|
pub variables: Variables,
|
||||||
|
/// The data of the request that can be accessed through `Context::data`.
|
||||||
|
///
|
||||||
|
/// **This data is only valid for this request**
|
||||||
|
#[serde(skip)]
|
||||||
|
pub data: Data,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
|
@ -18,11 +33,11 @@ impl Request {
|
||||||
query: query.into(),
|
query: query.into(),
|
||||||
operation_name: None,
|
operation_name: None,
|
||||||
variables: Variables::default(),
|
variables: Variables::default(),
|
||||||
ctx_data: Data::default(),
|
data: Data::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify the operation name.
|
/// Specify the operation name of the request.
|
||||||
pub fn operation_name<T: Into<String>>(self, name: T) -> Self {
|
pub fn operation_name<T: Into<String>>(self, name: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
operation_name: Some(name.into()),
|
operation_name: Some(name.into()),
|
||||||
|
@ -35,15 +50,18 @@ impl Request {
|
||||||
Self { variables, ..self }
|
Self { variables, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a context data that can be accessed in the `Context`, you access it with `Context::data`.
|
/// Insert some data for this request.
|
||||||
///
|
|
||||||
/// **This data is only valid for this query**
|
|
||||||
pub fn data<D: Any + Send + Sync>(mut self, data: D) -> Self {
|
pub fn data<D: Any + Send + Sync>(mut self, data: D) -> Self {
|
||||||
self.ctx_data.insert(data);
|
self.data.insert(data);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set uploaded file path
|
/// Set a variable to an upload value.
|
||||||
|
///
|
||||||
|
/// `var_path` is a dot-separated path to the item that begins with `variables`, for example
|
||||||
|
/// `variables.files.2.content` is equivalent to the Rust code
|
||||||
|
/// `request.variables["files"][2]["content"]`. If no variable exists at the path this function
|
||||||
|
/// won't do anything.
|
||||||
pub fn set_upload(
|
pub fn set_upload(
|
||||||
&mut self,
|
&mut self,
|
||||||
var_path: &str,
|
var_path: &str,
|
||||||
|
@ -68,3 +86,55 @@ impl<T: Into<String>> From<T> for Request {
|
||||||
Self::new(query)
|
Self::new(query)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_request() {
|
||||||
|
let request: Request = serde_json::from_value(json! ({
|
||||||
|
"query": "{ a b c }"
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
assert!(request.variables.0.is_empty());
|
||||||
|
assert!(request.operation_name.is_none());
|
||||||
|
assert_eq!(request.query, "{ a b c }");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_request_with_operation_name() {
|
||||||
|
let request: Request = serde_json::from_value(json! ({
|
||||||
|
"query": "{ a b c }",
|
||||||
|
"operationName": "a"
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
assert!(request.variables.0.is_empty());
|
||||||
|
assert_eq!(request.operation_name.as_deref(), Some("a"));
|
||||||
|
assert_eq!(request.query, "{ a b c }");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_request_with_variables() {
|
||||||
|
let request: Request = serde_json::from_value(json! ({
|
||||||
|
"query": "{ a b c }",
|
||||||
|
"variables": {
|
||||||
|
"v1": 100,
|
||||||
|
"v2": [1, 2, 3],
|
||||||
|
"v3": "str",
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
request.variables.into_value().into_json().unwrap(),
|
||||||
|
json!({
|
||||||
|
"v1": 100,
|
||||||
|
"v2": [1, 2, 3],
|
||||||
|
"v3": "str",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert!(request.operation_name.is_none());
|
||||||
|
assert_eq!(request.query, "{ a b c }");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -251,7 +251,7 @@ impl<'a> Fields<'a> {
|
||||||
|
|
||||||
let introspection_type_name = root.introspection_type_name();
|
let introspection_type_name = root.introspection_type_name();
|
||||||
|
|
||||||
if type_condition.map_or(false, |condition| {
|
let applies_concrete_object = type_condition.map_or(false, |condition| {
|
||||||
introspection_type_name == condition
|
introspection_type_name == condition
|
||||||
|| ctx
|
|| ctx
|
||||||
.schema_env
|
.schema_env
|
||||||
|
@ -259,7 +259,8 @@ impl<'a> Fields<'a> {
|
||||||
.implements
|
.implements
|
||||||
.get(&*introspection_type_name)
|
.get(&*introspection_type_name)
|
||||||
.map_or(false, |interfaces| interfaces.contains(condition))
|
.map_or(false, |interfaces| interfaces.contains(condition))
|
||||||
}) {
|
});
|
||||||
|
if applies_concrete_object {
|
||||||
// The fragment applies to the concrete object type.
|
// The fragment applies to the concrete object type.
|
||||||
|
|
||||||
// TODO: This solution isn't ideal. If there are two interfaces InterfaceA
|
// TODO: This solution isn't ideal. If there are two interfaces InterfaceA
|
||||||
|
|
|
@ -442,7 +442,7 @@ where
|
||||||
let (document, cache_control, extensions) =
|
let (document, cache_control, extensions) =
|
||||||
try_query_result!(self.prepare_request(&request));
|
try_query_result!(self.prepare_request(&request));
|
||||||
let mut resp = self
|
let mut resp = self
|
||||||
.execute_once(document, extensions, request.variables, request.ctx_data)
|
.execute_once(document, extensions, request.variables, request.data)
|
||||||
.await;
|
.await;
|
||||||
resp.cache_control = cache_control;
|
resp.cache_control = cache_control;
|
||||||
resp
|
resp
|
||||||
|
@ -466,7 +466,7 @@ where
|
||||||
|
|
||||||
if document.operation.node.ty != OperationType::Subscription {
|
if document.operation.node.ty != OperationType::Subscription {
|
||||||
let mut resp = schema
|
let mut resp = schema
|
||||||
.execute_once(document, extensions, request.variables, request.ctx_data)
|
.execute_once(document, extensions, request.variables, request.data)
|
||||||
.await;
|
.await;
|
||||||
resp.cache_control = cache_control;
|
resp.cache_control = cache_control;
|
||||||
yield resp;
|
yield resp;
|
||||||
|
@ -509,7 +509,7 @@ where
|
||||||
/// Execute an GraphQL subscription.
|
/// Execute an GraphQL subscription.
|
||||||
pub fn execute_stream(&self, request: impl Into<Request>) -> impl Stream<Item = Response> {
|
pub fn execute_stream(&self, request: impl Into<Request>) -> impl Stream<Item = Response> {
|
||||||
let mut request = request.into();
|
let mut request = request.into();
|
||||||
let ctx_data = std::mem::take(&mut request.ctx_data);
|
let ctx_data = std::mem::take(&mut request.data);
|
||||||
self.execute_stream_with_ctx_data(request, Arc::new(ctx_data))
|
self.execute_stream_with_ctx_data(request, Arc::new(ctx_data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! WebSocket transport for subscription
|
//! WebSocket transport for subscription
|
||||||
|
|
||||||
use crate::resolver_utils::ObjectType;
|
use crate::resolver_utils::ObjectType;
|
||||||
use crate::{http, Data, FieldResult, Request, Response, Schema, SubscriptionType};
|
use crate::{Data, FieldResult, Request, Response, Schema, SubscriptionType};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use futures::task::{Context, Poll};
|
use futures::task::{Context, Poll};
|
||||||
use futures::{Future, Stream, StreamExt};
|
use futures::{Future, Stream, StreamExt};
|
||||||
|
@ -229,8 +229,7 @@ where
|
||||||
}
|
}
|
||||||
"start" => {
|
"start" => {
|
||||||
if let (Some(id), Some(payload)) = (msg.id, msg.payload) {
|
if let (Some(id), Some(payload)) = (msg.id, msg.payload) {
|
||||||
if let Ok(request) = serde_json::from_value::<http::GQLRequest>(payload) {
|
if let Ok(request) = serde_json::from_value::<Request>(payload) {
|
||||||
let request = Request::from(request);
|
|
||||||
let stream = schema
|
let stream = schema
|
||||||
.execute_stream_with_ctx_data(request, ctx.ctx_data.clone())
|
.execute_stream_with_ctx_data(request, ctx.ctx_data.clone())
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub async fn test_variables() {
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.variables(Variables::parse_from_json(serde_json::json!({
|
.variables(Variables::from_json(serde_json::json!({
|
||||||
"intVal": 10,
|
"intVal": 10,
|
||||||
"intListVal": [1, 2, 3, 4, 5],
|
"intListVal": [1, 2, 3, 4, 5],
|
||||||
})));
|
})));
|
||||||
|
@ -117,7 +117,7 @@ pub async fn test_variable_null() {
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.variables(Variables::parse_from_json(serde_json::json!({
|
.variables(Variables::from_json(serde_json::json!({
|
||||||
"intVal": null,
|
"intVal": null,
|
||||||
})));
|
})));
|
||||||
let resp = schema.execute(query).await;
|
let resp = schema.execute(query).await;
|
||||||
|
@ -168,7 +168,7 @@ pub async fn test_variable_in_input_object() {
|
||||||
}"#;
|
}"#;
|
||||||
let resp = schema
|
let resp = schema
|
||||||
.execute(
|
.execute(
|
||||||
Request::new(query).variables(Variables::parse_from_json(serde_json::json!({
|
Request::new(query).variables(Variables::from_json(serde_json::json!({
|
||||||
"value": 10,
|
"value": 10,
|
||||||
}))),
|
}))),
|
||||||
)
|
)
|
||||||
|
@ -189,7 +189,7 @@ pub async fn test_variable_in_input_object() {
|
||||||
}"#;
|
}"#;
|
||||||
let resp = schema
|
let resp = schema
|
||||||
.execute(
|
.execute(
|
||||||
Request::new(query).variables(Variables::parse_from_json(serde_json::json!({
|
Request::new(query).variables(Variables::from_json(serde_json::json!({
|
||||||
"value": 3,
|
"value": 3,
|
||||||
}))),
|
}))),
|
||||||
)
|
)
|
||||||
|
@ -210,7 +210,7 @@ pub async fn test_variable_in_input_object() {
|
||||||
}"#;
|
}"#;
|
||||||
let resp = schema
|
let resp = schema
|
||||||
.execute(
|
.execute(
|
||||||
Request::new(query).variables(Variables::parse_from_json(serde_json::json!({
|
Request::new(query).variables(Variables::from_json(serde_json::json!({
|
||||||
"value": 10,
|
"value": 10,
|
||||||
}))),
|
}))),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user