Skip to content

Commit

Permalink
Fixed HTTP Spec issues
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib committed Nov 14, 2022
1 parent 96c46b7 commit f3239e4
Show file tree
Hide file tree
Showing 120 changed files with 241 additions and 184 deletions.
Expand Up @@ -180,10 +180,17 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter
var contextData = result.ContextData;

// first we check if there is an explicit HTTP status code override by the user.
if (contextData.TryGetValue(WellKnownContextData.HttpStatusCode, out var value) &&
value is HttpStatusCode statusCode)
if (contextData.TryGetValue(WellKnownContextData.HttpStatusCode, out var value))
{
return statusCode;
if (value is HttpStatusCode statusCode)
{
return statusCode;
}

if (value is int statusCodeInt)
{
return (HttpStatusCode)statusCodeInt;
}
}

// next we check if the validation of the request failed.
Expand Down Expand Up @@ -250,15 +257,15 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter
formatInfo = default;

// if the request does not specify the accept header then we will
// use the `application/json` response content-type,
// which is the legacy behavior.
// use the `application/graphql-response+json` response content-type,
// which is the new response content-type.
if (acceptMediaTypes.Length == 0)
{
if (result.Kind is SingleResult)
{
formatInfo = new FormatInfo(
ContentType.Json,
ResponseContentType.Json,
ContentType.GraphQLResponse,
ResponseContentType.GraphQLResponse,
_jsonFormatter);
return true;
}
Expand Down Expand Up @@ -301,7 +308,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter
var mediaType = acceptMediaTypes[0];

if (resultKind is ResultKind.Single &&
mediaType.Kind is ApplicationGraphQL or AllApplication)
mediaType.Kind is ApplicationGraphQL or AllApplication or All)
{
formatInfo = new FormatInfo(
ContentType.GraphQLResponse,
Expand All @@ -311,7 +318,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter
}

if (resultKind is ResultKind.Single &&
mediaType.Kind is ApplicationJson or All)
mediaType.Kind is ApplicationJson)
{
formatInfo = new FormatInfo(
ContentType.Json,
Expand Down Expand Up @@ -352,7 +359,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter
var mediaType = Unsafe.Add(ref searchSpace, i);

if (resultKind is ResultKind.Single &&
mediaType.Kind is ApplicationGraphQL or AllApplication)
mediaType.Kind is ApplicationGraphQL or AllApplication or All)
{
formatInfo = new FormatInfo(
ContentType.GraphQLResponse,
Expand All @@ -362,7 +369,7 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter
}

if (resultKind is ResultKind.Single &&
mediaType.Kind is ApplicationJson or All)
mediaType.Kind is ApplicationJson)
{
// application/json is a legacy response content-type.
// We will create a formatInfo but keep on validating for
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"default": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"default": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"default": "foo"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"piped": "foo"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"piped": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"age": "foo"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"afterResolver": "foo"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"afterResolver": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"age": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"age": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"age": "foo"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"roles": "foo"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"roles_ab": "foo"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"roles": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"roles": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"roles_ab": null
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"roles_ab": "foo"
Expand Down
Expand Up @@ -47,13 +47,50 @@ public async Task Legacy_Query_No_Streams_1()
.Add(response)
.MatchInline(
@"Headers:
Content-Type: application/json; charset=utf-8
Content-Type: application/graphql-response+json; charset=utf-8
-------------------------->
Status Code: OK
-------------------------->
{""data"":{""__typename"":""Query""}}");
}

/// <summary>
/// This request does not specify a accept header.
/// expected response content-type: application/json
/// expected status code: 200
/// </summary>
[Fact]
public async Task Query_No_Body()
{
// arrange
var server = CreateStarWarsServer();
var client = server.CreateClient();

// act
using var request = new HttpRequestMessage(HttpMethod.Post, _url)
{
Content = new ByteArrayContent(Array.Empty<byte>())
{
Headers = { ContentType = new("application/json") { CharSet = "utf-8" } }
}
};
using var response = await client.SendAsync(request);

// assert
// expected response content-type: application/json
// expected status code: 200
Snapshot
.Create()
.Add(response)
.MatchInline(
@"Headers:
Content-Type: application/graphql-response+json; charset=utf-8
-------------------------->
Status Code: BadRequest
-------------------------->
{""errors"":[{""message"":""The GraphQL request is empty."",""extensions"":{""code"":""HC0012""}}]}");
}

/// <summary>
/// This request does not specify a accept header and has a syntax error.
/// expected response content-type: application/json
Expand Down Expand Up @@ -86,9 +123,9 @@ public async Task Legacy_Query_No_Streams_2()
.Add(response)
.MatchInline(
@"Headers:
Content-Type: application/json; charset=utf-8
Content-Type: application/graphql-response+json; charset=utf-8
-------------------------->
Status Code: OK
Status Code: BadRequest
-------------------------->
{""errors"":[{""message"":""Expected a \u0060Name\u0060-token, but found a " +
@"\u0060Dollar\u0060-token."",""locations"":[{""line"":1,""column"":8}]," +
Expand Down Expand Up @@ -127,9 +164,9 @@ public async Task Legacy_Query_No_Streams_3()
.Add(response)
.MatchInline(
@"Headers:
Content-Type: application/json; charset=utf-8
Content-Type: application/graphql-response+json; charset=utf-8
-------------------------->
Status Code: OK
Status Code: BadRequest
-------------------------->
{""errors"":[{""message"":""\u0060__type\u0060 is an object, interface or " +
"union type field. Leaf selections on objects, interfaces, and unions without " +
Expand Down Expand Up @@ -420,7 +457,7 @@ public async Task New_Query_No_Streams_5()
.Add(response)
.MatchInline(
@"Headers:
Content-Type: application/json; charset=utf-8
Content-Type: application/graphql-response+json; charset=utf-8
-------------------------->
Status Code: OK
-------------------------->
Expand Down
Expand Up @@ -165,7 +165,7 @@ public async Task Download_GraphQL_SDL_Disabled()
var response = await server.CreateClient().SendAsync(request);

// assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
var result = await response.Content.ReadAsStringAsync();
result.MatchSnapshot();
}
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"hero": {
Expand Down
@@ -1,6 +1,6 @@
[
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand All @@ -14,7 +14,7 @@
}
},
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand Down
@@ -1,6 +1,6 @@
[
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand All @@ -14,7 +14,7 @@
}
},
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand Down
@@ -1,6 +1,6 @@
{
"ContentType": "application/json; charset=utf-8",
"StatusCode": "OK",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "BadRequest",
"Data": null,
"Errors": [
{
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"__typename": "Query"
Expand Down
@@ -1,6 +1,6 @@
{
"ContentType": "application/json; charset=utf-8",
"StatusCode": "OK",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "InternalServerError",
"Data": null,
"Errors": [
{
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"createReview": {
Expand Down
@@ -1,6 +1,6 @@
{
"ContentType": "application/json; charset=utf-8",
"StatusCode": "OK",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "BadRequest",
"Data": null,
"Errors": [
{
Expand Down
@@ -1,5 +1,5 @@
{
"ContentType": "application/json; charset=utf-8",
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "OK",
"Data": {
"createReview": {
Expand Down

0 comments on commit f3239e4

Please sign in to comment.