diff --git a/examples b/examples index 58e92b7f..b3915aa7 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 58e92b7ffec6aee23b59584331dbe4e101aa049f +Subproject commit b3915aa777e434e9049c4d4a2448ebbd2524f6b1 diff --git a/integrations/poem/Cargo.toml b/integrations/poem/Cargo.toml index 143c10fc..9c5a6fbd 100644 --- a/integrations/poem/Cargo.toml +++ b/integrations/poem/Cargo.toml @@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"] [dependencies] async-graphql = { path = "../..", version = "=2.11.0" } -poem = { version = "1.0.13", features = ["websocket"] } +poem = { version = "1.0.19", features = ["websocket"] } futures-util = { version = "0.3.13", default-features = false } serde_json = "1.0.66" tokio-util = { version = "0.6.7", features = ["compat"] } diff --git a/integrations/poem/src/lib.rs b/integrations/poem/src/lib.rs index 0a140beb..7fcc5ebd 100644 --- a/integrations/poem/src/lib.rs +++ b/integrations/poem/src/lib.rs @@ -4,8 +4,10 @@ mod extractor; mod query; +mod response; mod subscription; pub use extractor::{GraphQLBatchRequest, GraphQLRequest}; pub use query::GraphQL; +pub use response::{GraphQLBatchResponse, GraphQLResponse}; pub use subscription::GraphQLSubscription; diff --git a/integrations/poem/src/query.rs b/integrations/poem/src/query.rs index 6dbc0478..73d20fbd 100644 --- a/integrations/poem/src/query.rs +++ b/integrations/poem/src/query.rs @@ -1,8 +1,7 @@ -use async_graphql::{BatchResponse as GraphQLBatchResponse, ObjectType, Schema, SubscriptionType}; -use poem::web::Json; +use async_graphql::{ObjectType, Schema, SubscriptionType}; use poem::{async_trait, Endpoint, FromRequest, Request, Result}; -use crate::GraphQLBatchRequest; +use crate::{GraphQLBatchRequest, GraphQLBatchResponse}; /// A GraphQL query endpoint. /// @@ -45,11 +44,11 @@ where Mutation: ObjectType + 'static, Subscription: SubscriptionType + 'static, { - type Output = Result>; + type Output = Result; async fn call(&self, req: Request) -> Self::Output { let (req, mut body) = req.split(); let req = GraphQLBatchRequest::from_request(&req, &mut body).await?; - Ok(Json(self.schema.execute_batch(req.0).await)) + Ok(GraphQLBatchResponse(self.schema.execute_batch(req.0).await)) } } diff --git a/integrations/poem/src/response.rs b/integrations/poem/src/response.rs new file mode 100644 index 00000000..7e0dfd68 --- /dev/null +++ b/integrations/poem/src/response.rs @@ -0,0 +1,50 @@ +use poem::http::header::HeaderName; +use poem::web::Json; +use poem::{IntoResponse, Response}; + +/// Response for `async_graphql::Request`. +pub struct GraphQLResponse(pub async_graphql::Response); + +impl From for GraphQLResponse { + fn from(resp: async_graphql::Response) -> Self { + Self(resp) + } +} + +impl IntoResponse for GraphQLResponse { + fn into_response(self) -> Response { + GraphQLBatchResponse(self.0.into()).into_response() + } +} + +/// Response for `async_graphql::BatchRequest`. +pub struct GraphQLBatchResponse(pub async_graphql::BatchResponse); + +impl From for GraphQLBatchResponse { + fn from(resp: async_graphql::BatchResponse) -> Self { + Self(resp) + } +} + +impl IntoResponse for GraphQLBatchResponse { + fn into_response(self) -> Response { + let mut resp = Json(&self.0).into_response(); + + if self.0.is_ok() { + if let Some(cache_control) = self.0.cache_control().value() { + if let Ok(value) = cache_control.try_into() { + resp.headers_mut().insert("cache-control", value); + } + } + } + + for (name, value) in self.0.http_headers() { + if let (Ok(name), Ok(value)) = (TryInto::::try_into(name), value.try_into()) + { + resp.headers_mut().append(name, value); + } + } + + resp + } +}