@@ -15,42 +15,46 @@ open FsToolkit.ErrorHandling
1515open FSharp.Data .GraphQL .Server
1616open FSharp.Data .GraphQL .Shared
1717
18- type DefaultGraphQLRequestHandler < 'Root > (
19- httpContextAccessor : IHttpContextAccessor,
20- options : IOptionsMonitor< GraphQLOptions< 'Root>>,
21- logger : ILogger< DefaultGraphQLRequestHandler< 'Root>>
22- ) =
18+ type DefaultGraphQLRequestHandler < 'Root >
19+ (
20+ /// The accessor to the current HTTP context
21+ httpContextAccessor : IHttpContextAccessor,
22+ /// The options monitor for GraphQL options
23+ options : IOptionsMonitor< GraphQLOptions< 'Root>>,
24+ /// The logger to log messages
25+ logger : ILogger< DefaultGraphQLRequestHandler< 'Root>>
26+ ) =
2327 inherit GraphQLRequestHandler< 'Root> ( httpContextAccessor, options, logger)
2428
2529/// Provides logic to parse and execute GraphQL request
26- and [<AbstractClass>] GraphQLRequestHandler < 'Root > (
27- httpContextAccessor : IHttpContextAccessor ,
28- options : IOptionsMonitor < GraphQLOptions < 'Root >>,
29- logger : ILogger
30- ) =
30+ and [<AbstractClass>] GraphQLRequestHandler < 'Root >
31+ (
32+ /// The accessor to the current HTTP context
33+ httpContextAccessor : IHttpContextAccessor ,
34+ /// The options monitor for GraphQL options
35+ options : IOptionsMonitor < GraphQLOptions < 'Root >>,
36+ /// The logger to log messages
37+ logger : ILogger
38+ ) =
3139
3240 let ctx = httpContextAccessor.HttpContext
3341
3442 let toResponse { DocumentId = documentId ; Content = content ; Metadata = metadata } =
3543
3644 let serializeIndented value =
3745 let jsonSerializerOptions = options.Get( GraphQLOptions.IndentedOptionsName) .SerializerOptions
38- JsonSerializer.Serialize( value, jsonSerializerOptions)
46+ JsonSerializer.Serialize ( value, jsonSerializerOptions)
3947
4048 match content with
41- | Direct( data, errs) ->
42- logger.LogDebug(
43- $" Produced direct GraphQL response with documentId = '{{documentId}}' and metadata:\n {{metadata}}" ,
44- documentId,
45- metadata
46- )
49+ | Direct ( data, errs) ->
50+ logger.LogDebug ( $" Produced direct GraphQL response with documentId = '{{documentId}}' and metadata:\n {{metadata}}" , documentId, metadata)
4751
4852 if logger.IsEnabled LogLevel.Trace then
49- logger.LogTrace( $" GraphQL response data:\n :{{data}}" , serializeIndented data)
53+ logger.LogTrace ( $" GraphQL response data:\n :{{data}}" , serializeIndented data)
5054
51- GQLResponse.Direct( documentId, data, errs)
52- | Deferred( data, errs, deferred) ->
53- logger.LogDebug(
55+ GQLResponse.Direct ( documentId, data, errs)
56+ | Deferred ( data, errs, deferred) ->
57+ logger.LogDebug (
5458 $" Produced deferred GraphQL response with documentId = '{{documentId}}' and metadata:\n {{metadata}}" ,
5559 documentId,
5660 metadata
@@ -59,97 +63,83 @@ and [<AbstractClass>] GraphQLRequestHandler<'Root> (
5963 if logger.IsEnabled LogLevel.Debug then
6064 deferred
6165 |> Observable.add ( function
62- | DeferredResult( data, path) ->
63- logger.LogDebug(
64- " Produced GraphQL deferred result for path: {path}" ,
65- path |> Seq.map string |> Seq.toArray |> Path.Join
66- )
66+ | DeferredResult ( data, path) ->
67+ logger.LogDebug ( " Produced GraphQL deferred result for path: {path}" , path |> Seq.map string |> Seq.toArray |> Path.Join)
6768
6869 if logger.IsEnabled LogLevel.Trace then
69- logger.LogTrace(
70- $" GraphQL deferred data:\n {{data}}" ,
71- serializeIndented data
72- )
73- | DeferredErrors( null , errors, path) ->
74- logger.LogDebug(
75- " Produced GraphQL deferred errors for path: {path}" ,
76- path |> Seq.map string |> Seq.toArray |> Path.Join
77- )
70+ logger.LogTrace ( $" GraphQL deferred data:\n {{data}}" , serializeIndented data)
71+ | DeferredErrors ( null , errors, path) ->
72+ logger.LogDebug ( " Produced GraphQL deferred errors for path: {path}" , path |> Seq.map string |> Seq.toArray |> Path.Join)
7873
7974 if logger.IsEnabled LogLevel.Trace then
80- logger.LogTrace( $" GraphQL deferred errors:\n {{errors}}" , errors)
81- | DeferredErrors( data, errors, path) ->
82- logger.LogDebug(
75+ logger.LogTrace ( $" GraphQL deferred errors:\n {{errors}}" , errors)
76+ | DeferredErrors ( data, errors, path) ->
77+ logger.LogDebug (
8378 " Produced GraphQL deferred result with errors for path: {path}" ,
8479 path |> Seq.map string |> Seq.toArray |> Path.Join
8580 )
8681
8782 if logger.IsEnabled LogLevel.Trace then
88- logger.LogTrace(
83+ logger.LogTrace (
8984 $" GraphQL deferred errors:\n {{errors}}\n GraphQL deferred data:\n {{data}}" ,
9085 errors,
9186 serializeIndented data
9287 ))
9388
94- GQLResponse.Direct( documentId, data, errs)
89+ GQLResponse.Direct ( documentId, data, errs)
90+
9591 | Stream stream ->
96- logger.LogDebug(
97- $" Produced stream GraphQL response with documentId = '{{documentId}}' and metadata:\n {{metadata}}" ,
98- documentId,
99- metadata
100- )
92+ logger.LogDebug ( $" Produced stream GraphQL response with documentId = '{{documentId}}' and metadata:\n {{metadata}}" , documentId, metadata)
10193
10294 if logger.IsEnabled LogLevel.Debug then
10395 stream
10496 |> Observable.add ( function
10597 | SubscriptionResult data ->
106- logger.LogDebug( " Produced GraphQL subscription result" )
98+ logger.LogDebug ( " Produced GraphQL subscription result" )
10799
108100 if logger.IsEnabled LogLevel.Trace then
109- logger.LogTrace(
110- $" GraphQL subscription data:\n {{data}}" ,
111- serializeIndented data
112- )
113- | SubscriptionErrors( null , errors) ->
114- logger.LogDebug( " Produced GraphQL subscription errors" )
101+ logger.LogTrace ( $" GraphQL subscription data:\n {{data}}" , serializeIndented data)
102+ | SubscriptionErrors ( null , errors) ->
103+ logger.LogDebug ( " Produced GraphQL subscription errors" )
115104
116105 if logger.IsEnabled LogLevel.Trace then
117- logger.LogTrace( $" GraphQL subscription errors:\n {{errors}}" , errors)
118- | SubscriptionErrors( data, errors) ->
119- logger.LogDebug( " Produced GraphQL subscription result with errors" )
106+ logger.LogTrace ( $" GraphQL subscription errors:\n {{errors}}" , errors)
107+ | SubscriptionErrors ( data, errors) ->
108+ logger.LogDebug ( " Produced GraphQL subscription result with errors" )
120109
121110 if logger.IsEnabled LogLevel.Trace then
122- logger.LogTrace(
111+ logger.LogTrace (
123112 $" GraphQL subscription errors:\n {{errors}}\n GraphQL deferred data:\n {{data}}" ,
124113 errors,
125114 serializeIndented data
126115 ))
127116
128117 GQLResponse.Stream documentId
118+
129119 | RequestError errs ->
130- logger.LogWarning(
120+ logger.LogWarning (
131121 $" Produced request error GraphQL response with documentId = '{{documentId}}' and metadata:\n {{metadata}}" ,
132122 documentId,
133123 metadata
134124 )
135125
136- GQLResponse.RequestError( documentId, errs)
126+ GQLResponse.RequestError ( documentId, errs)
137127
138128 /// Checks if the request contains a body
139- let checkIfHasBody ( request : HttpRequest ) = task {
129+ let checkIfHasBody ( request : HttpRequest ) = task {
140130 if request.Body.CanSeek then
141131 return ( request.Body.Length > 0 L)
142132 else
143- request.EnableBuffering()
133+ request.EnableBuffering ()
144134 let body = request.Body
145135 let buffer = Array.zeroCreate 1
146- let! bytesRead = body.ReadAsync( buffer, 0 , 1 )
147- body.Seek( 0 , SeekOrigin.Begin) |> ignore
136+ let! bytesRead = body.ReadAsync ( buffer, 0 , 1 )
137+ body.Seek ( 0 , SeekOrigin.Begin) |> ignore
148138 return bytesRead > 0
149139 }
150140
151141 /// Execute default or custom introspection query
152- let executeIntrospectionQuery ( executor : Executor < _ >) ( ast : Ast.Document voption ) : Task < IResult > = task {
142+ let executeIntrospectionQuery ( executor : Executor < _ >) ( ast : Ast.Document voption ) : Task < IResult > = task {
153143 let! result =
154144 match ast with
155145 | ValueNone -> executor.AsyncExecute IntrospectionQuery.Definition
@@ -166,21 +156,19 @@ and [<AbstractClass>] GraphQLRequestHandler<'Root> (
166156 /// <returns>Result of check of <see cref="OperationType"/></returns>
167157 let checkOperationType () = taskResult {
168158
169- let checkAnonymousFieldsOnly ( ctx : HttpContext ) = taskResult {
170- let! gqlRequest = ctx.TryBindJsonAsync< GQLRequestContent>( GQLRequestContent.expectedJSON)
159+ let checkAnonymousFieldsOnly ( ctx : HttpContext ) = taskResult {
160+ let! gqlRequest = ctx.TryBindJsonAsync< GQLRequestContent> ( GQLRequestContent.expectedJSON)
171161 let! ast = Parser.parseOrIResult ctx.Request.Path.Value gqlRequest.Query
172162 let operationName = gqlRequest.OperationName |> Skippable.toValueOption
173163
174- let createParsedContent () = {
164+ let createParsedContent () = {
175165 Query = gqlRequest.Query
176166 Ast = ast
177167 OperationName = gqlRequest.OperationName
178168 Variables = gqlRequest.Variables
179169 }
180170 if ast.IsEmpty then
181- logger.LogTrace(
182- " Request is not GET, but 'query' field is an empty string. Must be an introspection query"
183- )
171+ logger.LogTrace ( " Request is not GET, but 'query' field is an empty string. Must be an introspection query" )
184172 return IntrospectionQuery <| ValueNone
185173 else
186174 match Ast.tryFindOperationByName operationName ast with
@@ -195,53 +183,52 @@ and [<AbstractClass>] GraphQLRequestHandler<'Root> (
195183 let hasNonMetaFields =
196184 Ast.containsFieldsBeyond
197185 Ast.metaTypeFields
198- ( fun x ->
199- logger.LogTrace( $" Operation Selection in Field with name: {{fieldName}}" , x.Name))
186+ ( fun field -> logger.LogTrace ( $" Operation Selection in Field with name: {{fieldName}}" , field.Name))
200187 ( fun _ -> logger.LogTrace " Operation Selection is non-Field type" )
201188 op
202189
203190 if hasNonMetaFields then
204- return createParsedContent() |> OperationQuery
191+ return createParsedContent () |> OperationQuery
205192 else
206193 return IntrospectionQuery <| ValueSome ast
207194 }
208195
209196 let request = ctx.Request
210197
211198 if HttpMethods.Get = request.Method then
212- logger.LogTrace( " Request is GET. Must be an introspection query" )
199+ logger.LogTrace ( " Request is GET. Must be an introspection query" )
213200 return IntrospectionQuery <| ValueNone
214201 else
215202 let! hasBody = checkIfHasBody request
216203
217204 if not hasBody then
218- logger.LogTrace( " Request is not GET, but has no body. Must be an introspection query" )
205+ logger.LogTrace ( " Request is not GET, but has no body. Must be an introspection query" )
219206 return IntrospectionQuery <| ValueNone
220207 else
221208 return ! checkAnonymousFieldsOnly ctx
222209 }
223210
224- abstract ExecuteOperation <'Root > : executor : Executor <'Root > * content : ParsedGQLQueryRequestContent -> Task < IResult >
211+ abstract ExecuteOperation <'Root > : executor : Executor <'Root > * content : ParsedGQLQueryRequestContent -> Task < IResult >
225212
226213 /// Execute the operation for given request
227- default _.ExecuteOperation < 'Root > ( executor : Executor < 'Root >, content ) = task {
214+ default _.ExecuteOperation < 'Root > ( executor : Executor < 'Root >, content ) = task {
228215
229216 let operationName = content.OperationName |> Skippable.filter ( not << isNull) |> Skippable.toOption
230217 let variables = content.Variables |> Skippable.filter ( not << isNull) |> Skippable.toOption
231218
232219 operationName
233- |> Option.iter ( fun on -> logger.LogTrace( " GraphQL operation name: '{operationName}'" , on))
220+ |> Option.iter ( fun on -> logger.LogTrace ( " GraphQL operation name: '{operationName}'" , on))
234221
235- logger.LogTrace( $" Executing GraphQL query:\n {{query}}" , content.Query)
222+ logger.LogTrace ( $" Executing GraphQL query:\n {{query}}" , content.Query)
236223
237224 variables
238- |> Option.iter ( fun v -> logger.LogTrace( $" GraphQL variables:\n {{variables}}" , v))
225+ |> Option.iter ( fun v -> logger.LogTrace ( $" GraphQL variables:\n {{variables}}" , v))
239226
240227 let root = options.CurrentValue.RootFactory ctx
241228
242229 let! result =
243- Async.StartImmediateAsTask(
244- executor.AsyncExecute( content.Ast, root, ?variables = variables, ?operationName = operationName),
230+ Async.StartImmediateAsTask (
231+ executor.AsyncExecute ( content.Ast, root, ?variables = variables, ?operationName = operationName),
245232 cancellationToken = ctx.RequestAborted
246233 )
247234
0 commit comments