Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0641023

Browse filesBrowse files
Support for GET requests (#81)
* added support for GET requests * added support for query params on POST request, and application/graphql content-header
1 parent abba86b commit 0641023
Copy full SHA for 0641023
Expand file treeCollapse file tree

13 files changed

+907
-43
lines changed
File renamed without changes.

‎build/nuget-package-readme.md

Copy file name to clipboardExpand all lines: build/nuget-package-readme.md
+1-6Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
## GraphQL ASP.NET
22

3-
<br/>
4-
53
### Documentation: [https://graphql-aspnet.github.io](https://graphql-aspnet.github.io)
64

7-
<br />
8-
9-
GraphQL ASP.NET is a fully featured graphql library that utilizes a controller/action programming model similar to ASP.NET.
10-
5+
GraphQL ASP.NET is a fully featured graphql library that utilizes a controller/action programming model similar to ASP.NET.
116

127
**This Controller**
138

‎src/graphql-aspnet/Configuration/SchemaQueryHandlerConfiguration.cs

Copy file name to clipboardExpand all lines: src/graphql-aspnet/Configuration/SchemaQueryHandlerConfiguration.cs
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ public class SchemaQueryHandlerConfiguration
3333

3434
/// <summary>
3535
/// Gets or sets a value indicating whether the default query processing controller
36-
/// should be registered to the application. If disabled, the application will not register
36+
/// should be registered to the application. When disabled, the application will not register
3737
/// its internal handler as a public end point; the application will need to handle
38-
/// HTTP request routing manually (Default: false).
38+
/// HTTP request routing manually (Default: false, "do include the default route").
3939
/// </summary>
4040
/// <value><c>true</c> if the route should be disabled; otherwise, <c>false</c>.</value>
4141
public bool DisableDefaultRoute { get; set; } = false;
4242

4343
/// <summary>
4444
/// <para>
4545
/// Gets or sets the route to which the internal controller registered for the schema will listen.
46-
/// The route is automatically registered as a POST request. (Default: '/graphql').
46+
/// The route is automatically registered as a POST and GET request. (Default: '/graphql').
4747
/// </para>
4848
/// <para>
4949
/// NOTE: If this application registers more than one <see cref="ISchema"/> this value must be unique

‎src/graphql-aspnet/Constants.cs

Copy file name to clipboardExpand all lines: src/graphql-aspnet/Constants.cs
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,36 @@ public static class Pipelines
568568
public const string DIRECTIVE_PIPELINE = "Directive Execution Pipeline";
569569
}
570570

571+
/// <summary>
572+
/// A collection of constants related to the web processing of a query.
573+
/// </summary>
574+
public static class Web
575+
{
576+
/// <summary>
577+
/// The key in the query string representing the query text when
578+
/// processing a GET request.
579+
/// </summary>
580+
public const string QUERYSTRING_QUERY_KEY = "query";
581+
582+
/// <summary>
583+
/// The key in the query string representing the named operation when
584+
/// processing a GET request.
585+
/// </summary>
586+
public const string QUERYSTRING_OPERATIONNAME_KEY = "operationName";
587+
588+
/// <summary>
589+
/// The key in the query string representing the the json encoded variable collection
590+
/// when processing a GET request.
591+
/// </summary>
592+
public const string QUERYSTRING_VARIABLES_KEY = "variables";
593+
594+
/// <summary>
595+
/// A 'content-type' header value that indicates the body of a POST request
596+
/// should be treated entirely as a graphql query string.
597+
/// </summary>
598+
public const string GRAPHQL_CONTENT_TYPE_HEADER_VALUE = "application/graphql";
599+
}
600+
571601
/// <summary>
572602
/// Gets a URL pointing to the page of the graphql specification this library
573603
/// targets. This value is used as a base url for most validation rules to generate

‎src/graphql-aspnet/Defaults/DefaultGraphQLHttpProcessor{TSchema}.cs

