Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions juniper_axum/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ All user visible changes to `juniper_axum` crate will be documented in this file

- Building on `wasm32-unknown-unknown` and `wasm32-wasi` targets. ([#1283], [#1282])

### Fixed

- `Content-Type` header reading full value instead of just the media type. ([#1288])

[#1272]: /../../pull/1272
[#1282]: /../../issues/1282
[#1283]: /../../pull/1283
Expand Down
56 changes: 45 additions & 11 deletions juniper_axum/src/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use axum::{
async_trait,
body::Body,
extract::{FromRequest, FromRequestParts, Query},
http::{HeaderValue, Method, Request, StatusCode},
http::{header, HeaderValue, Method, Request, StatusCode},
response::{IntoResponse as _, Response},
Json, RequestExt as _,
};
Expand Down Expand Up @@ -85,7 +85,7 @@ where
async fn from_request(mut req: Request<Body>, state: &State) -> Result<Self, Self::Rejection> {
let content_type = req
.headers()
.get("content-type")
.get(header::CONTENT_TYPE)
.map(HeaderValue::to_str)
.transpose()
.map_err(|_| {
Expand Down Expand Up @@ -122,22 +122,24 @@ where
.into_response()
})
}),
(&Method::POST, Some("application/json")) => {
(&Method::POST, Some(x)) if x.starts_with("application/json") => {
Json::<GraphQLBatchRequest<S>>::from_request(req, state)
.await
.map(|req| Self(req.0))
.map_err(|e| {
(StatusCode::BAD_REQUEST, format!("Invalid JSON body: {e}")).into_response()
})
}
(&Method::POST, Some("application/graphql")) => String::from_request(req, state)
.await
.map(|body| {
Self(GraphQLBatchRequest::Single(GraphQLRequest::new(
body, None, None,
)))
})
.map_err(|_| (StatusCode::BAD_REQUEST, "Not valid UTF-8 body").into_response()),
(&Method::POST, Some(x)) if x.starts_with("application/graphql") => {
String::from_request(req, state)
.await
.map(|body| {
Self(GraphQLBatchRequest::Single(GraphQLRequest::new(
body, None, None,
)))
})
.map_err(|_| (StatusCode::BAD_REQUEST, "Not valid UTF-8 body").into_response())
}
(&Method::POST, _) => Err((
StatusCode::UNSUPPORTED_MEDIA_TYPE,
"`Content-Type` header is expected to be either `application/json` or \
Expand Down Expand Up @@ -246,6 +248,22 @@ mod juniper_request_tests {
assert_eq!(do_from_request(req).await, expected);
}

#[tokio::test]
async fn from_json_post_request_with_charset() {
let req = Request::post("/")
.header("content-type", "application/json; charset=utf-8")
.body(Body::from(r#"{"query": "{ add(a: 2, b: 3) }"}"#))
.unwrap_or_else(|e| panic!("cannot build `Request`: {e}"));

let expected = JuniperRequest(GraphQLBatchRequest::Single(GraphQLRequest::new(
"{ add(a: 2, b: 3) }".to_string(),
None,
None,
)));

assert_eq!(do_from_request(req).await, expected);
}

#[tokio::test]
async fn from_graphql_post_request() {
let req = Request::post("/")
Expand All @@ -262,6 +280,22 @@ mod juniper_request_tests {
assert_eq!(do_from_request(req).await, expected);
}

#[tokio::test]
async fn from_graphql_post_request_with_charset() {
let req = Request::post("/")
.header("content-type", "application/graphql; charset=utf-8")
.body(Body::from(r#"{ add(a: 2, b: 3) }"#))
.unwrap_or_else(|e| panic!("cannot build `Request`: {e}"));

let expected = JuniperRequest(GraphQLBatchRequest::Single(GraphQLRequest::new(
"{ add(a: 2, b: 3) }".to_string(),
None,
None,
)));

assert_eq!(do_from_request(req).await, expected);
}

/// Performs [`JuniperRequest::from_request()`].
async fn do_from_request(req: Request<Body>) -> JuniperRequest {
match JuniperRequest::from_request(req, &()).await {
Expand Down
Loading