diff --git a/src/BuiltInTools/BrowserRefresh/BrowserRefreshMiddleware.cs b/src/BuiltInTools/BrowserRefresh/BrowserRefreshMiddleware.cs index 210b4f73e890..778f1c0693bd 100644 --- a/src/BuiltInTools/BrowserRefresh/BrowserRefreshMiddleware.cs +++ b/src/BuiltInTools/BrowserRefresh/BrowserRefreshMiddleware.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Watch.BrowserRefresh @@ -23,7 +24,7 @@ public BrowserRefreshMiddleware(RequestDelegate next, ILogger acceptHeaders)) + if (typedHeaders.Accept is not IList acceptHeaders) { return false; } diff --git a/src/Tests/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/BrowserRefreshMiddlewareTest.cs b/src/Tests/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/BrowserRefreshMiddlewareTest.cs index 24dc14db5ddb..b0389345d710 100644 --- a/src/Tests/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/BrowserRefreshMiddlewareTest.cs +++ b/src/Tests/Microsoft.AspNetCore.Watch.BrowserRefresh.Tests/BrowserRefreshMiddlewareTest.cs @@ -16,7 +16,7 @@ public class BrowserRefreshMiddlewareTest [InlineData("DELETE")] [InlineData("head")] [InlineData("Put")] - public void IsBrowserRequest_ReturnsFalse_ForNonGetOrPostRequests(string method) + public void IsBrowserDocumentRequest_ReturnsFalse_ForNonGetOrPostRequests(string method) { // Arrange var context = new DefaultHttpContext @@ -32,14 +32,14 @@ public void IsBrowserRequest_ReturnsFalse_ForNonGetOrPostRequests(string method) }; // Act - var result = BrowserRefreshMiddleware.IsBrowserRequest(context); + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); // Assert Assert.False(result); } [Fact] - public void IsBrowserRequest_ReturnsFalse_IsRequestDoesNotAcceptHtml() + public void IsBrowserDocumentRequest_ReturnsFalse_IsRequestDoesNotAcceptHtml() { // Arrange var context = new DefaultHttpContext @@ -55,14 +55,14 @@ public void IsBrowserRequest_ReturnsFalse_IsRequestDoesNotAcceptHtml() }; // Act - var result = BrowserRefreshMiddleware.IsBrowserRequest(context); + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); // Assert Assert.False(result); } [Fact] - public void IsBrowserRequest_ReturnsTrue_ForGetRequestsThatAcceptHtml() + public void IsBrowserDocumentRequest_ReturnsTrue_ForGetRequestsThatAcceptHtml() { // Arrange var context = new DefaultHttpContext @@ -78,14 +78,14 @@ public void IsBrowserRequest_ReturnsTrue_ForGetRequestsThatAcceptHtml() }; // Act - var result = BrowserRefreshMiddleware.IsBrowserRequest(context); + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); // Assert Assert.True(result); } [Fact] - public void IsBrowserRequest_ReturnsTrue_ForRequestsThatAcceptAnyHtml() + public void IsBrowserDocumentRequest_ReturnsTrue_ForRequestsThatAcceptAnyHtml() { // Arrange var context = new DefaultHttpContext @@ -101,12 +101,112 @@ public void IsBrowserRequest_ReturnsTrue_ForRequestsThatAcceptAnyHtml() }; // Act - var result = BrowserRefreshMiddleware.IsBrowserRequest(context); + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); // Assert Assert.True(result); } + [Fact] + public void IsBrowserDocumentRequest_ReturnsTrue_IfRequestDoesNotHaveFetchMetadataRequestHeader() + { + // Arrange + var context = new DefaultHttpContext + { + Request = + { + Method = "GET", + Headers = + { + ["Accept"] = "text/html", + }, + }, + }; + + // Act + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); + + // Assert + Assert.True(result); + } + + [Fact] + public void IsBrowserDocumentRequest_ReturnsTrue_IfRequestFetchMetadataRequestHeaderIsEmpty() + { + // Arrange + var context = new DefaultHttpContext + { + Request = + { + Method = "Post", + Headers = + { + ["Accept"] = "text/html", + ["Sec-Fetch-Dest"] = string.Empty, + }, + }, + }; + + // Act + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); + + // Assert + Assert.True(result); + } + + [Theory] + [InlineData("document")] + [InlineData("Document")] + public void IsBrowserDocumentRequest_ReturnsTrue_IfRequestFetchMetadataRequestHeaderIsDocument(string headerValue) + { + // Arrange + var context = new DefaultHttpContext + { + Request = + { + Method = "Post", + Headers = + { + ["Accept"] = "text/html", + ["Sec-Fetch-Dest"] = headerValue, + }, + }, + }; + + // Act + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); + + // Assert + Assert.True(result); + } + + [Theory] + [InlineData("frame")] + [InlineData("iframe")] + [InlineData("serviceworker")] + public void IsBrowserDocumentRequest_ReturnsFalse_IfRequestFetchMetadataRequestHeaderIsNotDocument(string headerValue) + { + // Arrange + var context = new DefaultHttpContext + { + Request = + { + Method = "Post", + Headers = + { + ["Accept"] = "text/html", + ["Sec-Fetch-Dest"] = headerValue, + }, + }, + }; + + // Act + var result = BrowserRefreshMiddleware.IsBrowserDocumentRequest(context); + + // Assert + Assert.False(result); + } + [Fact] public async Task InvokeAsync_AddsScriptToThePage() {