-
-
Notifications
You must be signed in to change notification settings - Fork 431
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add support
multipart/mixed
request. #1348
- Loading branch information
Showing
15 changed files
with
314 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule examples
updated
8 files
+9 −15 | actix-web/error-extensions/src/main.rs | |
+12 −13 | actix-web/starwars/src/main.rs | |
+11 −12 | actix-web/subscription/src/main.rs | |
+3 −13 | axum/starwars/src/main.rs | |
+7 −10 | axum/subscription/src/main.rs | |
+4 −4 | axum/token-from-header/src/main.rs | |
+3 −9 | axum/upload/src/main.rs | |
+1 −1 | tide/subscription/src/main.rs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
use std::time::Duration; | ||
|
||
use actix_http::StatusCode; | ||
use actix_web::{Handler, HttpRequest, HttpResponse, Responder}; | ||
use async_graphql::{ | ||
http::{create_multipart_mixed_stream, is_multipart_mixed}, | ||
Executor, | ||
}; | ||
use futures_util::{future::LocalBoxFuture, FutureExt, StreamExt}; | ||
|
||
use crate::{GraphQLRequest, GraphQLResponse}; | ||
|
||
/// A GraphQL handler. | ||
#[derive(Clone)] | ||
pub struct GraphQL<E> { | ||
executor: E, | ||
} | ||
|
||
impl<E> GraphQL<E> { | ||
/// Create a GraphQL handler. | ||
pub fn new(executor: E) -> Self { | ||
Self { executor } | ||
} | ||
} | ||
|
||
impl<E: Executor> Handler<(HttpRequest, GraphQLRequest)> for GraphQL<E> { | ||
type Output = HttpResponse; | ||
type Future = LocalBoxFuture<'static, Self::Output>; | ||
|
||
fn call(&self, (http_req, graphql_req): (HttpRequest, GraphQLRequest)) -> Self::Future { | ||
let executor = self.executor.clone(); | ||
async move { | ||
let is_multipart_mixed = http_req | ||
.headers() | ||
.get("accept") | ||
.and_then(|value| value.to_str().ok()) | ||
.map(is_multipart_mixed) | ||
.unwrap_or_default(); | ||
|
||
if is_multipart_mixed { | ||
let stream = executor.execute_stream(graphql_req.0, None); | ||
let interval = Box::pin(async_stream::stream! { | ||
let mut interval = actix_web::rt::time::interval(Duration::from_secs(30)); | ||
loop { | ||
interval.tick().await; | ||
yield (); | ||
} | ||
}); | ||
HttpResponse::build(StatusCode::OK) | ||
.insert_header(("content-type", "multipart/mixed; boundary=graphql")) | ||
.streaming( | ||
create_multipart_mixed_stream(stream, interval) | ||
.map(Ok::<_, actix_web::Error>), | ||
) | ||
} else { | ||
GraphQLResponse(executor.execute(graphql_req.into_inner()).await.into()) | ||
.respond_to(&http_req) | ||
} | ||
} | ||
.boxed_local() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use std::{ | ||
convert::Infallible, | ||
task::{Context, Poll}, | ||
time::Duration, | ||
}; | ||
|
||
use async_graphql::{ | ||
http::{create_multipart_mixed_stream, is_multipart_mixed}, | ||
Executor, | ||
}; | ||
use axum::{ | ||
body::{BoxBody, HttpBody, StreamBody}, | ||
extract::FromRequest, | ||
http::{Request as HttpRequest, Response as HttpResponse}, | ||
response::IntoResponse, | ||
BoxError, | ||
}; | ||
use bytes::Bytes; | ||
use futures_util::{future::BoxFuture, StreamExt}; | ||
use tower_service::Service; | ||
|
||
use crate::{ | ||
extract::rejection::GraphQLRejection, GraphQLBatchRequest, GraphQLRequest, GraphQLResponse, | ||
}; | ||
|
||
/// A GraphQL service. | ||
#[derive(Clone)] | ||
pub struct GraphQL<E> { | ||
executor: E, | ||
} | ||
|
||
impl<E> GraphQL<E> { | ||
/// Create a GraphQL handler. | ||
pub fn new(executor: E) -> Self { | ||
Self { executor } | ||
} | ||
} | ||
|
||
impl<B, E> Service<HttpRequest<B>> for GraphQL<E> | ||
where | ||
B: HttpBody + Send + Sync + 'static, | ||
B::Data: Into<Bytes>, | ||
B::Error: Into<BoxError>, | ||
E: Executor, | ||
{ | ||
type Response = HttpResponse<BoxBody>; | ||
type Error = Infallible; | ||
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>; | ||
|
||
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { | ||
Poll::Ready(Ok(())) | ||
} | ||
|
||
fn call(&mut self, req: HttpRequest<B>) -> Self::Future { | ||
let executor = self.executor.clone(); | ||
Box::pin(async move { | ||
let is_multipart_mixed = req | ||
.headers() | ||
.get("accept") | ||
.and_then(|value| value.to_str().ok()) | ||
.map(is_multipart_mixed) | ||
.unwrap_or_default(); | ||
|
||
if is_multipart_mixed { | ||
let req = match GraphQLRequest::<GraphQLRejection>::from_request(req, &()).await { | ||
Ok(req) => req, | ||
Err(err) => return Ok(err.into_response()), | ||
}; | ||
let stream = executor.execute_stream(req.0, None); | ||
let body = StreamBody::new( | ||
create_multipart_mixed_stream( | ||
stream, | ||
tokio_stream::wrappers::IntervalStream::new(tokio::time::interval( | ||
Duration::from_secs(30), | ||
)) | ||
.map(|_| ()), | ||
) | ||
.map(Ok::<_, std::io::Error>), | ||
); | ||
Ok(HttpResponse::builder() | ||
.header("content-type", "multipart/mixed; boundary=graphql") | ||
.body(body.boxed_unsync()) | ||
.expect("BUG: invalid response")) | ||
} else { | ||
let req = | ||
match GraphQLBatchRequest::<GraphQLRejection>::from_request(req, &()).await { | ||
Ok(req) => req, | ||
Err(err) => return Ok(err.into_response()), | ||
}; | ||
Ok(GraphQLResponse(executor.execute_batch(req.0).await).into_response()) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.