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

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using HotChocolate.AspNetCore.Formatters;
using HotChocolate.AspNetCore.Instrumentation;
using HotChocolate.AspNetCore.Parsers;
using HotChocolate.AspNetCore.Utilities;
using HotChocolate.Features;
using HotChocolate.Language;
using Microsoft.AspNetCore.Http;
Expand Down Expand Up @@ -85,7 +86,8 @@ public ValueTask OnCreateAsync(
public async Task<IExecutionResult> ExecuteSingleAsync(
HttpContext context,
GraphQLRequest request,
RequestFlags flags)
RequestFlags flags,
GraphQLServerOptions options)
{
_diagnosticEvents.StartSingleRequest(context, request);

Expand All @@ -95,7 +97,26 @@ public async Task<IExecutionResult> ExecuteSingleAsync(

await _requestInterceptor.OnCreateAsync(context, _executor, requestBuilder, context.RequestAborted);

return await _executor.ExecuteAsync(requestBuilder.Build(), context.RequestAborted);
var operationRequest = requestBuilder.Build();

if (operationRequest is VariableBatchRequest variableBatch)
{
if (!options.Batching.HasFlag(AllowedBatching.VariableBatching))
{
var error = Handle(ErrorHelper.InvalidRequest());
return OperationResult.FromError(error);
}

var maxBatchSize = options.MaxBatchSize;
if (maxBatchSize > 0
&& variableBatch.VariableValues.Document.RootElement.GetArrayLength() > maxBatchSize)
{
var error = Handle(ErrorHelper.BatchSizeExceeded(maxBatchSize));
return OperationResult.FromError(error);
}
}

return await _executor.ExecuteAsync(operationRequest, context.RequestAborted);
}

#if !NET9_0_OR_GREATER
Expand Down Expand Up @@ -136,8 +157,16 @@ public async Task<IResponseStream> ExecuteOperationBatchAsync(
public async Task<IResponseStream> ExecuteBatchAsync(
HttpContext context,
GraphQLRequest[] requests,
RequestFlags flags)
RequestFlags flags,
GraphQLServerOptions options)
{
var maxBatchSize = options.MaxBatchSize;
if (maxBatchSize > 0 && requests.Length > maxBatchSize)
{
var error = Handle(ErrorHelper.BatchSizeExceeded(maxBatchSize));
throw new GraphQLException(error);
}

_diagnosticEvents.StartBatchRequest(context, requests);

var requestBatch = new IOperationRequest[requests.Length];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ public static GraphQLEndpointConventionBuilder MapGraphQL(
var pattern = Parse(path + "/{**slug}");
var requestPipeline = endpointRouteBuilder.CreateApplicationBuilder();
requestPipeline.MapGraphQL(path, schemaNameOrDefault);
var serverOptions = endpointRouteBuilder.ServiceProvider.GetRequiredService<IOptionsMonitor<GraphQLServerOptions>>().Get(schemaNameOrDefault);

return new GraphQLEndpointConventionBuilder(
endpointRouteBuilder
.Map(pattern, requestPipeline.Build())
.WithDisplayName("Hot Chocolate GraphQL Pipeline"));
.WithDisplayName("Hot Chocolate GraphQL Pipeline")
.WithMetadata(serverOptions.Tool));
}

/// <summary>
Expand Down Expand Up @@ -125,15 +127,16 @@ public static IApplicationBuilder MapGraphQL(
var executorEvents = applicationBuilder.ApplicationServices.GetRequiredService<IRequestExecutorEvents>();
var formOptions = applicationBuilder.ApplicationServices.GetRequiredService<IOptions<FormOptions>>();
var executor = new HttpRequestExecutorProxy(executorProvider, executorEvents, schemaName);
var serverOptions = applicationBuilder.ApplicationServices.GetRequiredService<IOptionsMonitor<GraphQLServerOptions>>().Get(schemaName);

applicationBuilder
.Use(MiddlewareFactory.CreateCancellationMiddleware())
.Use(MiddlewareFactory.CreateWebSocketSubscriptionMiddleware(executor))
.Use(MiddlewareFactory.CreateHttpPostMiddleware(executor))
.Use(MiddlewareFactory.CreateHttpMultipartMiddleware(executor, formOptions))
.Use(MiddlewareFactory.CreateHttpGetMiddleware(executor))
.Use(MiddlewareFactory.CreateHttpGetSchemaMiddleware(executor, path, MiddlewareRoutingType.Integrated))
.UseNitroApp(path)
.Use(MiddlewareFactory.CreateWebSocketSubscriptionMiddleware(executor, serverOptions))
.Use(MiddlewareFactory.CreateHttpPostMiddleware(executor, serverOptions))
.Use(MiddlewareFactory.CreateHttpMultipartMiddleware(executor, serverOptions, formOptions))
.Use(MiddlewareFactory.CreateHttpGetMiddleware(executor, serverOptions))
.Use(MiddlewareFactory.CreateHttpGetSchemaMiddleware(executor, serverOptions, path, MiddlewareRoutingType.Integrated))
.UseNitroApp(path, serverOptions.Tool)
.Use(_ => context =>
{
context.Response.StatusCode = 404;
Expand Down Expand Up @@ -204,12 +207,13 @@ public static GraphQLHttpEndpointConventionBuilder MapGraphQLHttp(
var executorEvents = endpointRouteBuilder.ServiceProvider.GetRequiredService<IRequestExecutorEvents>();
var formOptions = endpointRouteBuilder.ServiceProvider.GetRequiredService<IOptions<FormOptions>>();
var executor = new HttpRequestExecutorProxy(executorProvider, executorEvents, schemaNameOrDefault);
var serverOptions = endpointRouteBuilder.ServiceProvider.GetRequiredService<IOptionsMonitor<GraphQLServerOptions>>().Get(schemaNameOrDefault);

requestPipeline
.Use(MiddlewareFactory.CreateCancellationMiddleware())
.Use(MiddlewareFactory.CreateHttpPostMiddleware(executor))
.Use(MiddlewareFactory.CreateHttpMultipartMiddleware(executor, formOptions))
.Use(MiddlewareFactory.CreateHttpGetMiddleware(executor))
.Use(MiddlewareFactory.CreateHttpPostMiddleware(executor, serverOptions))
.Use(MiddlewareFactory.CreateHttpMultipartMiddleware(executor, serverOptions, formOptions))
.Use(MiddlewareFactory.CreateHttpGetMiddleware(executor, serverOptions))
.Use(_ => context =>
{
context.Response.StatusCode = 404;
Expand Down Expand Up @@ -241,7 +245,7 @@ public static GraphQLHttpEndpointConventionBuilder MapGraphQLHttp(
/// <exception cref="ArgumentNullException">
/// The <paramref name="endpointRouteBuilder" /> is <c>null</c>.
/// </exception>
public static WebSocketEndpointConventionBuilder MapGraphQLWebSocket(
public static GraphQLWebSocketEndpointConventionBuilder MapGraphQLWebSocket(
this IEndpointRouteBuilder endpointRouteBuilder,
[StringSyntax("Route")] string pattern = GraphQLWebSocketPath,
string? schemaName = null)
Expand All @@ -266,7 +270,7 @@ public static WebSocketEndpointConventionBuilder MapGraphQLWebSocket(
/// <exception cref="ArgumentNullException">
/// The <paramref name="endpointRouteBuilder" /> is <c>null</c>.
/// </exception>
public static WebSocketEndpointConventionBuilder MapGraphQLWebSocket(
public static GraphQLWebSocketEndpointConventionBuilder MapGraphQLWebSocket(
this IEndpointRouteBuilder endpointRouteBuilder,
RoutePattern pattern,
string? schemaName = null)
Expand All @@ -282,10 +286,11 @@ public static WebSocketEndpointConventionBuilder MapGraphQLWebSocket(
var executorProvider = endpointRouteBuilder.ServiceProvider.GetRequiredService<IRequestExecutorProvider>();
var executorEvents = endpointRouteBuilder.ServiceProvider.GetRequiredService<IRequestExecutorEvents>();
var executor = new HttpRequestExecutorProxy(executorProvider, executorEvents, schemaNameOrDefault);
var serverOptions = endpointRouteBuilder.ServiceProvider.GetRequiredService<IOptionsMonitor<GraphQLServerOptions>>().Get(schemaNameOrDefault);

requestPipeline
.Use(MiddlewareFactory.CreateCancellationMiddleware())
.Use(MiddlewareFactory.CreateWebSocketSubscriptionMiddleware(executor))
.Use(MiddlewareFactory.CreateWebSocketSubscriptionMiddleware(executor, serverOptions))
.Use(_ => context =>
{
context.Response.StatusCode = 404;
Expand All @@ -297,7 +302,7 @@ public static WebSocketEndpointConventionBuilder MapGraphQLWebSocket(
.Map(pattern, requestPipeline.Build())
.WithDisplayName("Hot Chocolate GraphQL WebSocket Pipeline"));

return new WebSocketEndpointConventionBuilder(builder);
return new GraphQLWebSocketEndpointConventionBuilder(builder);
}

/// <summary>
Expand Down Expand Up @@ -360,10 +365,11 @@ public static IEndpointConventionBuilder MapGraphQLSchema(
var executorProvider = endpointRouteBuilder.ServiceProvider.GetRequiredService<IRequestExecutorProvider>();
var executorEvents = endpointRouteBuilder.ServiceProvider.GetRequiredService<IRequestExecutorEvents>();
var executor = new HttpRequestExecutorProxy(executorProvider, executorEvents, schemaNameOrDefault);
var serverOptions = endpointRouteBuilder.ServiceProvider.GetRequiredService<IOptionsMonitor<GraphQLServerOptions>>().Get(schemaNameOrDefault);

requestPipeline
.Use(MiddlewareFactory.CreateCancellationMiddleware())
.Use(MiddlewareFactory.CreateHttpGetSchemaMiddleware(executor, PathString.Empty, MiddlewareRoutingType.Explicit))
.Use(MiddlewareFactory.CreateHttpGetSchemaMiddleware(executor, serverOptions, PathString.Empty, MiddlewareRoutingType.Explicit))
.Use(_ => context =>
{
context.Response.StatusCode = 404;
Expand Down Expand Up @@ -426,9 +432,10 @@ public static NitroAppEndpointConventionBuilder MapNitroApp(

var pattern = Parse(toolPath + "/{**slug}");
var requestPipeline = endpointRouteBuilder.CreateApplicationBuilder();
var nitroOptions = new NitroAppOptions { GraphQLEndpoint = relativeRequestPath };

requestPipeline
.UseNitroApp(toolPath)
.UseNitroApp(toolPath, nitroOptions)
.Use(_ => context =>
{
context.Response.StatusCode = 404;
Expand All @@ -438,7 +445,7 @@ public static NitroAppEndpointConventionBuilder MapNitroApp(
var builder = endpointRouteBuilder
.Map(pattern, requestPipeline.Build())
.WithDisplayName("Nitro Pipeline")
.WithMetadata(new NitroAppOptions { GraphQLEndpoint = relativeRequestPath });
.WithMetadata(nitroOptions);

return new NitroAppEndpointConventionBuilder(builder);
}
Expand Down Expand Up @@ -504,87 +511,120 @@ public static IEndpointConventionBuilder MapGraphQLPersistedOperations(
}

/// <summary>
/// Specifies the GraphQL server options.
/// Specifies per-endpoint overrides for <see cref="GraphQLServerOptions"/>.
/// The overrides are applied on top of the schema-level defaults configured
/// via <c>ModifyServerOptions</c>.
/// </summary>
/// <param name="builder">
/// The <see cref="GraphQLEndpointConventionBuilder"/>.
/// </param>
/// <param name="serverOptions">
/// The GraphQL server options.
/// <param name="configure">
/// A delegate to configure the server options for this endpoint.
/// </param>
/// <returns>
/// Returns the <see cref="GraphQLEndpointConventionBuilder"/> so that
/// configuration can be chained.
/// </returns>
public static GraphQLEndpointConventionBuilder WithOptions(
this GraphQLEndpointConventionBuilder builder,
GraphQLServerOptions serverOptions)
=> builder
.WithMetadata(serverOptions)
.WithMetadata(serverOptions.Tool.ToNitroAppOptions());
Action<GraphQLServerOptions> configure)
{
builder.Add(c => c.Metadata.Add(new GraphQLServerOptionsOverride(configure)));
return builder;
}

/// <summary>
/// Specifies the GraphQL HTTP request options.
/// Specifies per-endpoint overrides for <see cref="GraphQLServerOptions"/>.
/// The overrides are applied on top of the schema-level defaults configured
/// via <c>ModifyServerOptions</c>.
/// </summary>
/// <param name="builder">
/// The <see cref="GraphQLEndpointConventionBuilder"/>.
/// The <see cref="GraphQLHttpEndpointConventionBuilder"/>.
/// </param>
/// <param name="httpOptions">
/// The GraphQL HTTP request options.
/// <param name="configure">
/// A delegate to configure the server options for this endpoint.
/// </param>
/// <returns>
/// Returns the <see cref="GraphQLEndpointConventionBuilder"/> so that
/// Returns the <see cref="GraphQLHttpEndpointConventionBuilder"/> so that
/// configuration can be chained.
/// </returns>
public static GraphQLHttpEndpointConventionBuilder WithOptions(
this GraphQLHttpEndpointConventionBuilder builder,
GraphQLHttpOptions httpOptions) =>
builder.WithMetadata(
new GraphQLServerOptions
{
AllowedGetOperations = httpOptions.AllowedGetOperations,
EnableGetRequests = httpOptions.EnableGetRequests,
EnableMultipartRequests = httpOptions.EnableMultipartRequests
});
Action<GraphQLServerOptions> configure)
{
builder.Add(c => c.Metadata.Add(new GraphQLServerOptionsOverride(configure)));
return builder;
}

/// <summary>
/// Specifies the Nitro tooling options.
/// Specifies per-endpoint overrides for <see cref="GraphQLSocketOptions"/>.
/// The overrides are applied on top of the schema-level defaults configured
/// via <c>ModifyServerOptions</c>.
/// </summary>
/// <param name="builder">
/// The <see cref="NitroAppEndpointConventionBuilder"/>.
/// The <see cref="GraphQLWebSocketEndpointConventionBuilder"/>.
/// </param>
/// <param name="toolOptions">
/// The Nitro tooling options.
/// <param name="configure">
/// A delegate to configure the socket options for this endpoint.
/// </param>
/// <returns>
/// Returns the <see cref="NitroAppEndpointConventionBuilder"/> so that
/// Returns the <see cref="GraphQLWebSocketEndpointConventionBuilder"/> so that
/// configuration can be chained.
/// </returns>
public static NitroAppEndpointConventionBuilder WithOptions(
this NitroAppEndpointConventionBuilder builder,
GraphQLToolOptions toolOptions)
public static GraphQLWebSocketEndpointConventionBuilder WithOptions(
this GraphQLWebSocketEndpointConventionBuilder builder,
Action<GraphQLSocketOptions> configure)
{
builder.Add(c => c.Metadata.Add(toolOptions.ToNitroAppOptions()));
builder.Add(c => c.Metadata.Add(
new GraphQLServerOptionsOverride(o => configure(o.Sockets))));
return builder;
}

/// <summary>
/// Specifies the GraphQL over Websocket options.
/// Specifies the Nitro tool options for this endpoint.
/// </summary>
/// <param name="builder">
/// The <see cref="WebSocketEndpointConventionBuilder"/>.
/// The <see cref="GraphQLEndpointConventionBuilder"/>.
/// </param>
/// <param name="socketOptions">
/// The GraphQL socket options.
/// <param name="configure">
/// A delegate to configure the tool options.
/// </param>
/// <returns>
/// Returns the <see cref="WebSocketEndpointConventionBuilder"/> so that
/// Returns the <see cref="GraphQLEndpointConventionBuilder"/> so that
/// configuration can be chained.
/// </returns>
public static WebSocketEndpointConventionBuilder WithOptions(
this WebSocketEndpointConventionBuilder builder,
GraphQLSocketOptions socketOptions) =>
builder.WithMetadata(new GraphQLServerOptions { Sockets = socketOptions });
public static GraphQLEndpointConventionBuilder WithOptions(
this GraphQLEndpointConventionBuilder builder,
Action<NitroAppOptions> configure)
{
var options = new NitroAppOptions();
configure(options);
builder.Add(c => c.Metadata.Add(options));
return builder;
}

/// <summary>
/// Specifies the Nitro tool options for this endpoint.
/// </summary>
/// <param name="builder">
/// The <see cref="NitroAppEndpointConventionBuilder"/>.
/// </param>
/// <param name="configure">
/// A delegate to configure the tool options.
/// </param>
/// <returns>
/// Returns the <see cref="NitroAppEndpointConventionBuilder"/> so that
/// configuration can be chained.
/// </returns>
public static NitroAppEndpointConventionBuilder WithOptions(
this NitroAppEndpointConventionBuilder builder,
Action<NitroAppOptions> configure)
{
var options = new NitroAppOptions();
configure(options);
builder.Add(c => c.Metadata.Add(options));
return builder;
}

private static void TryResolveSchemaName(IServiceProvider services, ref string? schemaName)
{
Expand All @@ -595,20 +635,4 @@ private static void TryResolveSchemaName(IServiceProvider services, ref string?
schemaName = provider.SchemaNames[0];
}
}

internal static NitroAppOptions ToNitroAppOptions(this GraphQLToolOptions options)
=> new()
{
ServeMode = ServeMode.Version(options.ServeMode.Mode),
Title = options.Title,
Document = options.Document,
UseBrowserUrlAsGraphQLEndpoint = options.UseBrowserUrlAsGraphQLEndpoint,
GraphQLEndpoint = options.GraphQLEndpoint,
IncludeCookies = options.IncludeCookies,
HttpHeaders = options.HttpHeaders,
UseGet = options.HttpMethod == DefaultHttpMethod.Get,
Enable = options.Enable,
GaTrackingId = options.GaTrackingId,
DisableTelemetry = options.DisableTelemetry
};
}
Loading
Loading