Copy file name to clipboardExpand all lines: src/graphql-aspnet/Defaults/DefaultGraphQLHttpProcessor{TSchema}.cs
+37-31Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ namespace GraphQL.AspNet.Defaults
1111
{
1212
using System;
1313
using System.Net;
14-
using System.Net.Http;
1514
using System.Security.Claims;
16-
using System.Text.Json;
1715
using System.Threading;
1816
using System.Threading.Tasks;
1917
using GraphQL.AspNet.Common;
@@ -27,6 +25,7 @@ namespace GraphQL.AspNet.Defaults
2725
using GraphQL.AspNet.Logging.Extensions;
2826
using GraphQL.AspNet.Security.Web;
2927
using GraphQL.AspNet.Web;
28+
using GraphQL.AspNet.Web.Exceptions;
3029
using Microsoft.AspNetCore.Http;
3130

3231
/// <summary>
@@ -42,12 +41,6 @@ public class DefaultGraphQLHttpProcessor<TSchema> : IGraphQLHttpProcessor<TSchem
4241
/// </summary>
4342
protected const string ERROR_NO_QUERY_PROVIDED = "No query received on the request";
4443

45-
/// <summary>
46-
/// An error message constant, in english, providing the text to return to the caller when they use any HTTP action verb
47-
/// other than post.
48-
/// </summary>
49-
protected const string ERROR_USE_POST = "GraphQL queries should be executed as a POST request";
50-
5144
/// <summary>
5245
/// An error message constant, in english, providing the text to return to the caller when a 500 error is generated.
5346
/// </summary>
@@ -67,10 +60,10 @@ public class DefaultGraphQLHttpProcessor<TSchema> : IGraphQLHttpProcessor<TSchem
6760
/// <summary>
6861
/// Initializes a new instance of the <see cref="DefaultGraphQLHttpProcessor{TSchema}" /> class.
6962
/// </summary>
70-
/// <param name="schema">The singleton instance of <typeparamref name="TSchema"/> representing this processor works against.</param>
71-
/// <param name="runtime">The primary runtime instance in which GraphQL requests are processed for <typeparamref name="TSchema"/>.</param>
72-
/// <param name="writer">The result writer capable of converting a <see cref="IGraphOperationResult"/> into a serialized payload
73-
/// for the given <typeparamref name="TSchema"/>.</param>
63+
/// <param name="schema">The singleton instance of <typeparamref name="TSchema" /> representing this processor works against.</param>
64+
/// <param name="runtime">The primary runtime instance in which GraphQL requests are processed for <typeparamref name="TSchema" />.</param>
65+
/// <param name="writer">The result writer capable of converting a <see cref="IGraphOperationResult" /> into a serialized payload
66+
/// for the given <typeparamref name="TSchema" />.</param>
7467
/// <param name="logger">A logger instance where this object can write and record log entries.</param>
7568
public DefaultGraphQLHttpProcessor(
7669
TSchema schema,
@@ -81,35 +74,43 @@ public DefaultGraphQLHttpProcessor(
8174
_schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema));
8275
_runtime = Validation.ThrowIfNullOrReturn(runtime, nameof(runtime));
8376
_writer = Validation.ThrowIfNullOrReturn(writer, nameof(writer));
77+
8478
_logger = logger;
8579
}
8680

8781
/// <inheritdoc />
8882
public virtual async Task Invoke(HttpContext context)
8983
{
9084
this.HttpContext = Validation.ThrowIfNullOrReturn(context, nameof(context));
91-
if (!string.Equals(context.Request.Method, nameof(HttpMethod.Post), StringComparison.OrdinalIgnoreCase))
85+
86+
GraphQueryData queryData;
87+
try
88+
{
89+
queryData = await this.ParseHttpContext();
90+
}
91+
catch (HttpContextParsingException ex)
9292
{
93-
await this.WriteStatusCodeResponse(HttpStatusCode.BadRequest, ERROR_USE_POST, context.RequestAborted).ConfigureAwait(false);
93+
await this.WriteStatusCodeResponse(ex.StatusCode, ex.Message, context.RequestAborted).ConfigureAwait(false);
9494
return;
9595
}
9696

97-
// accepting a parsed object causes havoc with any variables collection
98-
// ------
99-
// By default:
100-
// netcoreapp2.2 and older would auto parse to JObject (Newtonsoft)
101-
// netcoreapp3.0 and later will parse to JsonElement (System.Text.Json).
102-
// ------
103-
// in lue of supporting deserialization from both generic json object types
104-
// we accept the raw data and parse the json document
105-
// using System.Text.Json on all clients (netstandard2.0 compatiable)
106-
var options = new JsonSerializerOptions();
107-
options.PropertyNameCaseInsensitive = true;
108-
options.AllowTrailingCommas = true;
109-
options.ReadCommentHandling = JsonCommentHandling.Skip;
110-
111-
var data = await JsonSerializer.DeserializeAsync<GraphQueryData>(context.Request.Body, options).ConfigureAwait(false);
112-
await this.SubmitGraphQLQuery(data, context.RequestAborted).ConfigureAwait(false);
97+
await this.SubmitGraphQLQuery(queryData, context.RequestAborted).ConfigureAwait(false);
98+
}
99+
100+
/// <summary>
101+
/// When overriden in a child class, allows for the alteration of the method by which the various query
102+
/// parameters are extracted from the <see cref="HttpContext"/> for input to the graphql runtime.
103+
/// </summary>
104+
/// <remarks>
105+
/// Throw an <see cref="HttpContextParsingException"/> to stop execution and quickly write
106+
/// an error back to the requestor.
107+
/// </remarks>
108+
/// <returns>A parsed query data object containing the input parameters for the
109+
/// graphql runtime or <c>null</c>.</returns>
110+
protected virtual async Task<GraphQueryData> ParseHttpContext()
111+
{
112+
var dataGenerator = new HttpContextParser(this.HttpContext);
113+
return await dataGenerator.Parse();
113114
}
114115

