コード例 #1
0
 public static IQueryResult StateInvalidForOperationVariableCoercion() =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage(
         "There is no operation on the context which can be used to coerce " +
         "variables.")
     .Build());
コード例 #2
0
 public static IQueryResult StateInvalidForOperationExecution() =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage(
         "Either now compiled operation was found or the variables " +
         "have not been coerced.")
     .Build());
コード例 #3
0
 public static IQueryResult RootTypeNotFound(OperationType operationType) =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage(
         "The specified root type `{0}` is not supported by this server.",
         operationType)
     .Build());
コード例 #4
0
 public static IQueryResult StateInvalidForOperationResolver() =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage(
         "Either no query document exists or the document " +
         "validation result is invalid.")
     .Build());
コード例 #5
0
        public async Task InvokeAsync(IQueryContext context)
        {
            try
            {
                IHttpClientFactory httpClientFactory =
                    context.Services.GetRequiredService <IHttpClientFactory>();

                context.Result = await _client.FetchAsync(
                    context.Request,
                    httpClientFactory.CreateClient(_schemaName),
                    context.Services.GetServices <IHttpQueryRequestInterceptor>(),
                    context.RequestAborted)
                                 .ConfigureAwait(false);
            }
            catch (HttpRequestException ex)
            {
                IError error = _errorHandler.CreateUnexpectedError(ex)
                               .SetCode(ErrorCodes.HttpRequestException)
                               .Build();

                context.Exception = ex;
                context.Result    = QueryResultBuilder.CreateError(error);
            }

            await _next.Invoke(context).ConfigureAwait(false);
        }
