Require POST for GraphQL requests

This commit is contained in:
Koxiaet 2020-10-15 18:42:09 +01:00
parent 2756c2cd5b
commit 5c47f1ec57
5 changed files with 19 additions and 5 deletions

View File

@ -13,11 +13,12 @@ they must all internally use the below functions.
- Conversion from HTTP library's request to `async_graphql::BatchRequest`:
1. If the request is a `GET` request:
1. Return the request's query parameters deserialized as an `async_graphql::Request`.
1. Otherwise:
1. If the request is a `POST` request:
1. Get the request's `Content-Type` header.
1. Call `async_graphql::http::receive_batch_body` on the request's body.
1. Convert `ParseRequestError::PayloadTooLarge` to a 413 Payload Too Large response.
1. Convert all other errors to a 400 Bad Request response.
1. Otherwise return a 405 Method Not Allowed.
- Conversion from HTTP library's request to `async_graphql::Request`:
1. Call the above function to convert the request to an `async_graphql::BatchRequest`.
1. Call `BatchRequest::into_single` on the result.

View File

@ -75,7 +75,7 @@ impl FromRequest for BatchRequest {
if req.method() == Method::GET {
let res = serde_urlencoded::from_str(req.query_string());
Box::pin(async move { Ok(Self(async_graphql::BatchRequest::Single(res?))) })
} else {
} else if req.method() == Method::POST {
let content_type = req
.headers()
.get(http::header::CONTENT_TYPE)
@ -129,6 +129,12 @@ impl FromRequest for BatchRequest {
})?,
))
})
} else {
Box::pin(async move {
Err(actix_web::error::ErrorMethodNotAllowed(
"GraphQL only supports GET and POST requests",
))
})
}
}
}

View File

@ -128,7 +128,7 @@ pub async fn receive_batch_request_opts<State: Clone + Send + Sync + 'static>(
) -> tide::Result<async_graphql::BatchRequest> {
if request.method() == Method::Get {
request.query::<async_graphql::Request>().map(Into::into)
} else {
} else if request.method() == Method::Post {
let body = request.take_body();
let content_type = request
.header(headers::CONTENT_TYPE)
@ -146,6 +146,11 @@ pub async fn receive_batch_request_opts<State: Clone + Send + Sync + 'static>(
e,
)
})
} else {
Err(tide::Error::from_str(
StatusCode::MethodNotAllowed,
"GraphQL only supports GET and POST requests",
))
}
}

View File

@ -38,7 +38,7 @@ where
{
warp::any()
.and(warp::get().and(warp::query()).map(BatchRequest::Single))
.or(warp::any()
.or(warp::post()
.and(warp::header::optional::<String>("content-type"))
.and(warp::body::stream())
.and_then(move |content_type, body| async move {

View File

@ -43,7 +43,9 @@ pub async fn receive_batch_body(
if let Some(Ok(boundary)) = content_type.map(multer::parse_boundary) {
multipart::receive_batch_multipart(body, boundary, opts).await
} else if let Some(content_type) = content_type.filter(|&ct| ct != "application/json") {
Err(ParseRequestError::UnknownContentType(content_type.to_owned()))
Err(ParseRequestError::UnknownContentType(
content_type.to_owned(),
))
} else {
receive_batch_json(body).await
}