diff --git a/src/core/http/request_handler.rs b/src/core/http/request_handler.rs index e7ab5efae2..562dc57298 100644 --- a/src/core/http/request_handler.rs +++ b/src/core/http/request_handler.rs @@ -91,6 +91,19 @@ pub async fn graphql_request( let req_ctx = Arc::new(create_request_context(&req, app_ctx)); let (req, body) = req.into_parts(); let bytes = hyper::body::to_bytes(body).await?; + let bytes = if req.headers.get("content-type") + == Some(&HeaderValue::from_str("application/graphql")?) + { + let decoded_str = String::from_utf8_lossy(&bytes).clone(); + let enriched_str = if decoded_str.contains("\\") { + format!(r#"{{"query": {} }}"#, decoded_str) + } else { + format!(r#"{{"query": {:?} }}"#, decoded_str) + }; + hyper::body::to_bytes(enriched_str).await? + } else { + bytes + }; let graphql_request = serde_json::from_slice::(&bytes); match graphql_request { Ok(request) => { diff --git a/tests/core/snapshots/content-type-graphql.md_0.snap b/tests/core/snapshots/content-type-graphql.md_0.snap new file mode 100644 index 0000000000..380ff38f7c --- /dev/null +++ b/tests/core/snapshots/content-type-graphql.md_0.snap @@ -0,0 +1,19 @@ +--- +source: tests/core/spec.rs +expression: response +snapshot_kind: text +--- +{ + "status": 200, + "headers": { + "content-type": "application/json" + }, + "body": { + "data": { + "user": { + "city": "Globe", + "name": "Tailcall" + } + } + } +} diff --git a/tests/core/snapshots/content-type-graphql.md_client.snap b/tests/core/snapshots/content-type-graphql.md_client.snap new file mode 100644 index 0000000000..2e759f3b7c --- /dev/null +++ b/tests/core/snapshots/content-type-graphql.md_client.snap @@ -0,0 +1,18 @@ +--- +source: tests/core/spec.rs +expression: formatted +snapshot_kind: text +--- +type Query { + user(id: ID!): User! +} + +type User { + city: String + id: ID! + name: String! +} + +schema { + query: Query +} diff --git a/tests/core/snapshots/content-type-graphql.md_merged.snap b/tests/core/snapshots/content-type-graphql.md_merged.snap new file mode 100644 index 0000000000..577115996f --- /dev/null +++ b/tests/core/snapshots/content-type-graphql.md_merged.snap @@ -0,0 +1,22 @@ +--- +source: tests/core/spec.rs +expression: formatter +snapshot_kind: text +--- +schema + @server(hostname: "0.0.0.0", port: 8001, queryValidation: false) + @upstream(httpCache: 42) + @link(src: "schema_0.graphql", type: Config) { + query: Query +} + +type Query { + user(id: ID!): User! + @graphQL(args: [{key: "id", value: "{{.args.id}}"}], url: "http://upstream/graphql", name: "user") +} + +type User { + city: String + id: ID! + name: String! +} diff --git a/tests/execution/content-type-graphql.md b/tests/execution/content-type-graphql.md new file mode 100644 index 0000000000..69edc99ecb --- /dev/null +++ b/tests/execution/content-type-graphql.md @@ -0,0 +1,57 @@ +# Basic queries with field ordering check + +```yaml @config +server: + port: 8001 + hostname: "0.0.0.0" + queryValidation: false +upstream: + httpCache: 42 +``` + +```graphql @schema +schema { + query: Query +} + +type Query { + user(id: ID!): User! + @graphQL(url: "http://upstream/graphql", name: "user", args: [{key: "id", value: "{{.args.id}}"}]) +} + +type User { + id: ID! + name: String! + city: String +} +``` + +```yml @mock +- request: + method: POST + url: http://upstream/graphql + textBody: '{ "query": "query { user(id: 4) { city name } }" }' + expectedHits: 1 + response: + status: 200 + body: + data: + user: + city: Globe + name: Tailcall +``` + +```yml @test +# Positive: basic 1 +- method: POST + url: http://localhost:8080/graphql + headers: + content-type: application/graphql + body: | + query { + user(id: 4) { + city + name + } + } +```