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

Support for GET requests #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 4, 2022
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
File renamed without changes.
7 changes: 1 addition & 6 deletions 7 build/nuget-package-readme.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
## GraphQL ASP.NET

<br/>

### Documentation: [https://graphql-aspnet.github.io](https://graphql-aspnet.github.io)

<br />

GraphQL ASP.NET is a fully featured graphql library that utilizes a controller/action programming model similar to ASP.NET.

GraphQL ASP.NET is a fully featured graphql library that utilizes a controller/action programming model similar to ASP.NET.

**This Controller**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ public class SchemaQueryHandlerConfiguration

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

/// <summary>
/// <para>
/// Gets or sets the route to which the internal controller registered for the schema will listen.
/// The route is automatically registered as a POST request. (Default: '/graphql').
/// The route is automatically registered as a POST and GET request. (Default: '/graphql').
/// </para>
/// <para>
/// NOTE: If this application registers more than one <see cref="ISchema"/> this value must be unique
Expand Down
30 changes: 30 additions & 0 deletions 30 src/graphql-aspnet/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,36 @@ public static class Pipelines
public const string DIRECTIVE_PIPELINE = "Directive Execution Pipeline";
}

/// <summary>
/// A collection of constants related to the web processing of a query.
/// </summary>
public static class Web
{
/// <summary>
/// The key in the query string representing the query text when
/// processing a GET request.
/// </summary>
public const string QUERYSTRING_QUERY_KEY = "query";

/// <summary>
/// The key in the query string representing the named operation when
/// processing a GET request.
/// </summary>
public const string QUERYSTRING_OPERATIONNAME_KEY = "operationName";

/// <summary>
/// The key in the query string representing the the json encoded variable collection
/// when processing a GET request.
/// </summary>
public const string QUERYSTRING_VARIABLES_KEY = "variables";

/// <summary>
/// A 'content-type' header value that indicates the body of a POST request
/// should be treated entirely as a graphql query string.
/// </summary>
public const string GRAPHQL_CONTENT_TYPE_HEADER_VALUE = "application/graphql";
}

/// <summary>
/// Gets a URL pointing to the page of the graphql specification this library
/// targets. This value is used as a base url for most validation rules to generate
Expand Down
68 changes: 37 additions & 31 deletions 68 src/graphql-aspnet/Defaults/DefaultGraphQLHttpProcessor{TSchema}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ namespace GraphQL.AspNet.Defaults
{
using System;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using GraphQL.AspNet.Common;
Expand All @@ -27,6 +25,7 @@ namespace GraphQL.AspNet.Defaults
using GraphQL.AspNet.Logging.Extensions;
using GraphQL.AspNet.Security.Web;
using GraphQL.AspNet.Web;
using GraphQL.AspNet.Web.Exceptions;
using Microsoft.AspNetCore.Http;

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

/// <summary>
/// An error message constant, in english, providing the text to return to the caller when they use any HTTP action verb
/// other than post.
/// </summary>
protected const string ERROR_USE_POST = "GraphQL queries should be executed as a POST request";

/// <summary>
/// An error message constant, in english, providing the text to return to the caller when a 500 error is generated.
/// </summary>
Expand All @@ -67,10 +60,10 @@ public class DefaultGraphQLHttpProcessor<TSchema> : IGraphQLHttpProcessor<TSchem
/// <summary>
/// Initializes a new instance of the <see cref="DefaultGraphQLHttpProcessor{TSchema}" /> class.
/// </summary>
/// <param name="schema">The singleton instance of <typeparamref name="TSchema"/> representing this processor works against.</param>
/// <param name="runtime">The primary runtime instance in which GraphQL requests are processed for <typeparamref name="TSchema"/>.</param>
/// <param name="writer">The result writer capable of converting a <see cref="IGraphOperationResult"/> into a serialized payload
/// for the given <typeparamref name="TSchema"/>.</param>
/// <param name="schema">The singleton instance of <typeparamref name="TSchema" /> representing this processor works against.</param>
/// <param name="runtime">The primary runtime instance in which GraphQL requests are processed for <typeparamref name="TSchema" />.</param>
/// <param name="writer">The result writer capable of converting a <see cref="IGraphOperationResult" /> into a serialized payload
/// for the given <typeparamref name="TSchema" />.</param>
/// <param name="logger">A logger instance where this object can write and record log entries.</param>
public DefaultGraphQLHttpProcessor(
TSchema schema,
Expand All @@ -81,35 +74,43 @@ public DefaultGraphQLHttpProcessor(
_schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema));
_runtime = Validation.ThrowIfNullOrReturn(runtime, nameof(runtime));
_writer = Validation.ThrowIfNullOrReturn(writer, nameof(writer));

_logger = logger;
}