115116
/// <summary>
@@ -229,7 +230,7 @@ protected virtual IUserSecurityContext CreateUserSecurityContext()
229230
}
230231

231232
/// <summary>
232-
/// writes directly to the <see cref="HttpResponse" /> stream with the given status code
233+
/// Writes directly to the <see cref="HttpResponse" /> stream with the given status code
233234
/// and message.
234235
/// </summary>
235236
/// <param name="statusCode">The status code to deliver on the response.</param>
@@ -238,6 +239,11 @@ protected virtual IUserSecurityContext CreateUserSecurityContext()
238239
/// <returns>Task.</returns>
239240
protected async Task WriteStatusCodeResponse(HttpStatusCode statusCode, string message, CancellationToken cancelToken = default)
240241
{
242+
if (_schema.Configuration.ResponseOptions.AppendServerHeader)
243+
{
244+
this.Response.Headers.Add(Constants.ServerInformation.SERVER_INFORMATION_HEADER, Constants.ServerInformation.ServerData);
245+
}
246+
241247
this.Response.StatusCode = (int)statusCode;
242248
await this.Response.WriteAsync(message, cancelToken).ConfigureAwait(false);
243249
}

‎src/graphql-aspnet/GraphQueryData.cs

Copy file name to clipboardExpand all lines: src/graphql-aspnet/GraphQueryData.cs
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace GraphQL.AspNet
1212
using GraphQL.AspNet.Variables;
1313

1414
/// <summary>
15-
/// An binding model representing an incoming, structured GraphQL query on a HTTP request.
15+
/// A raw data package representing the various inputs to the graphql runtime.
1616
/// </summary>
1717
public class GraphQueryData
1818
{
@@ -35,6 +35,13 @@ static GraphQueryData()
3535
};
3636
}
3737

38+
/// <summary>
39+
/// Initializes a new instance of the <see cref="GraphQueryData"/> class.
40+
/// </summary>
41+
public GraphQueryData()
42+
{
43+
}
44+
3845
/// <summary>
3946
/// Gets or sets the name of the operation in the query document to execute. Must be included
4047
/// when the document defines more than one operation.

‎src/graphql-aspnet/Variables/InputVariableCollection.cs

Copy file name to clipboardExpand all lines: src/graphql-aspnet/Variables/InputVariableCollection.cs
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public class InputVariableCollection : IInputVariableCollection
3232
/// <returns>IInputVariableCollection.</returns>
3333
public static InputVariableCollection FromJsonDocument(string jsonDocument)
3434
{
35+
if (string.IsNullOrWhiteSpace(jsonDocument))
36+
return InputVariableCollection.Empty;
37+
3538
var options = new JsonSerializerOptions()
3639
{
3740
AllowTrailingCommas = true,
+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// *************************************************************
2+
// project: graphql-aspnet
3+
// --
4+
// repo: https://github.com/graphql-aspnet
5+
// docs: https://graphql-aspnet.github.io
6+
// --
7+
// License: MIT
8+
// *************************************************************
9+
10+
namespace GraphQL.AspNet.Web.Exceptions
11+
{
12+
using System;
13+
using System.Net;
14+
using Microsoft.AspNetCore.Http;
15+
16+
/// <summary>
17+
/// An exception thrown when the runtime is uanble to successfully extract the
18+
/// data from an <see cref="HttpContext"/> to generate a data package
19+
/// for the graphql runtime.
20+
/// </summary>
21+
public class HttpContextParsingException : Exception
22+
{
23+
/// <summary>
24+
/// Initializes a new instance of the <see cref="HttpContextParsingException"/> class.
25+
/// </summary>
26+
/// <param name="statusCode">The status code taht should be set, indicating the reason for failure.</param>
27+
/// <param name="errorMessage">An end user friendly error message to include. This message will be
28+
/// written directly to the http response.</param>
29+
public HttpContextParsingException(HttpStatusCode statusCode = HttpStatusCode.BadRequest, string errorMessage = "")
30+
: base(errorMessage)
31+
{
32+
this.StatusCode = statusCode;
33+
}
34+
35+
/// <summary>
36+
/// Gets the status code that should be set on the http response, indicating the reason for the failure.
37+
/// </summary>
38+
/// <value>The status code.</value>
39+
public HttpStatusCode StatusCode { get; }
40+
}
41+
}

‎src/graphql-aspnet/Web/GraphQueryHandler{TSchema}.cs

Copy file name to clipboardExpand all lines: src/graphql-aspnet/Web/GraphQueryHandler{TSchema}.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ protected Task Invoke(HttpContext context)
4444
throw new InvalidOperationException(
4545
$"No {nameof(IGraphQLHttpProcessor)} of type " +
4646
$"{typeof(IGraphQLHttpProcessor<TSchema>).FriendlyName()} " +
47-
"is registered with the DI container. The GraphQL runtime cannot invoke the schema.");
47+
"is registered with the DI container. The GraphQL runtime cannot invoke the target schema.");
4848
}
4949

5050
return processor.Invoke(context);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.