Skip to content

Commit e475f15

Browse files
authored
Fixed ability to override GraphQLRequestHandler<'Root> (#495)
1 parent f42e3d7 commit e475f15

File tree

2 files changed

+148
-14
lines changed

2 files changed

+148
-14
lines changed

src/FSharp.Data.GraphQL.Server.AspNetCore/GraphQLRequestHandler.fs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,18 @@ open FsToolkit.ErrorHandling
1414

1515
open FSharp.Data.GraphQL.Server
1616

17+
type DefaultGraphQLRequestHandler<'Root> (
18+
httpContextAccessor : IHttpContextAccessor,
19+
options : IOptionsMonitor<GraphQLOptions<'Root>>,
20+
logger : ILogger<DefaultGraphQLRequestHandler<'Root>>
21+
) =
22+
inherit GraphQLRequestHandler<'Root> (httpContextAccessor, options, logger)
23+
1724
/// Provides logic to parse and execute GraphQL request
18-
type GraphQLRequestHandler<'Root> (
25+
and [<AbstractClass>] GraphQLRequestHandler<'Root> (
1926
httpContextAccessor : IHttpContextAccessor,
2027
options : IOptionsMonitor<GraphQLOptions<'Root>>,
21-
logger : ILogger<GraphQLRequestHandler<'Root>>
28+
logger : ILogger
2229
) =
2330

2431
let ctx = httpContextAccessor.HttpContext
@@ -213,10 +220,10 @@ type GraphQLRequestHandler<'Root> (
213220
return! checkAnonymousFieldsOnly ctx
214221
}
215222

216-
abstract ExecuteOperation<'Root> : Executor<'Root> -> ParsedGQLQueryRequestContent -> Task<IResult>
223+
abstract ExecuteOperation<'Root> : executor:Executor<'Root> * content:ParsedGQLQueryRequestContent -> Task<IResult>
217224

218225
/// Execute the operation for given request
219-
default _.ExecuteOperation<'Root> (executor: Executor<'Root>) content = task {
226+
default _.ExecuteOperation<'Root> (executor: Executor<'Root>, content) = task {
220227

221228
let operationName = content.OperationName |> Skippable.filter (not << isNull) |> Skippable.toOption
222229
let variables = content.Variables |> Skippable.filter (not << isNull) |> Skippable.toOption
@@ -241,12 +248,12 @@ type GraphQLRequestHandler<'Root> (
241248
return (TypedResults.Ok response) :> IResult
242249
}
243250

244-
member request.HandleAsync () : Task<Result<IResult, IResult>> = taskResult {
251+
member handler.HandleAsync () : Task<Result<IResult, IResult>> = taskResult {
245252
if ctx.RequestAborted.IsCancellationRequested then
246253
return TypedResults.Empty
247254
else
248255
let executor = options.CurrentValue.SchemaExecutor
249256
match! checkOperationType () with
250257
| IntrospectionQuery optionalAstDocument -> return! executeIntrospectionQuery executor optionalAstDocument
251-
| OperationQuery content -> return! request.ExecuteOperation executor content
258+
| OperationQuery content -> return! handler.ExecuteOperation (executor, content)
252259
}

src/FSharp.Data.GraphQL.Server.AspNetCore/StartupExtensions.fs

Lines changed: 135 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module ServiceCollectionExtensions =
4040
/// </para>
4141
/// </summary>
4242
[<Extension; CompiledName "AddGraphQL">]
43-
member internal services.AddGraphQL<'Root>
43+
member internal services.AddGraphQL<'Root, 'Handler when 'Handler :> GraphQLRequestHandler<'Root> and 'Handler : not struct>
4444
(
4545
executorFactory : Func<IServiceProvider, Executor<'Root>>,
4646
rootFactory : HttpContext -> 'Root,
@@ -84,7 +84,41 @@ module ServiceCollectionExtensions =
8484
}
8585
)
8686
.AddHttpContextAccessor()
87-
.AddScoped<GraphQLRequestHandler<'Root>>()
87+
.AddScoped<GraphQLRequestHandler<'Root>, 'Handler>()
88+
89+
/// <summary>
90+
/// Adds GraphQL options and services to the service collection.
91+
/// <para>
92+
/// It also adds converters to <see href="Microsoft.AspNetCore.Http.Json.JsonOptions" />
93+
/// to support serialization of GraphQL responses.
94+
/// </para>
95+
/// </summary>
96+
[<Extension; CompiledName "AddGraphQL">]
97+
member internal services.AddGraphQL<'Root>
98+
(
99+
executorFactory : Func<IServiceProvider, Executor<'Root>>,
100+
rootFactory : HttpContext -> 'Root,
101+
[<Optional>] additionalConverters : JsonConverter seq,
102+
[<Optional; DefaultParameterValue (GraphQLOptionsDefaults.WebSocketEndpoint)>] webSocketEndpointUrl : string,
103+
[<Optional>] configure : Func<GraphQLOptions<'Root>, GraphQLOptions<'Root>>
104+
) =
105+
services.AddGraphQL<'Root, DefaultGraphQLRequestHandler<'Root>> (executorFactory, rootFactory, additionalConverters, webSocketEndpointUrl, configure)
106+
107+
/// <summary>
108+
/// Adds GraphQL options and services to the service collection. Requires an executor instance to be provided.
109+
/// <para>
110+
/// It also adds converters to <see href="Microsoft.AspNetCore.Http.Json.JsonOptions" />
111+
/// to support serialization of GraphQL responses.
112+
/// </para>
113+
/// </summary>
114+
[<Extension; CompiledName "AddGraphQL">]
115+
member services.AddGraphQL<'Root, 'Handler when 'Handler :> GraphQLRequestHandler<'Root> and 'Handler : not struct>
116+
(
117+
executor : Executor<'Root>,
118+
rootFactory : HttpContext -> 'Root,
119+
[<Optional>] additionalConverters : JsonConverter seq
120+
) =
121+
services.AddGraphQL<'Root, 'Handler> ((fun _ -> executor), rootFactory, additionalConverters, null, null)
88122