コード例 #6
0
        public async ValueTask InvokeAsync(IRequestContext context)
        {
            if (context.Document is null)
            {
                context.Result = StateInvalidForDocumentValidation();
            }
            else
            {
                if (context.ValidationResult is null)
                {
                    using (_diagnosticEvents.ValidateDocument(context))
                    {
                        context.ValidationResult = _documentValidator.Validate(
                            context.Schema,
                            context.Document,
                            context.ContextData);
                    }
                }

                if (context.ValidationResult is { HasErrors : true } validationResult)
                {
                    context.Result = QueryResultBuilder.CreateError(
                        validationResult.Errors,
                        new Dictionary <string, object?>
                    {
                        { WellKnownContextData.ValidationErrors, true }
                    });
                    _diagnosticEvents.ValidationErrors(context, validationResult.Errors);
                }
コード例 #7
0
        public async ValueTask InvokeAsync(IRequestContext context)
        {
            if (context.Document is null)
            {
                // TODO : ErrorHelper
                context.Result = QueryResultBuilder.CreateError(
                    ErrorBuilder.New()
                    .SetMessage("Cannot Validate")
                    .Build());
            }
            else
            {
                if (context.ValidationResult is null)
                {
                    using (_diagnosticEvents.ValidateDocument(context))
                    {
                        context.ValidationResult =
                            _documentValidator.Validate(context.Schema, context.Document !);
                    }
                }

                if (context.ValidationResult is { HasErrors : true } validationResult)
                {
                    context.Result = QueryResultBuilder.CreateError(validationResult.Errors);
                    _diagnosticEvents.ValidationErrors(context, validationResult.Errors);
                }
コード例 #8
0
 public static Task SerializeAsync(
     this IQueryResultSerializer serializer,
     IExecutionResult result,
     Stream outputStream,
     CancellationToken cancellationToken)
 {
     if (result is IReadOnlyQueryResult queryResult)
     {
         using (queryResult)
         {
             return(serializer.SerializeAsync(
                        queryResult,
                        outputStream,
                        cancellationToken));
         }
     }
     else
     {
         // TODO : resources
         return(serializer.SerializeAsync(
                    QueryResultBuilder.CreateError(
                        ErrorBuilder.New()
                        .SetMessage("Result type not supported.")
                        .SetCode(ErrorCodes.Serialization.ResultTypeNotSupported)
                        .Build()),
                    outputStream,
                    cancellationToken));
     }
 }
コード例 #9
0
        private async Task <IReadOnlyQueryResult> FetchAsync(
            IReadOnlyQueryRequest request,
            HttpContent requestContent,
            HttpClient httpClient,
            IEnumerable <IHttpQueryRequestInterceptor>?interceptors,
            CancellationToken cancellationToken)
        {
            HttpResponseMessage message =
                await FetchInternalAsync(requestContent, httpClient).ConfigureAwait(false);

            using (Stream stream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false))
            {
                object response = await BufferHelper.ReadAsync(
                    stream,
                    (buffer, bytesBuffered) => ParseJson(buffer, bytesBuffered),
                    cancellationToken)
                                  .ConfigureAwait(false);

                IReadOnlyQueryResult queryResult =
                    response is IReadOnlyDictionary <string, object> d
                        ? HttpResponseDeserializer.Deserialize(d)
                        : QueryResultBuilder.CreateError(
                        ErrorBuilder.New()
                        .SetMessage("Could not deserialize query response.")
                        .Build());

                if (interceptors is { })
コード例 #10
0
 public static IQueryResult UnknownSubscriptionError(Exception ex)
 => QueryResultBuilder.CreateError(
     ErrorBuilder
     .New()
     .SetException(ex)
     .SetCode(ErrorCodes.Execution.TaskProcessingError)
     .SetMessage(AspNetCoreResources.Subscription_SendResultsAsync)
     .Build());
コード例 #11
0
 public static IQueryResult OperationKindNotAllowed() =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage("The specified operation kind is not allowed.")
     .Build(),
     new Dictionary <string, object?>
 {
     { WellKnownContextData.OperationNotAllowed, null }
 });
コード例 #12
0
 public static IQueryResult InvalidTypeName(string typeName)
 => QueryResultBuilder.CreateError(
     new Error(
         "The type name is invalid.",
         code: ErrorCodes.Server.InvalidTypeName,
         extensions: new Dictionary <string, object?>
 {
     { "typeName", typeName }
 }));
コード例 #13
0
 public static IQueryResult TypeNotFound(string typeName)
 => QueryResultBuilder.CreateError(
     new Error(
         $"The type `{typeName}` does not exist.",
         code: ErrorCodes.Server.TypeDoesNotExist,
         extensions: new Dictionary <string, object?>
 {
     { "typeName", typeName }
 }));
コード例 #14
0
    private async Task HandleRequestAsync(HttpContext context)
    {
        // first we need to get the request executor to be able to execute requests.
        IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

        IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
        IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

        context.Items[WellKnownContextData.RequestExecutor] = requestExecutor;

        HttpStatusCode?  statusCode = null;
        IExecutionResult?result;

        // next we parse the GraphQL request.
        GraphQLRequest request;

        using (_diagnosticEvents.ParseHttpRequest(context))
        {
            try
            {
                request = _requestParser.ReadParamsRequest(context.Request.Query);
            }
            catch (GraphQLRequestException ex)
            {
                // A GraphQL request exception is thrown if the HTTP request body couldn't be
                // parsed. In this case we will return HTTP status code 400 and return a
                // GraphQL error result.
                statusCode = HttpStatusCode.BadRequest;
                IReadOnlyList <IError> errors = errorHandler.Handle(ex.Errors);
                result = QueryResultBuilder.CreateError(errors);
                _diagnosticEvents.ParserErrors(context, errors);
                goto HANDLE_RESULT;
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
                IError error = errorHandler.CreateUnexpectedError(ex).Build();
                result = QueryResultBuilder.CreateError(error);
                _diagnosticEvents.HttpRequestError(context, error);
                goto HANDLE_RESULT;
            }
        }

        // after successfully parsing the request we now will attempt to execute the request.
        try
        {
            GraphQLServerOptions?options = context.GetGraphQLServerOptions();
            result = await ExecuteSingleAsync(
                context,
                requestExecutor,
                requestInterceptor,
                _diagnosticEvents,
                request,
                options is null or { AllowedGetOperations : AllowedGetOperations.Query }
                ?_onlyQueries
                : null);
        }
コード例 #15
0
            private async Task <IQueryResult> ExecuteNextAsync(
                IReadOnlyQueryRequest request,
                CancellationToken cancellationToken)
            {
                try
                {
                    DocumentNode document = request.Query is QueryDocument d
                        ? d.Document
                        : Utf8GraphQLParser.Parse(request.Query !.AsSpan());

                    OperationDefinitionNode operation =
                        document.GetOperation(request.OperationName);

                    if (document != _previous)
                    {
                        _fragments = document.GetFragments();
                        _visitationMap.Initialize(_fragments);
                    }

                    operation.Accept(
                        _visitor,
                        _visitationMap,
                        n => VisitorAction.Continue);

                    _previous = document;
                    document  = RewriteDocument(operation);
                    operation = (OperationDefinitionNode)document.Definitions[0];
                    IReadOnlyDictionary <string, object?>?variableValues =
                        MergeVariables(request.VariableValues, operation);

                    request = QueryRequestBuilder.From(request)
                              .SetQuery(document)
                              .SetVariableValues(variableValues)
                              .AddExportedVariables(_exportedVariables)
                              .SetQueryName(null) // TODO ... should we create a name here?
                              .SetQueryHash(null)
                              .Create();

                    return((IReadOnlyQueryResult)await _requestExecutor.ExecuteAsync(
                               request, cancellationToken)
                           .ConfigureAwait(false));
                }
                catch (GraphQLException ex)
                {
                    return(QueryResultBuilder.CreateError(ex.Errors));
                }
                catch (Exception ex)
                {
                    return(QueryResultBuilder.CreateError(
                               _errorHandler.Handle(
                                   _errorHandler.CreateUnexpectedError(ex).Build())));
                }
            }
コード例 #16
0
 public static IQueryResult MaxComplexityReached(
     int complexity,
     int allowedComplexity) =>
 QueryResultBuilder.CreateError(
     new Error(
         ErrorHelper_MaxComplexityReached,
         ErrorCodes.Execution.ComplexityExceeded,
         extensions: new Dictionary <string, object?>
 {
     { nameof(complexity), complexity },
     { nameof(allowedComplexity), allowedComplexity }
 }));
コード例 #17
0
        private async Task SendResultsAsync()
        {
            try
            {
                await foreach (IQueryResult result in
                               _responseStream.ReadResultsAsync().WithCancellation(_cts.Token))
                {
                    using (result)
                    {
                        await _connection.SendAsync(new DataResultMessage(Id, result), _cts.Token);
                    }
                }

                if (!_cts.IsCancellationRequested)
                {
                    await _connection.SendAsync(new DataCompleteMessage(Id), _cts.Token);

                    Completed?.Invoke(this, EventArgs.Empty);
                }
            }
            catch (OperationCanceledException) { }
            catch (ObjectDisposedException) { }
            catch (Exception ex)
            {
                if (!_cts.IsCancellationRequested)
                {
                    IError error =
                        ErrorBuilder
                        .New()
                        .SetException(ex)
                        .SetCode(ErrorCodes.Execution.TaskProcessingError)
                        .SetMessage("Unexpected Execution Error")
                        .Build();

                    IQueryResult result = QueryResultBuilder.CreateError(error);
                    try
                    {
                        await _connection.SendAsync(new DataResultMessage(Id, result), _cts.Token);
                    }
                    finally
                    {
                        await _connection.SendAsync(new DataCompleteMessage(Id), _cts.Token);

                        Completed?.Invoke(this, EventArgs.Empty);
                    }
                }
            }
            finally
            {
                Dispose();
            }
        }
        /// <summary>
        /// Execute the current HttpContext provided using HotChocolate GraphQL and the currently configured pipeline.
        /// ALL parsing, and processing of the Query of the request will be handled by existing HotChoclate HttpPost & HttpGet
        /// middleware, this class will only proxy the context into HC for execution, and handle unexpected errors.
        /// NOTE: An EmptyResult() response is returned because that is what must be returned by the AzureFunction; because HotChocolate
        ///     has already processed the request and started the response (e.g. StatusCode will be set by HC) an EmptyResult() response
        ///     will prevent the Azure Functions framework from attempting to set it again resulting in a a Host error/crash.
        /// </summary>
        /// <param name="httpContext"></param>
        /// <param name="logger"></param>
        /// <param name="cancellationToken"></param>
        /// <returns>
        /// Returns an EmptyResult() response because HotChocolate has already processed the request and started the response
        /// (e.g. StatusCode will be set by HC) and an EmptyResult() response will prevent the Azure Functions framework from
        /// attempting to set it again resulting in a a Host error/crash.
        /// </returns>
        public async Task <IActionResult> ExecuteFunctionsQueryAsync(HttpContext httpContext, ILogger logger, CancellationToken cancellationToken)
        {
            try
            {
                //Use the Middleware Proxy to Invoke the pre-configured pipeline for Http POST & GET processing...
                var httpMiddlewareProxy = this.AzureFunctionsMiddlewareProxy;
                await httpMiddlewareProxy.InvokeAsync(httpContext).ConfigureAwait(false);
            }
            //NOTE: We Implement error handling that matches the Existing HttpPostMiddleware, to ensure that all code
            //  has top level error handling for Graph processing.
            catch (GraphQLRequestException ex)
            {
                //If Debugging is enabled then Log the Errors to AzureFunctions framework (e.g. Application Insights)
                logger.LogDebug(ex, $"{nameof(GraphQLRequestException)} occurred while processing the GraphQL request; {ex.Message}.");

                // A GraphQL request exception is thrown if the HTTP request body couldn't be parsed.
                // In this case we will return HTTP status code 400 and return a GraphQL error result.
                IErrorHandler errorHandler = await this.AzureFunctionsMiddlewareProxy.GetErrorHandlerAsync(cancellationToken).ConfigureAwait(false);

                IQueryResult errorResult = QueryResultBuilder.CreateError(errorHandler.Handle(ex.Errors));

                await HandleGraphQLErrorResponseAsync(httpContext, HttpStatusCode.BadRequest, errorResult);
            }
            catch (Exception exc)
            {
                //Log all Unknown Exceptions as GraphQLExceptions to Azure Framework (e.g. Application Insights).
                logger.LogError(exc, "An unhandled exception occurred while processing the GraphQL request.");

                // An unknown and unexpected GraphQL request exception was encountered.
                // In this case we will return HTTP status code 500 and return a GraphQL error result.
                IErrorHandler errorHandler = await this.AzureFunctionsMiddlewareProxy.GetErrorHandlerAsync(cancellationToken).ConfigureAwait(false);

                IError       error       = errorHandler.CreateUnexpectedError(exc).Build();
                IQueryResult errorResult = QueryResultBuilder.CreateError(error);

                HttpStatusCode statusCode = exc is HttpRequestException
                    ? HttpStatusCode.BadRequest
                    : HttpStatusCode.InternalServerError;

                await HandleGraphQLErrorResponseAsync(httpContext, statusCode, errorResult).ConfigureAwait(false);
            }

            //Safely resolve the .Net Core request with Empty Result because the Response has already been handled!
            //NOTE: We Must return EmptyResult() so that No Action is taken on the Response or else an error will occur
            //      since HotChocolate has ALREADY started (e.g. processed) the response, and the Status Code is already set!
            //For More Info See: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.emptyresult?view=aspnetcore-5.0
            return(new EmptyResult());
        }
コード例 #19
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task InvokeAsync(HttpContext context)
        {
            if (_isPathValid(context) && CanHandleRequest(context))
            {
                try
                {
                    await HandleRequestAsync(context)
                    .ConfigureAwait(false);
                }
                catch (ArgumentException)
                {
                    context.Response.StatusCode = _badRequest;
                }
                catch (NotSupportedException)
                {
                    context.Response.StatusCode = _badRequest;
                }
                catch (SyntaxException ex)
                {
                    IError error = ErrorBuilder.New()
                                   .SetMessage(ex.Message)
                                   .AddLocation(ex.Line, ex.Column)
                                   .SetCode(ErrorCodes.Execution.SyntaxError)
                                   .Build();
                    ErrorHandler.Handle(error);

                    var errorResult = QueryResultBuilder.CreateError(error);

                    SetResponseHeaders(context.Response, _serializer.ContentType);
                    await _serializer.SerializeAsync(errorResult, context.Response.Body)
                    .ConfigureAwait(false);
                }
                catch (QueryException ex)
                {
                    var errorResult = QueryResultBuilder.CreateError(
                        ErrorHandler.Handle(ex.Errors));
                    SetResponseHeaders(context.Response, _serializer.ContentType);
                    await _serializer.SerializeAsync(errorResult, context.Response.Body)
                    .ConfigureAwait(false);
                }
            }
            else if (Next != null)
            {
                await Next.Invoke(context).ConfigureAwait(false);
            }
        }
コード例 #20
0
 public async ValueTask InvokeAsync(IRequestContext context)
 {
     try
     {
         await _next(context).ConfigureAwait(false);
     }
     catch (GraphQLException ex)
     {
         context.Exception = ex;
         context.Result    = QueryResultBuilder.CreateError(_errorHandler.Handle(ex.Errors));
     }
     catch (Exception ex)
     {
         context.Exception = ex;
         IError error = _errorHandler.CreateUnexpectedError(ex).Build();
         context.Result = QueryResultBuilder.CreateError(_errorHandler.Handle(error));
     }
 }
コード例 #21
0
        public async ValueTask InvokeAsync(IRequestContext context)
        {
            if (context.Document is null && context.Request.Query is not null)
            {
                var success = true;

                try
                {
                    using (_diagnosticEvents.ParseDocument(context))
                    {
                        context.DocumentId = ComputeDocumentHash(
                            context.DocumentHash,
                            context.Request.QueryHash,
                            context.Request.Query);
                        context.Document = ParseDocument(context.Request.Query);
                    }
                }
                catch (SyntaxException ex)
                {
                    success = false;

                    IError error = context.ErrorHandler.Handle(
                        ErrorBuilder.New()
                        .SetMessage(ex.Message)
                        .SetCode(ErrorCodes.Execution.SyntaxError)
                        .AddLocation(ex.Line, ex.Column)
                        .Build());

                    context.Exception = ex;
                    context.Result    = QueryResultBuilder.CreateError(error);

                    _diagnosticEvents.SyntaxError(context, error);
                }

                if (success)
                {
                    await _next(context).ConfigureAwait(false);
                }
            }
コード例 #22
0
        private async Task HandleRequestAsync(HttpContext context)
        {
            // first we need to get the request executor to be able to execute requests.
            IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

            IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
            IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

            HttpStatusCode?  statusCode = null;
            IExecutionResult?result;

            try
            {
                // next we parse the GraphQL request.
                GraphQLRequest request = _requestParser.ReadParamsRequest(context.Request.Query);
                result = await ExecuteSingleAsync(
                    context, requestExecutor, requestInterceptor, request);
            }
            catch (GraphQLRequestException ex)
            {
                // A GraphQL request exception is thrown if the HTTP request body couldn't be
                // parsed. In this case we will return HTTP status code 400 and return a
                // GraphQL error result.
                statusCode = HttpStatusCode.BadRequest;
                result     = QueryResultBuilder.CreateError(errorHandler.Handle(ex.Errors));
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
                IError error = errorHandler.CreateUnexpectedError(ex).Build();
                result = QueryResultBuilder.CreateError(error);
            }

            // in any case we will have a valid GraphQL result at this point that can be written
            // to the HTTP response stream.
            Debug.Assert(result is not null, "No GraphQL result was created.");
            await WriteResultAsync(context.Response, result, statusCode, context.RequestAborted);
        }
コード例 #23
0
        public async ValueTask InvokeAsync(IRequestContext context)
        {
            if (context.Document is null)
            {
                context.Result = StateInvalidForDocumentValidation();
            }
            else
            {
                using (_diagnosticEvents.ValidateDocument(context))
                {
                    context.ValidationResult = _documentValidator.Validate(
                        context.Schema,
                        context.Document,
                        context.ContextData,
                        context.ValidationResult is not null);
                }

                if (context.IsValidDocument)
                {
                    await _next(context).ConfigureAwait(false);
                }
                else
                {
                    DocumentValidatorResult validationResult = context.ValidationResult;

                    context.Result = QueryResultBuilder.CreateError(
                        validationResult.Errors,
                        new Dictionary <string, object?>
                    {
                        { WellKnownContextData.ValidationErrors, true }
                    });

                    _diagnosticEvents.ValidationErrors(context, validationResult.Errors);
                }
            }
        }
コード例 #24
0
 public static IQueryResult StateInvalidForDocumentValidation() =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage("The query request contains no document.")
     .SetCode(ErrorCodes.Execution.QueryNotFound)
     .Build());
コード例 #25
0
        private async Task HandleRequestAsync(
            HttpContext context,
            AllowedContentType contentType)
        {
            // first we need to get the request executor to be able to execute requests.
            IRequestExecutor requestExecutor = await GetExecutorAsync(context.RequestAborted);

            IHttpRequestInterceptor requestInterceptor = requestExecutor.GetRequestInterceptor();
            IErrorHandler           errorHandler       = requestExecutor.GetErrorHandler();

            HttpStatusCode?  statusCode = null;
            IExecutionResult?result;

            try
            {
                // next we parse the GraphQL request.
                IReadOnlyList <GraphQLRequest> requests =
                    await _requestParser.ReadJsonRequestAsync(
                        context.Request.Body, context.RequestAborted);

                switch (requests.Count)
                {
                // if the HTTP request body contains no GraphQL request structure the
                // whole request is invalid and we will create a GraphQL error response.
                case 0:
                {
                    statusCode = HttpStatusCode.BadRequest;
                    IError error = errorHandler.Handle(ErrorHelper.RequestHasNoElements());
                    result = QueryResultBuilder.CreateError(error);
                    break;
                }

                // if the HTTP request body contains a single GraphQL request and we do have
                // the batch operations query parameter specified we need to execute an
                // operation batch.
                //
                // An operation batch consists of a single GraphQL request document that
                // contains multiple operations. The batch operation query parameter
                // defines the order in which the operations shall be executed.
                case 1 when context.Request.Query.ContainsKey(_batchOperations):
                {
                    string operationNames = context.Request.Query[_batchOperations];

                    if (TryParseOperations(operationNames, out IReadOnlyList <string>?ops))
                    {
                        result = await ExecuteOperationBatchAsync(
                            context, requestExecutor, requestInterceptor, requests[0], ops);
                    }
                    else
                    {
                        IError error = errorHandler.Handle(ErrorHelper.InvalidRequest());
                        statusCode = HttpStatusCode.BadRequest;
                        result     = QueryResultBuilder.CreateError(error);
                    }
                    break;
                }

                // if the HTTP request body contains a single GraphQL request and
                // no batch query parameter is specified we need to execute a single
                // GraphQL request.
                //
                // Most GraphQL requests will be of this type where we want to execute
                // a single GraphQL query or mutation.
                case 1:
                {
                    result = await ExecuteSingleAsync(
                        context, requestExecutor, requestInterceptor, requests[0]);

                    break;
                }

                // if the HTTP request body contains more than one GraphQL request than
                // we need to execute a request batch where we need to execute multiple
                // fully specified GraphQL requests at once.
                default:
                    result = await ExecuteBatchAsync(
                        context, requestExecutor, requestInterceptor, requests);

                    break;
                }
            }
            catch (GraphQLRequestException ex)
            {
                // A GraphQL request exception is thrown if the HTTP request body couldn't be
                // parsed. In this case we will return HTTP status code 400 and return a
                // GraphQL error result.
                statusCode = HttpStatusCode.BadRequest;
                result     = QueryResultBuilder.CreateError(errorHandler.Handle(ex.Errors));
            }
            catch (Exception ex)
            {
                statusCode = HttpStatusCode.InternalServerError;
                IError error = errorHandler.CreateUnexpectedError(ex).Build();
                result = QueryResultBuilder.CreateError(error);
            }

            // in any case we will have a valid GraphQL result at this point that can be written
            // to the HTTP response stream.
            Debug.Assert(result is not null, "No GraphQL result was created.");
            await WriteResultAsync(context.Response, result, statusCode, context.RequestAborted);
        }
コード例 #26
0
    protected override async Task HandleAsync(
        ISocketConnection connection,
        DataStartMessage message,
        CancellationToken cancellationToken)
    {
        var session  = new CancellationTokenSource();
        var combined = CancellationTokenSource.CreateLinkedTokenSource(
            session.Token, cancellationToken);
        var sessionIsHandled = false;

        IExecutionResult result = await ExecuteAsync(combined.Token);

        try
        {
            switch (result)
            {
            case SubscriptionResult subscriptionResult:
                // first we add the cts to the result so that they are disposed when the
                // subscription is disposed.
                subscriptionResult.RegisterDisposable(combined);

                // while a subscription result must be disposed we are not handling it here
                // and leave this responsibility to the subscription session.
                ISubscription subscription = GetSubscription(result);

                var subscriptionSession = new SubscriptionSession(
                    session,
                    _socketSessionInterceptor,
                    connection,
                    subscriptionResult,
                    subscription,
                    _diagnosticEvents,
                    message.Id);

                connection.Subscriptions.Register(subscriptionSession);
                sessionIsHandled = true;
                break;

            case IResponseStream streamResult:
                // stream results represent deferred execution streams that use execution
                // resources. We need to ensure that these are disposed when we are
                // finished.
                await using (streamResult)
                {
                    await HandleStreamResultAsync(
                        connection,
                        message,
                        streamResult,
                        cancellationToken);
                }

                break;

            case IQueryResult queryResult:
                // query results use pooled memory an need to be disposed after we have
                // used them.
                using (queryResult)
                {
                    await HandleQueryResultAsync(
                        connection,
                        message,
                        queryResult,
                        cancellationToken);
                }

                break;

            default:
                throw DataStartMessageHandler_RequestTypeNotSupported();
            }
        }
        finally
        {
            if (!sessionIsHandled)
            {
                session.Dispose();
                combined.Dispose();
            }
        }

        async ValueTask <IExecutionResult> ExecuteAsync(CancellationToken cancellationToken)
        {
            try
            {
                IQueryRequestBuilder requestBuilder =
                    QueryRequestBuilder.From(message.Payload)
                    .SetServices(connection.RequestServices);

                await _socketSessionInterceptor.OnRequestAsync(
                    connection, requestBuilder, cancellationToken);

                return(await _requestExecutor.ExecuteAsync(
                           requestBuilder.Create(), cancellationToken));
            }
            catch (Exception ex)
            {
                IErrorBuilder error = _errorHandler.CreateUnexpectedError(ex);
                return(QueryResultBuilder.CreateError(error.Build()));
            }
        }
    }
コード例 #27
0
 public static IQueryResult ResponseTypeNotSupported() =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage("The response type is not supported.")
     .Build());
コード例 #28
0
 public static IQueryResult ParserExpectedQuery() =>
 QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage("The parse query middleware expects a valid query request.")
     .SetCode(ErrorCodes.Execution.Incomplete)
     .Build());
コード例 #29
0
 public static IQueryResult TypeNameIsEmpty()
 => QueryResultBuilder.CreateError(
     new Error(
         "The specified types argument is empty.",
         code: ErrorCodes.Server.TypeParameterIsEmpty));
コード例 #30
0
 public static IQueryResult ResponseTypeNotSupported()
 => QueryResultBuilder.CreateError(
     ErrorBuilder.New()
     .SetMessage(AspNetCoreResources.ErrorHelper_ResponseTypeNotSupported)
     .Build());