public GraphQLAzureFunctionsMiddlewareProxy( IRequestExecutorResolver graphqlExecutorResolver, IHttpResultSerializer graphqlResultSerializer, IHttpRequestParser graphqlRequestParser, NameString schemaName = default ) { //We support multiple schemas by allowing a name to be specified, but default to DefaultName if not. this.SchemaName = schemaName.HasValue ? schemaName : Schema.DefaultName; //Validate Dependencies... this.ExecutorResolver = graphqlExecutorResolver ?? throw new ArgumentNullException(nameof(graphqlExecutorResolver), GRAPHQL_MIDDLEWARE_INIT_ERROR); this.ResultSerializer = graphqlResultSerializer ?? throw new ArgumentNullException(nameof(graphqlResultSerializer), GRAPHQL_MIDDLEWARE_INIT_ERROR); this.RequestParser = graphqlRequestParser ?? throw new ArgumentNullException(nameof(graphqlRequestParser), GRAPHQL_MIDDLEWARE_INIT_ERROR); //BBernard - Initialize the middleware proxy and pipeline with support for both Http GET & POST processing... //NOTE: Middleware uses the Pipeline Pattern (similar to Chain Of Responsibility), therefore // we adapt that here to manually build up the two key middleware handlers for Http Get & Http Post processing. var httpGetMiddlewareShim = new HttpGetMiddleware( (httpContext) => throw new HttpRequestException( "GraphQL was unable to process the request, ensure that an Http POST or GET GraphQL request was sent as well-formed Json." ), this.ExecutorResolver, this.ResultSerializer, this.RequestParser, this.SchemaName ); ////NOTE: The normal use case for GraphQL is POST'ing of the query so we initialize it last in the chain/pipeline //// so that it is the first to execute, and then fallback to Http Get if appropriate, finally throw //// an exception if neither are supported by the current request. this.MiddlewareProxy = new HttpPostMiddleware( async(httpContext) => await httpGetMiddlewareShim.InvokeAsync(httpContext), this.ExecutorResolver, this.ResultSerializer, this.RequestParser, this.SchemaName ); }
private MiddlewareBase ConfigureMiddlewareChainOfResponsibility() { //********************************************* //Manually Build the Proxy Pipeline... //********************************************* this.MiddlewareProxyDelegate = (httpContext) => throw new HttpRequestException( "GraphQL was unable to process the request, ensure that an Http POST or GET GraphQL request was sent as well-formed Json." ); //BBernard - Initialize the middleware proxy and pipeline with support for both Http GET & POST processing... //NOTE: Middleware uses the Pipeline Pattern (e.g. Chain Of Responsibility), therefore // we adapt that here to manually build up the key middleware handlers for Http Get & Http Post processing. //NOTE: Other key features such as Schema download and the GraphQL IDE (Banana Cake Pop Dynamic UI) are all // delivered by other Middleware also. //NOTE: Middleware MUST be configured in the correct order of dependency to support the functionality and // the chain of responsibility is executed inside-out; or last registered middleware will run first and // the first one registered will run last (if not already previously handled). // Therefore we MUST register the middleware in reverse order of how the HC Core code does in the // `public static GraphQLEndpointConventionBuilder MapGraphQL()` builder logic. // Proper Execution Order must be: // - HttpPostMiddleware // - HttpGetSchemaMiddleware // - ToolDefaultFileMiddleware // - ToolOptionsFileMiddleware // - ToolStaticFileMiddleware // - HttpGetMiddleware if (Options.EnableGETRequests) { var httpGetMiddlewareShim = new HttpGetMiddleware( this.MiddlewareProxyDelegate, this.ExecutorResolver, this.ResultSerializer, this.RequestParser, this.SchemaName ); this.MiddlewareProxyDelegate = (httpContext) => httpGetMiddlewareShim.InvokeAsync(httpContext); } if (Options.EnableBananaCakePop) { var toolStaticFileMiddlewareShim = new ToolStaticFileMiddleware( this.MiddlewareProxyDelegate, this.FileProvider, this.RoutePath ); this.MiddlewareProxyDelegate = (httpContext) => toolStaticFileMiddlewareShim.Invoke(httpContext); var toolOptionsFileMiddlewareShim = new ToolOptionsFileMiddleware( //New for v12 The Constructor for this Middleware is simplified and no longer requires the injection of GraphQL dependencies because it's simply a File Handler for BCP this.MiddlewareProxyDelegate, this.RoutePath ); this.MiddlewareProxyDelegate = (httpContext) => toolOptionsFileMiddlewareShim.Invoke(httpContext); var toolDefaultFileMiddlewareShim = new ToolDefaultFileMiddleware( this.MiddlewareProxyDelegate, this.FileProvider, this.RoutePath ); this.MiddlewareProxyDelegate = (httpContext) => toolDefaultFileMiddlewareShim.Invoke(httpContext); } if (Options.EnableSchemaDefinitionDownload) { var httpGetSchemaMiddlewareShim = new HttpGetSchemaMiddleware( this.MiddlewareProxyDelegate, this.ExecutorResolver, this.ResultSerializer, this.SchemaName, //New v12 parameter set to Integrated to enable integrated/default functionality (compatible with v11 behavior). MiddlewareRoutingType.Integrated ); this.MiddlewareProxyDelegate = (httpContext) => httpGetSchemaMiddlewareShim.InvokeAsync(httpContext); } ////NOTE: The normal use case for GraphQL is POST'ing of the query so we initialize it last in the chain/pipeline //// so that it is the first to execute, and then fallback to Http Get if appropriate, finally throw //// an exception if neither are supported by the current request. var httpPostMiddlewareShim = new HttpPostMiddleware( this.MiddlewareProxyDelegate, this.ExecutorResolver, this.ResultSerializer, this.RequestParser, this.SchemaName ); this.MiddlewareProxyDelegate = (httpContext) => httpPostMiddlewareShim.InvokeAsync(httpContext); //RETURN the Post Middleware as the Primary Middleware reference... return(httpPostMiddlewareShim); }