89123
/// <summary>
90124
/// Adds GraphQL options and services to the service collection. Requires an executor instance to be provided.
@@ -100,7 +134,24 @@ module ServiceCollectionExtensions =
100134
rootFactory : HttpContext -> 'Root,
101135
[<Optional>] additionalConverters : JsonConverter seq
102136
) =
103-
services.AddGraphQL ((fun _ -> executor), rootFactory, additionalConverters, null, null)
137+
services.AddGraphQL<'Root> ((fun _ -> executor), rootFactory, additionalConverters, null, null)
138+
139+
/// <summary>
140+
/// Adds GraphQL options and services to the service collection. Requires an executor instance to be provided.
141+
/// <para>
142+
/// It also adds converters to <see href="Microsoft.AspNetCore.Http.Json.JsonOptions" />
143+
/// to support serialization of GraphQL responses.
144+
/// </para>
145+
/// </summary>
146+
[<Extension; CompiledName "AddGraphQL">]
147+
member services.AddGraphQL<'Root, 'Handler when 'Handler :> GraphQLRequestHandler<'Root> and 'Handler : not struct>
148+
(
149+
executor : Executor<'Root>,
150+
rootFactory : HttpContext -> 'Root,
151+
webSocketEndpointUrl : string,
152+
[<Optional>] additionalConverters : JsonConverter seq
153+
) =
154+
services.AddGraphQL<'Root, 'Handler> ((fun _ -> executor), rootFactory, additionalConverters, webSocketEndpointUrl, null)
104155

105156
/// <summary>
106157
/// Adds GraphQL options and services to the service collection. Requires an executor instance to be provided.
@@ -117,7 +168,24 @@ module ServiceCollectionExtensions =
117168
webSocketEndpointUrl : string,
118169
[<Optional>] additionalConverters : JsonConverter seq
119170
) =
120-
services.AddGraphQL ((fun _ -> executor), rootFactory, additionalConverters, webSocketEndpointUrl, null)
171+
services.AddGraphQL<'Root> ((fun _ -> executor), rootFactory, additionalConverters, webSocketEndpointUrl, null)
172+
173+
/// <summary>
174+
/// Adds GraphQL options and services to the service collection. Requires an executor instance to be provided.
175+
/// <para>
176+
/// It also adds converters to <see href="Microsoft.AspNetCore.Http.Json.JsonOptions" />
177+
/// to support serialization of GraphQL responses.
178+
/// </para>
179+
/// </summary>
180+
[<Extension; CompiledName "AddGraphQL">]
181+
member services.AddGraphQL<'Root, 'Handler when 'Handler :> GraphQLRequestHandler<'Root> and 'Handler : not struct>
182+
(
183+
executor : Executor<'Root>,
184+
rootFactory : HttpContext -> 'Root,
185+
configure : Func<GraphQLOptions<'Root>, GraphQLOptions<'Root>>,
186+
[<Optional>] additionalConverters : JsonConverter seq
187+
) =
188+
services.AddGraphQL<'Root, 'Handler> ((fun _ -> executor), rootFactory, additionalConverters, null, configure)
121189

122190
/// <summary>
123191
/// Adds GraphQL options and services to the service collection. Requires an executor instance to be provided.
@@ -134,7 +202,26 @@ module ServiceCollectionExtensions =
134202
configure : Func<GraphQLOptions<'Root>, GraphQLOptions<'Root>>,
135203
[<Optional>] additionalConverters : JsonConverter seq
136204
) =
137-
services.AddGraphQL ((fun _ -> executor), rootFactory, additionalConverters, null, configure)
205+
services.AddGraphQL<'Root> ((fun _ -> executor), rootFactory, additionalConverters, null, configure)
206+
207+
/// <summary>
208+
/// Adds GraphQL options and services to the service collection. It gets the executor from the service provider.
209+
/// <para>
210+
/// It also adds converters to <see href="Microsoft.AspNetCore.Http.Json.JsonOptions" />
211+
/// to support serialization of GraphQL responses.
212+
/// </para>
213+
/// </summary>
214+
/// <remarks>
215+
/// The executor must be registered as a singleton service.
216+
/// </remarks>
217+
[<Extension; CompiledName "AddGraphQL">]
218+
member services.AddGraphQL<'Root, 'Handler when 'Handler :> GraphQLRequestHandler<'Root> and 'Handler : not struct>
219+
(
220+
rootFactory : HttpContext -> 'Root,
221+
[<Optional>] additionalConverters : JsonConverter seq
222+
) =
223+
let getExecutorService (sp : IServiceProvider) = sp.GetRequiredService<Executor<'Root>>()
224+
services.AddGraphQL<'Root, 'Handler> (getExecutorService, rootFactory, additionalConverters, null, null)
138225

