diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ContentType.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ContentType.cs index c553280ebf7..a3e4646ab99 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/ContentType.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ContentType.cs @@ -11,6 +11,7 @@ internal static class ContentType public const string MultiPartMixed = $"{Types.MultiPart}/{SubTypes.Mixed};{_boundary}"; public const string GraphQLResponse = $"{Types.Application}/{SubTypes.GraphQLResponse};{_utf8}"; public const string EventStream = $"{Types.Text}/{SubTypes.EventStream};{_utf8}"; + public const string Html = $"{Types.Text}/{SubTypes.Html}"; private static readonly char[] _jsonArray = { @@ -44,5 +45,6 @@ public static class SubTypes public const string Json = "json"; public const string Mixed = "mixed"; public const string EventStream = "event-stream"; + public const string Html = "html"; } } diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/EndpointRouteBuilderExtensions.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/EndpointRouteBuilderExtensions.cs index c120baf11f1..c79ae7160b6 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/EndpointRouteBuilderExtensions.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/EndpointRouteBuilderExtensions.cs @@ -88,7 +88,7 @@ public static class EndpointRouteBuilderExtensions .UseMiddleware(fileProvider, path) .UseMiddleware(path) .UseMiddleware(fileProvider, path) - .UseMiddleware(schemaNameOrDefault) + .UseMiddleware(schemaNameOrDefault, path) .Use(_ => context => { context.Response.StatusCode = 404; diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HttpRequestExtensions.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HttpRequestExtensions.cs index 03e81c36bac..352017eeecd 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HttpRequestExtensions.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HttpRequestExtensions.cs @@ -5,10 +5,13 @@ namespace HotChocolate.AspNetCore; internal static class HttpRequestExtensions { + private const string _slash = "/"; + private static readonly PathString _slashPath = new("/"); + internal static bool AcceptHeaderContainsHtml(this HttpRequest request) { return request.Headers.TryGetValue(HeaderNames.Accept, out var values) && - values.Count > 0 && (values[0]?.Contains("text/html") ?? false); + values.Count > 0 && (values[0]?.Contains(ContentType.Html) ?? false); } internal static bool IsGetOrHeadMethod(this HttpRequest request) @@ -18,7 +21,7 @@ internal static bool IsGetOrHeadMethod(this HttpRequest request) internal static bool PathEndsInSlash(this HttpRequest request) { - return request.Path.Value?.EndsWith("/", StringComparison.Ordinal) ?? false; + return request.Path.Value?.EndsWith(_slash, StringComparison.Ordinal) ?? false; } internal static bool TryMatchPath( @@ -31,11 +34,15 @@ internal static bool PathEndsInSlash(this HttpRequest request) if (forDirectory && !request.PathEndsInSlash()) { - path += new PathString("/"); + path += _slashPath; } if (path.StartsWithSegments(matchUrl, out subPath)) { + if (subPath.Value?.Length is 1 && subPath.Equals(_slashPath)) + { + subPath = default; + } return true; } diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/HttpGetMiddleware.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/HttpGetMiddleware.cs index e6f47c97682..7473a3cac9d 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/HttpGetMiddleware.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/HttpGetMiddleware.cs @@ -13,6 +13,7 @@ public sealed class HttpGetMiddleware : MiddlewareBase { private readonly IHttpRequestParser _requestParser; private readonly IServerDiagnosticEvents _diagnosticEvents; + private readonly PathString _matchUrl; public HttpGetMiddleware( HttpRequestDelegate next, @@ -20,6 +21,7 @@ public sealed class HttpGetMiddleware : MiddlewareBase IHttpResponseFormatter responseFormatter, IHttpRequestParser requestParser, IServerDiagnosticEvents diagnosticEvents, + PathString matchUrl, string schemaName) : base(next, executorResolver, responseFormatter, schemaName) { @@ -27,11 +29,14 @@ public sealed class HttpGetMiddleware : MiddlewareBase throw new ArgumentNullException(nameof(requestParser)); _diagnosticEvents = diagnosticEvents ?? throw new ArgumentNullException(nameof(diagnosticEvents)); + _matchUrl = matchUrl; } public async Task InvokeAsync(HttpContext context) { if (HttpMethods.IsGet(context.Request.Method) && + context.Request.TryMatchPath(_matchUrl, false, out var subPath) && + !subPath.HasValue && (context.GetGraphQLServerOptions()?.EnableGetRequests ?? true)) { if (!IsDefaultSchema) diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/HttpMultipartRequest.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/HttpMultipartRequest.cs index cdb54cd7399..6452e05be77 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/HttpMultipartRequest.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/HttpMultipartRequest.cs @@ -1,6 +1,6 @@ namespace HotChocolate.AspNetCore; -internal class HttpMultipartRequest +internal sealed class HttpMultipartRequest { public HttpMultipartRequest(string operations, IDictionary fileMap) { diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ToolDefaultFileMiddleware.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ToolDefaultFileMiddleware.cs index 17978aaf87a..46254b80f32 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/ToolDefaultFileMiddleware.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ToolDefaultFileMiddleware.cs @@ -11,7 +11,7 @@ namespace HotChocolate.AspNetCore; /// If so the file name is appended to the path and execution continues. /// Note we don't just serve the file because it may require interpretation. /// -public class ToolDefaultFileMiddleware +public sealed class ToolDefaultFileMiddleware { private const string _defaultFile = "index.html"; private readonly IFileProvider _fileProvider; diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ToolOptionsFileMiddleware.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ToolOptionsFileMiddleware.cs index 1d161ce71ad..240d2836268 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/ToolOptionsFileMiddleware.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ToolOptionsFileMiddleware.cs @@ -6,7 +6,7 @@ namespace HotChocolate.AspNetCore; /// /// This middleware handles the Banana Cake Pop configuration file request. /// -public class ToolOptionsFileMiddleware +public sealed class ToolOptionsFileMiddleware { private const string _configFile = "/bcp-config.json"; private readonly HttpRequestDelegate _next; diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/ToolStaticFileMiddleware.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/ToolStaticFileMiddleware.cs index 32e69ed3a17..b25694a995e 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/ToolStaticFileMiddleware.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/ToolStaticFileMiddleware.cs @@ -12,7 +12,7 @@ namespace HotChocolate.AspNetCore; /// /// Enables serving static files for a given request path /// -public class ToolStaticFileMiddleware +public sealed class ToolStaticFileMiddleware { private readonly IContentTypeProvider _contentTypeProvider; private readonly IFileProvider _fileProvider; @@ -105,7 +105,7 @@ private Task TryServeStaticFile(HttpContext context, string contentType, PathStr return false; } - private async Task SendAsync(HttpContext context, StaticFileInfo fileInfo) + private static async Task SendAsync(HttpContext context, StaticFileInfo fileInfo) { SetCompressionMode(context); context.Response.StatusCode = 200; @@ -131,7 +131,7 @@ private async Task SendAsync(HttpContext context, StaticFileInfo fileInfo) } } - private void SetCompressionMode(HttpContext context) + private static void SetCompressionMode(HttpContext context) { if (context.Features.Get() is { } c) { diff --git a/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Opa.Tests/HotChocolate.AspNetCore.Authorization.Opa.Tests.csproj b/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Opa.Tests/HotChocolate.AspNetCore.Authorization.Opa.Tests.csproj index 5be06a07b17..aed7ee0ad2a 100644 --- a/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Opa.Tests/HotChocolate.AspNetCore.Authorization.Opa.Tests.csproj +++ b/src/HotChocolate/AspNetCore/test/AspNetCore.Authorization.Opa.Tests/HotChocolate.AspNetCore.Authorization.Opa.Tests.csproj @@ -13,6 +13,11 @@ + + + + + Always @@ -21,17 +26,4 @@ - - - - - - - - - - - - -