1
+ using System . Diagnostics . CodeAnalysis ;
1
2
using Microsoft . AspNetCore . Http ;
2
3
using Microsoft . AspNetCore . Routing ;
3
4
using Microsoft . AspNetCore . Routing . Patterns ;
4
5
using HotChocolate . AspNetCore ;
5
6
using HotChocolate . AspNetCore . Extensions ;
6
7
using BananaCakePop . Middleware ;
8
+ using HotChocolate . AspNetCore . Instrumentation ;
9
+ using HotChocolate . AspNetCore . Serialization ;
7
10
using static HotChocolate . AspNetCore . MiddlewareRoutingType ;
8
11
using static Microsoft . AspNetCore . Routing . Patterns . RoutePatternFactory ;
9
12
@@ -19,6 +22,7 @@ public static class EndpointRouteBuilderExtensions
19
22
private const string _graphQLWebSocketPath = "/graphql/ws" ;
20
23
private const string _graphQLSchemaPath = "/graphql/sdl" ;
21
24
private const string _graphQLToolPath = "/graphql/ui" ;
25
+ private const string _graphQLPersistedOperationPath = "/graphql/q" ;
22
26
private const string _graphQLToolRelativeRequestPath = ".." ;
23
27
24
28
/// <summary>
@@ -73,11 +77,9 @@ public static GraphQLEndpointConventionBuilder MapGraphQL(
73
77
}
74
78
75
79
path = path . ToString ( ) . TrimEnd ( '/' ) ;
76
-
80
+ var schemaNameOrDefault = schemaName ?? Schema . DefaultName ;
77
81
var pattern = Parse ( path + "/{**slug}" ) ;
78
82
var requestPipeline = endpointRouteBuilder . CreateApplicationBuilder ( ) ;
79
- var schemaNameOrDefault = schemaName ?? Schema . DefaultName ;
80
-
81
83
requestPipeline . MapGraphQL ( path , schemaNameOrDefault ) ;
82
84
83
85
return new GraphQLEndpointConventionBuilder (
@@ -125,11 +127,12 @@ public static IApplicationBuilder MapGraphQL(
125
127
. UseMiddleware < HttpGetMiddleware > ( schemaName )
126
128
. UseMiddleware < HttpGetSchemaMiddleware > ( schemaName , Integrated )
127
129
. UseBananaCakePop ( path )
128
- . Use ( _ => context =>
129
- {
130
- context . Response . StatusCode = 404 ;
131
- return Task . CompletedTask ;
132
- } ) ;
130
+ . Use (
131
+ _ => context =>
132
+ {
133
+ context . Response . StatusCode = 404 ;
134
+ return Task . CompletedTask ;
135
+ } ) ;
133
136
134
137
return applicationBuilder ;
135
138
}
@@ -201,11 +204,12 @@ public static GraphQLHttpEndpointConventionBuilder MapGraphQLHttp(
201
204
. UseMiddleware < HttpPostMiddleware > ( schemaNameOrDefault )
202
205
. UseMiddleware < HttpMultipartMiddleware > ( schemaNameOrDefault )
203
206
. UseMiddleware < HttpGetMiddleware > ( schemaNameOrDefault )
204
- . Use ( _ => context =>
205
- {
206
- context . Response . StatusCode = 404 ;
207
- return Task . CompletedTask ;
208
- } ) ;
207
+ . Use (
208
+ _ => context =>
209
+ {
210
+ context . Response . StatusCode = 404 ;
211
+ return Task . CompletedTask ;
212
+ } ) ;
209
213
210
214
return new GraphQLHttpEndpointConventionBuilder (
211
215
endpointRouteBuilder
@@ -278,11 +282,12 @@ public static WebSocketEndpointConventionBuilder MapGraphQLWebSocket(
278
282
requestPipeline
279
283
. UseCancellation ( )
280
284
. UseMiddleware < WebSocketSubscriptionMiddleware > ( schemaNameOrDefault )
281
- . Use ( _ => context =>
282
- {
283
- context . Response . StatusCode = 404 ;
284
- return Task . CompletedTask ;
285
- } ) ;
285
+ . Use (
286
+ _ => context =>
287
+ {
288
+ context . Response . StatusCode = 404 ;
289
+ return Task . CompletedTask ;
290
+ } ) ;
286
291
287
292
var builder = new GraphQLEndpointConventionBuilder (
288
293
endpointRouteBuilder
@@ -357,11 +362,12 @@ public static IEndpointConventionBuilder MapGraphQLSchema(
357
362
requestPipeline
358
363
. UseCancellation ( )
359
364
. UseMiddleware < HttpGetSchemaMiddleware > ( schemaNameOrDefault , Explicit )
360
- . Use ( _ => context =>
361
- {
362
- context . Response . StatusCode = 404 ;
363
- return Task . CompletedTask ;
364
- } ) ;
365
+ . Use (
366
+ _ => context =>
367
+ {
368
+ context . Response . StatusCode = 404 ;
369
+ return Task . CompletedTask ;
370
+ } ) ;
365
371
366
372
return new GraphQLEndpointConventionBuilder (
367
373
endpointRouteBuilder
@@ -425,11 +431,12 @@ public static BananaCakePopEndpointConventionBuilder MapBananaCakePop(
425
431
426
432
requestPipeline
427
433
. UseBananaCakePop ( toolPath )
428
- . Use ( _ => context =>
429
- {
430
- context . Response . StatusCode = 404 ;
431
- return Task . CompletedTask ;
432
- } ) ;
434
+ . Use (
435
+ _ => context =>
436
+ {
437
+ context . Response . StatusCode = 404 ;
438
+ return Task . CompletedTask ;
439
+ } ) ;
433
440
434
441
var builder = endpointRouteBuilder
435
442
. Map ( pattern , requestPipeline . Build ( ) )
@@ -439,6 +446,56 @@ public static BananaCakePopEndpointConventionBuilder MapBananaCakePop(
439
446
return new BananaCakePopEndpointConventionBuilder ( builder ) ;
440
447
}
441
448
449
+ #if NET8_0_OR_GREATER
450
+ /// <summary>
451
+ /// Adds a persisted query endpoint to the endpoint configurations.
452
+ /// </summary>
453
+ /// <param name="endpointRouteBuilder">
454
+ /// The <see cref="IEndpointRouteBuilder"/>.
455
+ /// </param>
456
+ /// <param name="path">
457
+ /// The path to which the persisted query endpoint shall be mapped.
458
+ /// </param>
459
+ /// <param name="schemaName">
460
+ /// The name of the schema that shall be used by this endpoint.
461
+ /// </param>
462
+ /// <returns>
463
+ /// Returns the <see cref="IEndpointConventionBuilder"/> so that
464
+ /// </returns>
465
+ public static IEndpointConventionBuilder MapGraphQLPersistedOperations (
466
+ this IEndpointRouteBuilder endpointRouteBuilder ,
467
+ [ StringSyntax ( "Route" ) ] string path = _graphQLPersistedOperationPath ,
468
+ string ? schemaName = default )
469
+ => MapGraphQLPersistedOperations ( endpointRouteBuilder , Parse ( path ) , schemaName ) ;
470
+
471
+ /// <summary>
472
+ /// Adds a persisted query endpoint to the endpoint configurations.
473
+ /// </summary>
474
+ /// <param name="endpointRouteBuilder">
475
+ /// The <see cref="IEndpointRouteBuilder"/>.
476
+ /// </param>
477
+ /// <param name="path">
478
+ /// The path to which the persisted query endpoint shall be mapped.
479
+ /// </param>
480
+ /// <param name="schemaName">
481
+ /// The name of the schema that shall be used by this endpoint.
482
+ /// </param>
483
+ /// <returns>
484
+ /// Returns the <see cref="IEndpointConventionBuilder"/> so that
485
+ /// </returns>
486
+ public static IEndpointConventionBuilder MapGraphQLPersistedOperations (
487
+ this IEndpointRouteBuilder endpointRouteBuilder ,
488
+ RoutePattern path ,
489
+ string ? schemaName = default )
490
+ {
491
+ var schemaNameOrDefault = schemaName ?? Schema . DefaultName ;
492
+
493
+ var group = endpointRouteBuilder . MapGroup ( path ) ;
494
+ group . MapPersistedQueryMiddleware ( schemaNameOrDefault ) ;
495
+ return group ;
496
+ }
497
+ #endif
498
+
442
499
/// <summary>
443
500
/// Specifies the GraphQL server options.
444
501
/// </summary>
@@ -454,7 +511,7 @@ public static BananaCakePopEndpointConventionBuilder MapBananaCakePop(
454
511
/// </returns>
455
512
public static GraphQLEndpointConventionBuilder WithOptions (
456
513
this GraphQLEndpointConventionBuilder builder ,
457
- GraphQLServerOptions serverOptions )
514
+ GraphQLServerOptions serverOptions )
458
515
=> builder
459
516
. WithMetadata ( serverOptions )
460
517
. WithMetadata ( serverOptions . Tool . ToBcpOptions ( ) ) ;
@@ -475,12 +532,13 @@ public static GraphQLEndpointConventionBuilder WithOptions(
475
532
public static GraphQLHttpEndpointConventionBuilder WithOptions (
476
533
this GraphQLHttpEndpointConventionBuilder builder ,
477
534
GraphQLHttpOptions httpOptions ) =>
478
- builder . WithMetadata ( new GraphQLServerOptions
479
- {
480
- AllowedGetOperations = httpOptions . AllowedGetOperations ,
481
- EnableGetRequests = httpOptions . EnableGetRequests ,
482
- EnableMultipartRequests = httpOptions . EnableMultipartRequests ,
483
- } ) ;
535
+ builder . WithMetadata (
536
+ new GraphQLServerOptions
537
+ {
538
+ AllowedGetOperations = httpOptions . AllowedGetOperations ,
539
+ EnableGetRequests = httpOptions . EnableGetRequests ,
540
+ EnableMultipartRequests = httpOptions . EnableMultipartRequests ,
541
+ } ) ;
484
542
485
543
/// <summary>
486
544
/// Specifies the Banana Cake Pop tooling options.
@@ -522,17 +580,18 @@ public static WebSocketEndpointConventionBuilder WithOptions(
522
580
builder . WithMetadata ( new GraphQLServerOptions { Sockets = socketOptions , } ) ;
523
581
524
582
private static IApplicationBuilder UseCancellation ( this IApplicationBuilder builder )
525
- => builder . Use ( next => async context =>
526
- {
527
- try
528
- {
529
- await next ( context ) ;
530
- }
531
- catch ( OperationCanceledException )
583
+ => builder . Use (
584
+ next => async context =>
532
585
{
533
- // we just catch cancellations here and do nothing.
534
- }
535
- } ) ;
586
+ try
587
+ {
588
+ await next ( context ) ;
589
+ }
590
+ catch ( OperationCanceledException )
591
+ {
592
+ // we just catch cancellations here and do nothing.
593
+ }
594
+ } ) ;
536
595
537
596
internal static BananaCakePopOptions ToBcpOptions ( this GraphQLToolOptions options )
538
597
=> new ( )
@@ -549,4 +608,4 @@ internal static BananaCakePopOptions ToBcpOptions(this GraphQLToolOptions option
549
608
GaTrackingId = options . GaTrackingId ,
550
609
DisableTelemetry = options . DisableTelemetry ,
551
610
} ;
552
- }
611
+ }
0 commit comments