139226
/// <summary>
140227
/// Adds GraphQL options and services to the service collection. It gets the executor from the service provider.
@@ -153,7 +240,27 @@ module ServiceCollectionExtensions =
153240
[<Optional>] additionalConverters : JsonConverter seq
154241
) =
155242
let getExecutorService (sp : IServiceProvider) = sp.GetRequiredService<Executor<'Root>>()
156-
services.AddGraphQL (getExecutorService, rootFactory, additionalConverters, null, null)
243+
services.AddGraphQL<'Root> (getExecutorService, rootFactory, additionalConverters, null, null)
244+
245+
/// <summary>
246+
/// Adds GraphQL options and services to the service collection. It gets the executor from the service provider.
247+
/// <para>
248+
/// It also adds converters to <see href="Microsoft.AspNetCore.Http.Json.JsonOptions" />
249+
/// to support serialization of GraphQL responses.
250+
/// </para>
251+
/// </summary>
252+
/// <remarks>
253+
/// The executor must be registered as a singleton service.
254+
/// </remarks>
255+
[<Extension; CompiledName "AddGraphQL">]
256+
member services.AddGraphQL<'Root, 'Handler when 'Handler :> GraphQLRequestHandler<'Root> and 'Handler : not struct>
257+
(
258+
rootFactory : HttpContext -> 'Root,
259+
[<Optional; DefaultParameterValue (GraphQLOptionsDefaults.WebSocketEndpoint)>] webSocketEndpointUrl : string,
260+
[<Optional>] additionalConverters : JsonConverter seq
261+
) =
262+
let getExecutorService (sp : IServiceProvider) = sp.GetRequiredService<Executor<'Root>>()
263+
services.AddGraphQL<'Root, 'Handler> (getExecutorService, rootFactory, additionalConverters, webSocketEndpointUrl, null)
157264

158265
/// <summary>
159266
/// Adds GraphQL options and services to the service collection. It gets the executor from the service provider.
@@ -173,7 +280,27 @@ module ServiceCollectionExtensions =
173280
[<Optional>] additionalConverters : JsonConverter seq
174281
) =
175282
let getExecutorService (sp : IServiceProvider) = sp.GetRequiredService<Executor<'Root>>()
176-
services.AddGraphQL (getExecutorService, rootFactory, additionalConverters, webSocketEndpointUrl, null)
283+
services.AddGraphQL<'Root> (getExecutorService, rootFactory, additionalConverters, webSocketEndpointUrl, null)
284+
285+
/// <summary>
286+
/// Adds GraphQL options and services to the service collection. It gets the executor from the service provider.
287+
/// <para>
288+
/// It also adds converters to <see href="Microsoft.AspNetCore.Http.Json.JsonOptions" />
289+
/// to support serialization of GraphQL responses.
290+
/// </para>
291+
/// </summary>
292+
/// <remarks>
293+
/// The executor must be registered as a singleton service.
294+
/// </remarks>
295+
[<Extension; CompiledName "AddGraphQL">]
296+
member services.AddGraphQL<'Root, 'Handler when 'Handler :> GraphQLRequestHandler<'Root> and 'Handler : not struct>
297+
(
298+
rootFactory : HttpContext -> 'Root,
299+
configure : Func<GraphQLOptions<'Root>, GraphQLOptions<'Root>>,
300+
[<Optional>] additionalConverters : JsonConverter seq
301+
) =
302+
let getExecutorService (sp : IServiceProvider) = sp.GetRequiredService<Executor<'Root>>()
303+
services.AddGraphQL<'Root, 'Handler> (getExecutorService, rootFactory, additionalConverters, null, configure)
177304

178305
/// <summary>
179306
/// Adds GraphQL options and services to the service collection. It gets the executor from the service provider.
@@ -193,7 +320,7 @@ module ServiceCollectionExtensions =
193320
[<Optional>] additionalConverters : JsonConverter seq
194321
) =
195322
let getExecutorService (sp : IServiceProvider) = sp.GetRequiredService<Executor<'Root>>()
196-
services.AddGraphQL (getExecutorService, rootFactory, additionalConverters, null, configure)
323+
services.AddGraphQL<'Root> (getExecutorService, rootFactory, additionalConverters, null, configure)
197324

198325

199326
[<AutoOpen; Extension>]

0 commit comments

Comments
 (0)