diff options
author | Matt Mitchell <mmitche@microsoft.com> | 2022-03-22 00:50:13 +0300 |
---|---|---|
committer | Matt Mitchell <mmitche@microsoft.com> | 2022-03-22 00:50:13 +0300 |
commit | cdabbaa6ffb048ff964474b934f54bfde1cfc6ff (patch) | |
tree | c6848e5588293e97a4ed2209305231452c828c4b | |
parent | 578ba6d8016785b53d7a96248ed6ccf211843b05 (diff) | |
parent | 0498f89e9fe1927489ca87a3d2d03b27759f2c35 (diff) |
Merged PR 21913: Merge from public release/6.0
# {PR title}
Summary of the changes (Less than 80 chars)
## Description
{Detail}
Fixes #{bug number} (in this specific format)
## Customer Impact
{Justification}
## Regression?
- [ ] Yes
- [ ] No
[If yes, specify the version the behavior has regressed from]
## Risk
- [ ] High
- [ ] Medium
- [ ] Low
[Justify the selection above]
## Verification
- [ ] Manual (required)
- [ ] Automated
## Packaging changes reviewed?
- [ ] Yes
- [ ] No
- [ ] N/A
----
## When servicing release/2.1
- [ ] Make necessary changes in eng/PatchConfig.props
14 files changed, 55 insertions, 13 deletions
diff --git a/src/Components/README.md b/src/Components/README.md index 2ecd768375..913ae5e9ff 100644 --- a/src/Components/README.md +++ b/src/Components/README.md @@ -26,6 +26,7 @@ The following contains a description of each sub-directory in the `Components` d - `Server`: Contains the implementation for WASM-specific extension methods and the launch logic for the debugging proxy - `WebAssembly`: Contains WebAssembly-specific implementations of the renderer, HostBuilder, etc. - `WebAssembly.Authentication`: Contains the WASM-specific implementations +- `WebView`: Contains the source files to support [Blazor Hybrid](https://github.com/dotnet/maui/tree/main/src/BlazorWebView) within [`dotnet/maui`](https://github.com/dotnet/maui). Changes in this project can be tested with `dotnet/maui` following [this guide](https://github.com/dotnet/maui/wiki/Blazor-Desktop#aspnet-core). ## Development Setup diff --git a/src/Components/WebView/WebView/src/IpcSender.cs b/src/Components/WebView/WebView/src/IpcSender.cs index a0ba3d5b67..a0ddd9fba0 100644 --- a/src/Components/WebView/WebView/src/IpcSender.cs +++ b/src/Components/WebView/WebView/src/IpcSender.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Runtime.ExceptionServices; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.JSInterop; @@ -62,8 +63,12 @@ namespace Microsoft.AspNetCore.Components.WebView public void NotifyUnhandledException(Exception exception) { + // Send the serialized exception to the WebView for display var message = IpcCommon.Serialize(IpcCommon.OutgoingMessageType.NotifyUnhandledException, exception.Message, exception.StackTrace); _dispatcher.InvokeAsync(() => _messageDispatcher(message)); + + // Also rethrow so the AppDomain's UnhandledException handler gets notified + _dispatcher.InvokeAsync(() => ExceptionDispatchInfo.Capture(exception).Throw()); } private void DispatchMessageWithErrorHandling(string message) diff --git a/src/Components/WebView/WebView/src/Services/WebViewRenderer.cs b/src/Components/WebView/WebView/src/Services/WebViewRenderer.cs index b928d82afa..20f3c48579 100644 --- a/src/Components/WebView/WebView/src/Services/WebViewRenderer.cs +++ b/src/Components/WebView/WebView/src/Services/WebViewRenderer.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.ExceptionServices; using System.Text.Json; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Web; @@ -38,9 +37,6 @@ namespace Microsoft.AspNetCore.Components.WebView.Services { // Notify the JS code so it can show the in-app UI _ipcSender.NotifyUnhandledException(exception); - - // Also rethrow so the AppDomain's UnhandledException handler gets notified - ExceptionDispatchInfo.Capture(exception).Throw(); } protected override Task UpdateDisplayAsync(in RenderBatch renderBatch) diff --git a/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj b/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj index dff0c5861c..07f2d99eed 100644 --- a/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj +++ b/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj @@ -18,6 +18,7 @@ <Compile Include="$(SharedSourceRoot)HttpSys\**\*.cs" /> <Compile Include="$(SharedSourceRoot)Buffers.MemoryPool\*.cs" LinkBase="MemoryPool" /> <Compile Include="$(SharedSourceRoot)ServerInfrastructure\StringUtilities.cs" LinkBase="ServerInfrastructure\StringUtilities.cs" /> + <Compile Include="$(SharedSourceRoot)ServerInfrastructure\HttpCharacters.cs" LinkBase="ServerInfrastructure\HttpCharacters.cs" /> <Compile Include="$(SharedSourceRoot)TaskToApm.cs" /> </ItemGroup> diff --git a/src/Servers/HttpSys/test/FunctionalTests/ResponseHeaderTests.cs b/src/Servers/HttpSys/test/FunctionalTests/ResponseHeaderTests.cs index f22b104477..19d9abae07 100644 --- a/src/Servers/HttpSys/test/FunctionalTests/ResponseHeaderTests.cs +++ b/src/Servers/HttpSys/test/FunctionalTests/ResponseHeaderTests.cs @@ -114,6 +114,27 @@ namespace Microsoft.AspNetCore.Server.HttpSys } [ConditionalFact] + public async Task ResponseHeaders_ServerSendsNonAsciiHeaders_Success() + { + string address; + using (Utilities.CreateHttpServer(out address, httpContext => + { + var responseInfo = httpContext.Features.Get<IHttpResponseFeature>(); + var responseHeaders = responseInfo.Headers; + responseHeaders["Custom-Header1"] = new string[] { "Dašta" }; + return Task.FromResult(0); + })) + { + var socketsHttpHandler = new SocketsHttpHandler() { ResponseHeaderEncodingSelector = (_, _) => Encoding.UTF8 }; + var httpClient = new HttpClient(socketsHttpHandler); + var response = await httpClient.GetAsync(address); + response.EnsureSuccessStatusCode(); + Assert.True(response.Headers.TryGetValues("Custom-Header1", out var header)); + Assert.Equal("Dašta", header.Single()); + } + } + + [ConditionalFact] public async Task ResponseHeaders_ServerSendsConnectionClose_Closed() { string address; diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs index 16176ecc43..ccf85081f3 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.IO.Pipelines; using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.cs index 72bcfc688a..3a9382333c 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.cs @@ -10,7 +10,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs index 739282953b..064da12cb6 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs @@ -6,6 +6,7 @@ using System.Buffers; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs index eb5294b2a1..685b25220e 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs @@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.FlowControl; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; +using HttpCharacters = Microsoft.AspNetCore.Http.HttpCharacters; using HttpMethods = Microsoft.AspNetCore.Http.HttpMethods; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 diff --git a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs index c1086dc02a..0f862c69fe 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; +using HttpCharacters = Microsoft.AspNetCore.Http.HttpCharacters; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3 { diff --git a/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs b/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs index a959dfdf7d..bee7ab9fce 100644 --- a/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs +++ b/src/Servers/Kestrel/Core/src/Internal/KestrelServerImpl.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; diff --git a/src/Servers/Kestrel/Core/test/HttpResponseHeadersTests.cs b/src/Servers/Kestrel/Core/test/HttpResponseHeadersTests.cs index 5795fa4077..0ebf12b0c8 100644 --- a/src/Servers/Kestrel/Core/test/HttpResponseHeadersTests.cs +++ b/src/Servers/Kestrel/Core/test/HttpResponseHeadersTests.cs @@ -242,6 +242,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] + public void AddingTabCharactersToHeaderPropertyWorks() + { + var responseHeaders = (IHeaderDictionary)new HttpResponseHeaders(); + + // Known special header + responseHeaders.Allow = "Da\tta"; + + // Unknown header fallback + responseHeaders.Accept = "Da\tta"; + } + + [Fact] public void ThrowsWhenAddingHeaderAfterReadOnlyIsSet() { var headers = new HttpResponseHeaders(); diff --git a/src/Shared/HttpSys/RequestProcessing/HeaderCollection.cs b/src/Shared/HttpSys/RequestProcessing/HeaderCollection.cs index 8fbc04221b..5c79a6b88d 100644 --- a/src/Shared/HttpSys/RequestProcessing/HeaderCollection.cs +++ b/src/Shared/HttpSys/RequestProcessing/HeaderCollection.cs @@ -272,12 +272,10 @@ namespace Microsoft.AspNetCore.HttpSys.Internal { if (headerCharacters != null) { - foreach (var ch in headerCharacters) + var invalid = HttpCharacters.IndexOfInvalidFieldValueCharExtended(headerCharacters); + if (invalid >= 0) { - if (ch < 0x20) - { - throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Invalid control character in header: 0x{0:X2}", (byte)ch)); - } + throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Invalid control character in header: 0x{0:X2}", headerCharacters[invalid])); } } } diff --git a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/HttpCharacters.cs b/src/Shared/ServerInfrastructure/HttpCharacters.cs index 213844419a..7f7de7acc0 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/HttpCharacters.cs +++ b/src/Shared/ServerInfrastructure/HttpCharacters.cs @@ -4,7 +4,7 @@ using System; using System.Runtime.CompilerServices; -namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure +namespace Microsoft.AspNetCore.Http { internal static class HttpCharacters { @@ -107,6 +107,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure { // field-value https://tools.ietf.org/html/rfc7230#section-3.2 var fieldValue = new bool[_tableSize]; + + fieldValue[0x9] = true; // HTAB + for (var c = 0x20; c <= 0x7e; c++) // VCHAR and SP { fieldValue[c] = true; @@ -182,7 +185,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure return -1; } - // Disallows control characters and anything more than 0x7F + // Follows field-value rules in https://tools.ietf.org/html/rfc7230#section-3.2 + // Disallows characters > 0x7E. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfInvalidFieldValueChar(string s) { @@ -200,7 +204,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure return -1; } - // Disallows control characters but allows extended characters > 0x7F + // Follows field-value rules for chars <= 0x7F. Allows extended characters > 0x7F. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOfInvalidFieldValueCharExtended(string s) { |