/// <inheritdoc />
public virtual async Task Invoke(HttpContext context)
{
this.HttpContext = Validation.ThrowIfNullOrReturn(context, nameof(context));
if (!string.Equals(context.Request.Method, nameof(HttpMethod.Post), StringComparison.OrdinalIgnoreCase))

GraphQueryData queryData;
try
{
queryData = await this.ParseHttpContext();
}
catch (HttpContextParsingException ex)
{
await this.WriteStatusCodeResponse(HttpStatusCode.BadRequest, ERROR_USE_POST, context.RequestAborted).ConfigureAwait(false);
await this.WriteStatusCodeResponse(ex.StatusCode, ex.Message, context.RequestAborted).ConfigureAwait(false);
return;
}

// accepting a parsed object causes havoc with any variables collection
// ------
// By default:
// netcoreapp2.2 and older would auto parse to JObject (Newtonsoft)
// netcoreapp3.0 and later will parse to JsonElement (System.Text.Json).
// ------
// in lue of supporting deserialization from both generic json object types
// we accept the raw data and parse the json document
// using System.Text.Json on all clients (netstandard2.0 compatiable)
var options = new JsonSerializerOptions();
options.PropertyNameCaseInsensitive = true;
options.AllowTrailingCommas = true;
options.ReadCommentHandling = JsonCommentHandling.Skip;

var data = await JsonSerializer.DeserializeAsync<GraphQueryData>(context.Request.Body, options).ConfigureAwait(false);
await this.SubmitGraphQLQuery(data, context.RequestAborted).ConfigureAwait(false);
await this.SubmitGraphQLQuery(queryData, context.RequestAborted).ConfigureAwait(false);
}

/// <summary>
/// When overriden in a child class, allows for the alteration of the method by which the various query
/// parameters are extracted from the <see cref="HttpContext"/> for input to the graphql runtime.
/// </summary>
/// <remarks>
/// Throw an <see cref="HttpContextParsingException"/> to stop execution and quickly write
/// an error back to the requestor.
/// </remarks>
/// <returns>A parsed query data object containing the input parameters for the
/// graphql runtime or <c>null</c>.</returns>
protected virtual async Task<GraphQueryData> ParseHttpContext()
{
var dataGenerator = new HttpContextParser(this.HttpContext);
return await dataGenerator.Parse();
}

/// <summary>
Expand Down Expand Up @@ -229,7 +230,7 @@ protected virtual IUserSecurityContext CreateUserSecurityContext()
}

/// <summary>
/// writes directly to the <see cref="HttpResponse" /> stream with the given status code
/// Writes directly to the <see cref="HttpResponse" /> stream with the given status code
/// and message.
/// </summary>
/// <param name="statusCode">The status code to deliver on the response.</param>
Expand All @@ -238,6 +239,11 @@ protected virtual IUserSecurityContext CreateUserSecurityContext()
/// <returns>Task.</returns>
protected async Task WriteStatusCodeResponse(HttpStatusCode statusCode, string message, CancellationToken cancelToken = default)
{
if (_schema.Configuration.ResponseOptions.AppendServerHeader)
{
this.Response.Headers.Add(Constants.ServerInformation.SERVER_INFORMATION_HEADER, Constants.ServerInformation.ServerData);
}

this.Response.StatusCode = (int)statusCode;
await this.Response.WriteAsync(message, cancelToken).ConfigureAwait(false);
}
Expand Down
9 changes: 8 additions & 1 deletion 9 src/graphql-aspnet/GraphQueryData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace GraphQL.AspNet
using GraphQL.AspNet.Variables;

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

/// <summary>
/// Initializes a new instance of the <see cref="GraphQueryData"/> class.
/// </summary>
public GraphQueryData()
{
}

/// <summary>
/// Gets or sets the name of the operation in the query document to execute. Must be included
/// when the document defines more than one operation.
Expand Down
3 changes: 3 additions & 0 deletions 3 src/graphql-aspnet/Variables/InputVariableCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public class InputVariableCollection : IInputVariableCollection
/// <returns>IInputVariableCollection.</returns>
public static InputVariableCollection FromJsonDocument(string jsonDocument)
{
if (string.IsNullOrWhiteSpace(jsonDocument))
return InputVariableCollection.Empty;

var options = new JsonSerializerOptions()
{
AllowTrailingCommas = true,
Expand Down
41 changes: 41 additions & 0 deletions 41 src/graphql-aspnet/Web/Exceptions/HttpContextParsingException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// *************************************************************
// project: graphql-aspnet
// --
// repo: https://github.com/graphql-aspnet
// docs: https://graphql-aspnet.github.io
// --
// License: MIT
// *************************************************************

namespace GraphQL.AspNet.Web.Exceptions
{
using System;
using System.Net;
using Microsoft.AspNetCore.Http;

/// <summary>
/// An exception thrown when the runtime is uanble to successfully extract the
/// data from an <see cref="HttpContext"/> to generate a data package
/// for the graphql runtime.
/// </summary>
public class HttpContextParsingException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="HttpContextParsingException"/> class.
/// </summary>
/// <param name="statusCode">The status code taht should be set, indicating the reason for failure.</param>
/// <param name="errorMessage">An end user friendly error message to include. This message will be
/// written directly to the http response.</param>
public HttpContextParsingException(HttpStatusCode statusCode = HttpStatusCode.BadRequest, string errorMessage = "")
: base(errorMessage)
{
this.StatusCode = statusCode;
}

/// <summary>
/// Gets the status code that should be set on the http response, indicating the reason for the failure.
/// </summary>
/// <value>The status code.</value>
public HttpStatusCode StatusCode { get; }
}
}
2 changes: 1 addition & 1 deletion 2 src/graphql-aspnet/Web/GraphQueryHandler{TSchema}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected Task Invoke(HttpContext context)
throw new InvalidOperationException(
$"No {nameof(IGraphQLHttpProcessor)} of type " +
$"{typeof(IGraphQLHttpProcessor<TSchema>).FriendlyName()} " +
"is registered with the DI container. The GraphQL runtime cannot invoke the schema.");
"is registered with the DI container. The GraphQL runtime cannot invoke the target schema.");
}

return processor.Invoke(context);
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.