Merge pull request #23427 from dotnet-maestro-bot/merge/release/5.0-preview7-to-master

[automated] Merge branch 'release/5.0-preview7' => 'master'
This commit is contained in:
Pranav K 2020-07-01 07:27:53 -07:00 committed by GitHub
commit dc4670e8d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 450 additions and 243 deletions

View File

@ -1,15 +1,9 @@
<!-- This file is automatically generated. --> <!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.Authorization.netstandard2.0.cs" />
<Reference Include="Microsoft.AspNetCore.Authorization" />
<Reference Include="Microsoft.AspNetCore.Components" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs" /> <Compile Include="Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs" />
<Reference Include="Microsoft.AspNetCore.Authorization" /> <Reference Include="Microsoft.AspNetCore.Authorization" />
<Reference Include="Microsoft.AspNetCore.Components" /> <Reference Include="Microsoft.AspNetCore.Components" />

View File

@ -1,12 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Razor"> <Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<IsAspNetCoreApp>true</IsAspNetCoreApp> <IsAspNetCoreApp>true</IsAspNetCoreApp>
<Description>Authentication and authorization support for Blazor applications.</Description> <Description>Authentication and authorization support for Blazor applications.</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,19 +1,10 @@
<!-- This file is automatically generated. --> <!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable> <Nullable>annotations</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.netstandard2.0.cs" />
<Compile Include="Microsoft.AspNetCore.Components.Manual.cs" />
<Compile Include="../src/Properties/AssemblyInfo.cs" />
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<Reference Include="System.Buffers" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.netcoreapp.cs" /> <Compile Include="Microsoft.AspNetCore.Components.netcoreapp.cs" />
<Compile Include="Microsoft.AspNetCore.Components.Manual.cs" /> <Compile Include="Microsoft.AspNetCore.Components.Manual.cs" />
<Compile Include="../src/Properties/AssemblyInfo.cs" /> <Compile Include="../src/Properties/AssemblyInfo.cs" />

View File

@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Description>Components feature for ASP.NET Core.</Description> <Description>Components feature for ASP.NET Core.</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAspNetCoreApp>true</IsAspNetCoreApp> <IsAspNetCoreApp>true</IsAspNetCoreApp>
@ -17,19 +16,12 @@
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Extensions.Logging.Abstractions" /> <Reference Include="Microsoft.Extensions.Logging.Abstractions" />
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" /> <Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<Compile Include="$(SharedSourceRoot)HashCodeCombiner\*.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<Reference Include="System.Buffers" />
</ItemGroup> </ItemGroup>
<!-- These references were removed in 3.0 --> <!-- These references were removed in 3.0 -->
<ItemGroup> <ItemGroup>
<SuppressBaselineReference Include="Microsoft.AspNetCore.Components.Analyzers" /> <SuppressBaselineReference Include="Microsoft.AspNetCore.Components.Analyzers" />
<SuppressBaselineReference Include="Microsoft.AspNetCore.Authorization" /> <SuppressBaselineReference Include="Microsoft.AspNetCore.Authorization" />
<SuppressBaselineReference Include="Microsoft.JSInterop" />
<SuppressBaselineReference Include="System.ComponentModel.Annotations" /> <SuppressBaselineReference Include="System.ComponentModel.Annotations" />
</ItemGroup> </ItemGroup>
@ -38,27 +30,25 @@
BuildInParallel="$(BuildInParallel)" BuildInParallel="$(BuildInParallel)"
Projects=" Projects="
../../Analyzers/src/Microsoft.AspNetCore.Components.Analyzers.csproj; ../../Analyzers/src/Microsoft.AspNetCore.Components.Analyzers.csproj;
../../../JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj;
../../../Security/Authorization/Core/src/Microsoft.AspNetCore.Authorization.csproj"> ../../../Security/Authorization/Core/src/Microsoft.AspNetCore.Authorization.csproj">
<Output TaskParameter="TargetOutputs" ItemName="_ProjectPathWithVersion" /> <Output TaskParameter="TargetOutputs" ItemName="_ProjectPathWithVersion" />
</MSBuild> </MSBuild>
<ItemGroup> <ItemGroup>
<NuspecProperty Include="@(_ProjectPathWithVersion->WithMetadataValue('PackageId', 'Microsoft.AspnetCore.Components.Analyzers')->'componentAnalyzerPackageVersion=%(PackageVersion)')" /> <NuspecProperty Include="@(_ProjectPathWithVersion->WithMetadataValue('PackageId', 'Microsoft.AspnetCore.Components.Analyzers')->'componentAnalyzerPackageVersion=%(PackageVersion)')" />
<NuspecProperty Include="@(_ProjectPathWithVersion->WithMetadataValue('PackageId', 'Microsoft.AspnetCore.Authorization')->'authorizationPackageVersion=%(PackageVersion)')" /> <NuspecProperty Include="@(_ProjectPathWithVersion->WithMetadataValue('PackageId', 'Microsoft.AspnetCore.Authorization')->'authorizationPackageVersion=%(PackageVersion)')" />
<NuspecProperty Include="@(_ProjectPathWithVersion->WithMetadataValue('PackageId', 'Microsoft.JSInterop')->'jsInteropPackageVersion=%(PackageVersion)')" />
</ItemGroup> </ItemGroup>
</Target> </Target>
<!-- Pack settings --> <!-- Pack settings -->
<PropertyGroup> <PropertyGroup>
<NuspecFile>Microsoft.AspNetCore.Components.multitarget.nuspec</NuspecFile> <NuspecFile>Microsoft.AspNetCore.Components.netcoreapp.nuspec</NuspecFile>
<NuspecFile Condition="'$(DotNetBuildFromSource)' == 'true'">Microsoft.AspNetCore.Components.netcoreapp.nuspec</NuspecFile>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);_GetNuspecDependencyPackageVersions</GenerateNuspecDependsOn> <GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);_GetNuspecDependencyPackageVersions</GenerateNuspecDependsOn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<NuspecProperty Condition="'$(DotNetBuildFromSource)' != 'true'" Include="systemComponentModelAnnotationsPackageVersion=$(SystemComponentModelAnnotationsPackageVersion)" /> <NuspecProperty Condition="'$(DotNetBuildFromSource)' != 'true'" Include="systemComponentModelAnnotationsPackageVersion=$(SystemComponentModelAnnotationsPackageVersion)" />
<NuspecProperty Include="AssemblyName=$(AssemblyName)" /> <NuspecProperty Include="AssemblyName=$(AssemblyName)" />
<NuspecProperty Include="DefaultNetCoreTargetFramework=$(DefaultNetCoreTargetFramework)" />
<NuspecProperty Include="OutputPath=$(OutputPath)" /> <NuspecProperty Include="OutputPath=$(OutputPath)" />
<NuspecProperty Include="PackageThirdPartyNoticesFile=$(PackageThirdPartyNoticesFile)" /> <NuspecProperty Include="PackageThirdPartyNoticesFile=$(PackageThirdPartyNoticesFile)" />
</ItemGroup> </ItemGroup>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
$CommonMetadataElements$
<dependencies>
<group targetFramework=".NETStandard2.0">
<dependency id="Microsoft.AspNetCore.Components.Analyzers" version="$componentAnalyzerPackageVersion$" />
<dependency id="Microsoft.AspNetCore.Authorization" version="$authorizationPackageVersion$" exclude="Build,Analyzers" />
<dependency id="Microsoft.JSInterop" version="$jsInteropPackageVersion$" exclude="Build,Analyzers" />
<dependency id="System.ComponentModel.Annotations" version="$systemComponentModelAnnotationsPackageVersion$" exclude="Build,Analyzers" />
</group>
<group targetFramework=".net5.0">
<dependency id="Microsoft.AspNetCore.Components.Analyzers" version="$componentAnalyzerPackageVersion$" />
<dependency id="Microsoft.AspNetCore.Authorization" version="$authorizationPackageVersion$" exclude="Build,Analyzers" />
<dependency id="Microsoft.JSInterop" version="$jsInteropPackageVersion$" exclude="Build,Analyzers" />
</group>
</dependencies>
</metadata>
<files>
$CommonFileElements$
<file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" />
<file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" />
<file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" />
<file src="$PackageThirdPartyNoticesFile$" target=".\THIRD-PARTY-NOTICES.txt" />
</files>
</package>

View File

@ -6,15 +6,14 @@
<group targetFramework=".net5.0"> <group targetFramework=".net5.0">
<dependency id="Microsoft.AspNetCore.Components.Analyzers" version="$componentAnalyzerPackageVersion$" /> <dependency id="Microsoft.AspNetCore.Components.Analyzers" version="$componentAnalyzerPackageVersion$" />
<dependency id="Microsoft.AspNetCore.Authorization" version="$authorizationPackageVersion$" exclude="Build,Analyzers" /> <dependency id="Microsoft.AspNetCore.Authorization" version="$authorizationPackageVersion$" exclude="Build,Analyzers" />
<dependency id="Microsoft.JSInterop" version="$jsInteropPackageVersion$" exclude="Build,Analyzers" />
</group> </group>
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>
$CommonFileElements$ $CommonFileElements$
<file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" /> <file src="$OutputPath$$AssemblyName$.dll" target="lib\$DefaultNetCoreTargetFramework$\" />
<file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" /> <file src="$OutputPath$$AssemblyName$.pdb" target="lib\$DefaultNetCoreTargetFramework$\" />
<file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" /> <file src="$OutputPath$$AssemblyName$.xml" target="lib\$DefaultNetCoreTargetFramework$\" />
<file src="$PackageThirdPartyNoticesFile$" target=".\THIRD-PARTY-NOTICES.txt" /> <file src="$PackageThirdPartyNoticesFile$" target=".\THIRD-PARTY-NOTICES.txt" />
</files> </files>
</package> </package>

View File

@ -221,7 +221,7 @@ namespace Microsoft.AspNetCore.Components
public override int GetHashCode() public override int GetHashCode()
{ {
var hash = new HashCodeCombiner(); var hash = new HashCode();
if (Assemblies != null) if (Assemblies != null)
{ {
@ -231,7 +231,7 @@ namespace Microsoft.AspNetCore.Components
} }
} }
return hash; return hash.ToHashCode();
} }
} }
} }

View File

@ -1,16 +1,10 @@
<!-- This file is automatically generated. --> <!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable> <Nullable>annotations</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.Forms.netstandard2.0.cs" />
<Reference Include="Microsoft.AspNetCore.Components" />
<Reference Include="System.ComponentModel.Annotations" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.Forms.netcoreapp.cs" /> <Compile Include="Microsoft.AspNetCore.Components.Forms.netcoreapp.cs" />
<Reference Include="Microsoft.AspNetCore.Components" /> <Reference Include="Microsoft.AspNetCore.Components" />
</ItemGroup> </ItemGroup>

View File

@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<IsAspNetCoreApp>true</IsAspNetCoreApp> <IsAspNetCoreApp>true</IsAspNetCoreApp>
<Description>Forms and validation support for Blazor applications.</Description> <Description>Forms and validation support for Blazor applications.</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
@ -13,8 +12,4 @@
<Reference Include="Microsoft.AspNetCore.Components" /> <Reference Include="Microsoft.AspNetCore.Components" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'" >
<Reference Include="System.ComponentModel.Annotations" />
</ItemGroup>
</Project> </Project>

View File

@ -1,19 +1,10 @@
<!-- This file is automatically generated. --> <!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable> <Nullable>annotations</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.Web.netstandard2.0.cs" />
<Compile Include="../src/Properties/AssemblyInfo.cs" />
<Reference Include="Microsoft.AspNetCore.Components" />
<Reference Include="Microsoft.AspNetCore.Components.Forms" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="Microsoft.JSInterop" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Components.Web.netcoreapp.cs" /> <Compile Include="Microsoft.AspNetCore.Components.Web.netcoreapp.cs" />
<Compile Include="../src/Properties/AssemblyInfo.cs" /> <Compile Include="../src/Properties/AssemblyInfo.cs" />
<Reference Include="Microsoft.AspNetCore.Components" /> <Reference Include="Microsoft.AspNetCore.Components" />

View File

@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<IsAspNetCoreApp>true</IsAspNetCoreApp> <IsAspNetCoreApp>true</IsAspNetCoreApp>
<Description>Support for rendering ASP.NET Core components for browsers.</Description> <Description>Support for rendering ASP.NET Core components for browsers.</Description>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>

View File

@ -3,9 +3,8 @@
<Sdk Name="Yarn.MSBuild" /> <Sdk Name="Yarn.MSBuild" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Description>Authenticate your Blazor webassembly applications with Azure Active Directory and Azure Active Directory B2C</Description> <Description>Authenticate your Blazor webassembly applications with Azure Active Directory and Azure Active Directory B2C</Description>
<RazorLangVersion>3.0</RazorLangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Description>Abstractions and features for interop between .NET WebAssembly and JavaScript code.</Description> <Description>Abstractions and features for interop between .NET WebAssembly and JavaScript code.</Description>
<PackageTags>wasm;javascript;interop</PackageTags> <PackageTags>wasm;javascript;interop</PackageTags>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>

View File

@ -3,10 +3,9 @@
<Sdk Name="Yarn.MSBuild" /> <Sdk Name="Yarn.MSBuild" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Description>Build client-side authentication for single-page applications (SPAs).</Description> <Description>Build client-side authentication for single-page applications (SPAs).</Description>
<IsShippingPackage>true</IsShippingPackage> <IsShippingPackage>true</IsShippingPackage>
<RazorLangVersion>3.0</RazorLangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Description>Build client-side single-page applications (SPAs) with Blazor running under WebAssembly.</Description> <Description>Build client-side single-page applications (SPAs) with Blazor running under WebAssembly.</Description>
<IsShippingPackage>true</IsShippingPackage> <IsShippingPackage>true</IsShippingPackage>
<NoWarn>$(NoWarn);BL0006</NoWarn> <NoWarn>$(NoWarn);BL0006</NoWarn>
@ -44,7 +44,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Include="$(BlazorWebAssemblyJSFile)" Pack="true" PackagePath="build\netstandard2.0\" LinkBase="build\netstandard2.0\" /> <Content Include="$(BlazorWebAssemblyJSFile)" Pack="true" PackagePath="build\net5.0\" LinkBase="build\net5.0\" />
<Content Include="build\netstandard2.0\*.props" Pack="true" PackagePath="build\netstandard2.0\" /> <Content Include="build\net5.0\*.props" Pack="true" PackagePath="build\net5.0\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,5 +0,0 @@
<Project>
<PropertyGroup>
<BlazorWebAssemblyJSPath>$(MSBuildThisFileDirectory)blazor.webassembly.js</BlazorWebAssemblyJSPath>
</PropertyGroup>
</Project>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<UseBlazorWebAssembly>true</UseBlazorWebAssembly> <UseBlazorWebAssembly>true</UseBlazorWebAssembly>
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference> <FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<UseBlazorWebAssembly>true</UseBlazorWebAssembly> <UseBlazorWebAssembly>true</UseBlazorWebAssembly>
<IsTestAssetProject>true</IsTestAssetProject> <IsTestAssetProject>true</IsTestAssetProject>

View File

@ -1,9 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<OutputType>library</OutputType> <OutputType>library</OutputType>
<RazorLangVersion>3.0</RazorLangVersion>
<StaticWebAssetBasePath>_content/TestContentPackage</StaticWebAssetBasePath> <StaticWebAssetBasePath>_content/TestContentPackage</StaticWebAssetBasePath>
</PropertyGroup> </PropertyGroup>

View File

@ -1,16 +1,10 @@
<!-- This file is automatically generated. --> <!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable> <Nullable>annotations</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.JSInterop.netstandard2.0.cs" />
<Reference Include="System.Text.Json" />
<InternalsVisibleTo Include="Microsoft.JSInterop.Tests" Key="" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.JSInterop.netcoreapp.cs" /> <Compile Include="Microsoft.JSInterop.netcoreapp.cs" />
<InternalsVisibleTo Include="Microsoft.JSInterop.Tests" Key="" /> <InternalsVisibleTo Include="Microsoft.JSInterop.Tests" Key="" />
</ItemGroup> </ItemGroup>

View File

@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Description>Abstractions and features for interop between .NET and JavaScript code.</Description> <Description>Abstractions and features for interop between .NET and JavaScript code.</Description>
<PackageTags>javascript;interop</PackageTags> <PackageTags>javascript;interop</PackageTags>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>

View File

@ -1,9 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor"> <Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup> <PropertyGroup>
<TargetFramework Condition="'$(SupportPagesAndViews)' == 'True'">${DefaultNetCoreTargetFramework}</TargetFramework> <TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework>
<TargetFramework Condition="'$(SupportPagesAndViews)' != 'True'">netstandard2.0</TargetFramework>
<RazorLangVersion Condition="'$(SupportPagesAndViews)' != 'True'">3.0</RazorLangVersion>
<AddRazorSupportForMvc Condition="'$(SupportPagesAndViews)' == 'True'">true</AddRazorSupportForMvc> <AddRazorSupportForMvc Condition="'$(SupportPagesAndViews)' == 'True'">true</AddRazorSupportForMvc>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.RazorClassLibrary1</RootNamespace> <RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.RazorClassLibrary1</RootNamespace>
</PropertyGroup> </PropertyGroup>
@ -13,7 +11,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(SupportPagesAndViews)' != 'True'"> <ItemGroup Condition="'$(SupportPagesAndViews)' != 'True'">
<PackageReference Include="Microsoft.AspNetCore.Components" Version="${MicrosoftAspNetCoreComponentsPackageVersion}" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="${MicrosoftAspNetCoreComponentsWebPackageVersion}" /> <PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="${MicrosoftAspNetCoreComponentsWebPackageVersion}" />
</ItemGroup> </ItemGroup>

View File

@ -20,7 +20,9 @@ namespace Microsoft.AspNetCore.Razor.Language
public static readonly RazorLanguageVersion Version_3_0 = new RazorLanguageVersion(3, 0); public static readonly RazorLanguageVersion Version_3_0 = new RazorLanguageVersion(3, 0);
public static readonly RazorLanguageVersion Latest = Version_3_0; public static readonly RazorLanguageVersion Version_5_0 = new RazorLanguageVersion(5, 0);
public static readonly RazorLanguageVersion Latest = Version_5_0;
public static readonly RazorLanguageVersion Experimental = new RazorLanguageVersion(1337, 1337); public static readonly RazorLanguageVersion Experimental = new RazorLanguageVersion(1337, 1337);
@ -41,6 +43,11 @@ namespace Microsoft.AspNetCore.Razor.Language
version = Experimental; version = Experimental;
return true; return true;
} }
else if (languageVersion == "5.0")
{
version = Version_5_0;
return true;
}
else if (languageVersion == "3.0") else if (languageVersion == "3.0")
{ {
version = Version_3_0; version = Version_3_0;

View File

@ -92,6 +92,20 @@ namespace Microsoft.AspNetCore.Razor.Language
Assert.Same(RazorLanguageVersion.Version_3_0, version); Assert.Same(RazorLanguageVersion.Version_3_0, version);
} }
[Fact]
public void TryParse50()
{
// Arrange
var value = "5.0";
// Act
var result = RazorLanguageVersion.TryParse(value, out var version);
// Assert
Assert.True(result);
Assert.Same(RazorLanguageVersion.Version_5_0, version);
}
[Fact] [Fact]
public void TryParseLatest() public void TryParseLatest()
{ {
@ -103,7 +117,7 @@ namespace Microsoft.AspNetCore.Razor.Language
// Assert // Assert
Assert.True(result); Assert.True(result);
Assert.Same(RazorLanguageVersion.Version_3_0, version); Assert.Same(RazorLanguageVersion.Version_5_0, version);
} }
[Fact] [Fact]

View File

@ -625,28 +625,26 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
{ {
var result = await DotnetMSBuild( var result = await DotnetMSBuild(
"Build", "Build",
"/p:UseRazorBuildServer=false /p:RazorLangVersion=5.0", "/p:UseRazorBuildServer=false /p:RazorLangVersion=99.0",
suppressBuildServer: true); suppressBuildServer: true);
Assert.BuildFailed(result); Assert.BuildFailed(result);
Assert.BuildOutputContainsLine( Assert.BuildOutputContainsLine(
result, result,
$"Invalid option 5.0 for Razor language version --version; must be Latest or a valid version in range 1.0 to 3.0."); $"Invalid option 99.0 for Razor language version --version; must be Latest or a valid version in range 1.0 to 5.0.");
// Compilation failed without creating the views assembly // Compilation failed without creating the views assembly
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.dll"); Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.dll");
Assert.FileDoesNotExist(result, IntermediateOutputPath, "SimpleMvc.Views.dll"); Assert.FileDoesNotExist(result, IntermediateOutputPath, "SimpleMvc.Views.dll");
} }
[Fact(Skip = "Default C# version is 7.3 for netcoreapp3.1 and later https://github.com/dotnet/aspnetcore/issues/13930")] [Fact]
[InitializeTestProject("SimpleMvc")] [InitializeTestProject("SimpleMvc")]
public async Task Build_ImplicitCSharp8_NullableEnforcement_WarningsDuringBuild_NoBuildServer() public async Task Build_ImplicitCSharp8_NullableEnforcement_WarningsDuringBuild_NoBuildServer()
{ {
var result = await DotnetMSBuild( var result = await DotnetMSBuild(
"Build", "Build",
// Remove /p:LangVersion=Default once we've picked up a compiler that supports .NET 5.0. "/p:Nullable=enable",
// Tracked by https://github.com/dotnet/aspnetcore/issues/13304
"/p:Nullable=enable /p:LangVersion=Default",
suppressBuildServer: true); suppressBuildServer: true);
var indexFilePath = Path.Combine(RazorIntermediateOutputPath, "Views", "Home", "Index.cshtml.g.cs"); var indexFilePath = Path.Combine(RazorIntermediateOutputPath, "Views", "Home", "Index.cshtml.g.cs");

View File

@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
} }
[Fact] [Fact]
[InitializeTestProject("SimpleMvc")] [InitializeTestProject("SimpleMvc31")]
public async Task RazorSdk_ResolvesRazorLangVersionTo30ForNetCoreApp30Projects() public async Task RazorSdk_ResolvesRazorLangVersionTo30ForNetCoreApp30Projects()
{ {
var result = await DotnetMSBuild("ResolveRazorConfiguration", "/t:_IntrospectResolvedConfiguration"); var result = await DotnetMSBuild("ResolveRazorConfiguration", "/t:_IntrospectResolvedConfiguration");
@ -98,6 +98,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.BuildOutputContainsLine(result, "ResolvedRazorConfiguration: MVC-3.0"); Assert.BuildOutputContainsLine(result, "ResolvedRazorConfiguration: MVC-3.0");
} }
[Fact]
[InitializeTestProject("SimpleMvc")]
public async Task RazorSdk_ResolvesRazorLangVersionTo50ForNetCoreApp50Projects()
{
var result = await DotnetMSBuild("ResolveRazorConfiguration", "/t:_IntrospectResolvedConfiguration");
Assert.BuildPassed(result);
Assert.BuildOutputContainsLine(result, "RazorLangVersion: 5.0");
Assert.BuildOutputContainsLine(result, "ResolvedRazorConfiguration: MVC-3.0");
}
[Fact] [Fact]
[InitializeTestProject("ComponentLibrary")] [InitializeTestProject("ComponentLibrary")]
public async Task RazorSdk_ResolvesRazorLangVersionFromValueSpecified() public async Task RazorSdk_ResolvesRazorLangVersionFromValueSpecified()
@ -142,7 +153,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
var result = await DotnetMSBuild("ResolveRazorConfiguration", "/t:_IntrospectResolvedConfiguration"); var result = await DotnetMSBuild("ResolveRazorConfiguration", "/t:_IntrospectResolvedConfiguration");
Assert.BuildPassed(result); Assert.BuildPassed(result);
Assert.BuildOutputContainsLine(result, "RazorLangVersion: 3.0"); Assert.BuildOutputContainsLine(result, "RazorLangVersion: 5.0");
Assert.BuildOutputContainsLine(result, "ResolvedRazorConfiguration: MVC-3.0"); Assert.BuildOutputContainsLine(result, "ResolvedRazorConfiguration: MVC-3.0");
} }

View File

@ -100,12 +100,12 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
{ {
var result = await DotnetMSBuild( var result = await DotnetMSBuild(
"Build", "Build",
"/p:_RazorForceBuildServer=true /p:RazorLangVersion=5.0"); "/p:_RazorForceBuildServer=true /p:RazorLangVersion=99.0");
Assert.BuildFailed(result); Assert.BuildFailed(result);
Assert.BuildOutputContainsLine( Assert.BuildOutputContainsLine(
result, result,
$"Invalid option 5.0 for Razor language version --version; must be Latest or a valid version in range 1.0 to 3.0."); $"Invalid option 99.0 for Razor language version --version; must be Latest or a valid version in range 1.0 to 5.0.");
// Compilation failed without creating the views assembly // Compilation failed without creating the views assembly
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.dll"); Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.dll");

View File

@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
Assert.FileContainsLine( Assert.FileContainsLine(
result, result,
razorAssemblyInfo, razorAssemblyInfo,
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute(\"3.0\")]"); "[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute(\"5.0\")]");
Assert.FileContainsLine( Assert.FileContainsLine(
result, result,
razorAssemblyInfo, razorAssemblyInfo,

View File

@ -1,6 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
{ {
public class MvcBuildIntegrationTest31 : MvcBuildIntegrationTestLegacy public class MvcBuildIntegrationTest31 : MvcBuildIntegrationTestLegacy
@ -12,5 +16,33 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
public override string TestProjectName => "SimpleMvc31"; public override string TestProjectName => "SimpleMvc31";
public override string TargetFramework => "netcoreapp3.1"; public override string TargetFramework => "netcoreapp3.1";
[Fact]
public async Task Build_WithGenerateRazorHostingAssemblyInfo_AddsConfigurationMetadata()
{
using var project = CreateTestProject();
var razorAssemblyInfo = Path.Combine(IntermediateOutputPath, "SimpleMvc31.RazorAssemblyInfo.cs");
var result = await DotnetMSBuild("Build", "/p:GenerateRazorHostingAssemblyInfo=true");
Assert.BuildPassed(result);
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc31.Views.dll");
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc31.Views.pdb");
Assert.FileExists(result, razorAssemblyInfo);
Assert.FileContainsLine(
result,
razorAssemblyInfo,
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute(\"3.0\")]");
Assert.FileContainsLine(
result,
razorAssemblyInfo,
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute(\"MVC-3.0\")]");
Assert.FileContainsLine(
result,
razorAssemblyInfo,
"[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute(\"MVC-3.0\", \"Microsoft.AspNetCore.Mvc.Razor.Extensions\")]");
}
} }
} }

View File

@ -69,6 +69,7 @@ Copyright (c) .NET Foundation. All rights reserved.
Determine the default Razor configuration Determine the default Razor configuration
--> -->
<PropertyGroup Condition="'$(RazorDefaultConfiguration)'==''"> <PropertyGroup Condition="'$(RazorDefaultConfiguration)'==''">
<!-- For 5.0, we're not introducing any new language features for MVC. We can continue using the 3.0 configuration \ extension for MVC support. -->
<RazorDefaultConfiguration Condition="'$(AddRazorSupportForMvc)'=='true'">MVC-3.0</RazorDefaultConfiguration> <RazorDefaultConfiguration Condition="'$(AddRazorSupportForMvc)'=='true'">MVC-3.0</RazorDefaultConfiguration>
<RazorDefaultConfiguration Condition="'$(RazorDefaultConfiguration)'==''">Default</RazorDefaultConfiguration> <RazorDefaultConfiguration Condition="'$(RazorDefaultConfiguration)'==''">Default</RazorDefaultConfiguration>
</PropertyGroup> </PropertyGroup>
@ -80,7 +81,7 @@ Copyright (c) .NET Foundation. All rights reserved.
the project's runtime. the project's runtime.
--> -->
<RazorConfiguration Include="Default" /> <RazorConfiguration Include="Default" />
<RazorConfiguration Include="MVC-3.0" > <RazorConfiguration Include="MVC-3.0">
<Extensions>MVC-3.0;$(CustomRazorExtension)</Extensions> <Extensions>MVC-3.0;$(CustomRazorExtension)</Extensions>
</RazorConfiguration> </RazorConfiguration>
</ItemGroup> </ItemGroup>

View File

@ -45,6 +45,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<!-- <!--
Infer the RazorLangVersion if no value was specified. When adding support for newer target frameworks, list newer language versions first. Infer the RazorLangVersion if no value was specified. When adding support for newer target frameworks, list newer language versions first.
--> -->
<RazorLangVersion Condition="'$(RazorLangVersion)' == '' AND '$(_TargetingNET50OrLater)' == 'true'">5.0</RazorLangVersion>
<RazorLangVersion Condition="'$(RazorLangVersion)' == '' AND '$(_TargetingNETCoreApp30OrLater)' == 'true'">3.0</RazorLangVersion> <RazorLangVersion Condition="'$(RazorLangVersion)' == '' AND '$(_TargetingNETCoreApp30OrLater)' == 'true'">3.0</RazorLangVersion>
<!-- <!--

View File

@ -137,6 +137,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
public bool DisableStringReuse { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool DisableStringReuse { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public bool EnableAltSvc { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool EnableAltSvc { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerLimits Limits { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerLimits Limits { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public System.Func<string, System.Text.Encoding> RequestHeaderEncodingSelector { get { throw null; } set { } }
public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure() { throw null; } public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure() { throw null; }
public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure(Microsoft.Extensions.Configuration.IConfiguration config) { throw null; } public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure(Microsoft.Extensions.Configuration.IConfiguration config) { throw null; }
public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure(Microsoft.Extensions.Configuration.IConfiguration config, bool reloadOnChange) { throw null; } public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure(Microsoft.Extensions.Configuration.IConfiguration config, bool reloadOnChange) { throw null; }

View File

@ -18,14 +18,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
private const string EndpointDefaultsKey = "EndpointDefaults"; private const string EndpointDefaultsKey = "EndpointDefaults";
private const string EndpointsKey = "Endpoints"; private const string EndpointsKey = "Endpoints";
private const string UrlKey = "Url"; private const string UrlKey = "Url";
private const string Latin1RequestHeadersKey = "Latin1RequestHeaders";
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
private IDictionary<string, CertificateConfig> _certificates; private IDictionary<string, CertificateConfig> _certificates;
private EndpointDefaults _endpointDefaults; private EndpointDefaults _endpointDefaults;
private IEnumerable<EndpointConfig> _endpoints; private IEnumerable<EndpointConfig> _endpoints;
private bool? _latin1RequestHeaders;
public ConfigurationReader(IConfiguration configuration) public ConfigurationReader(IConfiguration configuration)
{ {
@ -35,7 +33,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
public IDictionary<string, CertificateConfig> Certificates => _certificates ??= ReadCertificates(); public IDictionary<string, CertificateConfig> Certificates => _certificates ??= ReadCertificates();
public EndpointDefaults EndpointDefaults => _endpointDefaults ??= ReadEndpointDefaults(); public EndpointDefaults EndpointDefaults => _endpointDefaults ??= ReadEndpointDefaults();
public IEnumerable<EndpointConfig> Endpoints => _endpoints ??= ReadEndpoints(); public IEnumerable<EndpointConfig> Endpoints => _endpoints ??= ReadEndpoints();
public bool Latin1RequestHeaders => _latin1RequestHeaders ??= _configuration.GetValue<bool>(Latin1RequestHeadersKey);
private IDictionary<string, CertificateConfig> ReadCertificates() private IDictionary<string, CertificateConfig> ReadCertificates()
{ {

View File

@ -6270,6 +6270,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value) public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
{ {
ref byte nameStart = ref MemoryMarshal.GetReference(name); ref byte nameStart = ref MemoryMarshal.GetReference(name);
var nameStr = string.Empty;
ref StringValues values = ref Unsafe.AsRef<StringValues>(null); ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
var flag = 0L; var flag = 0L;
@ -6281,6 +6282,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x20000000000L; flag = 0x20000000000L;
values = ref _headers._TE; values = ref _headers._TE;
nameStr = HeaderNames.TE;
} }
break; break;
case 3: case 3:
@ -6289,11 +6291,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x100000000000L; flag = 0x100000000000L;
values = ref _headers._DNT; values = ref _headers._DNT;
nameStr = HeaderNames.DNT;
} }
else if ((firstTerm3 == 0x4956u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)2) & 0xdfu) == 0x41u)) else if ((firstTerm3 == 0x4956u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)2) & 0xdfu) == 0x41u))
{ {
flag = 0x100L; flag = 0x100L;
values = ref _headers._Via; values = ref _headers._Via;
nameStr = HeaderNames.Via;
} }
break; break;
case 4: case 4:
@ -6302,16 +6306,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x80000000L; flag = 0x80000000L;
values = ref _headers._Host; values = ref _headers._Host;
nameStr = HeaderNames.Host;
} }
else if ((firstTerm4 == 0x45544144u)) else if ((firstTerm4 == 0x45544144u))
{ {
flag = 0x4L; flag = 0x4L;
values = ref _headers._Date; values = ref _headers._Date;
nameStr = HeaderNames.Date;
} }
else if ((firstTerm4 == 0x4d4f5246u)) else if ((firstTerm4 == 0x4d4f5246u))
{ {
flag = 0x40000000L; flag = 0x40000000L;
values = ref _headers._From; values = ref _headers._From;
nameStr = HeaderNames.From;
} }
break; break;
case 5: case 5:
@ -6319,16 +6326,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x200000L; flag = 0x200000L;
values = ref _headers._Path; values = ref _headers._Path;
nameStr = HeaderNames.Path;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x4f4c4c41u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)4) & 0xdfu) == 0x57u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x4f4c4c41u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)4) & 0xdfu) == 0x57u))
{ {
flag = 0x400L; flag = 0x400L;
values = ref _headers._Allow; values = ref _headers._Allow;
nameStr = HeaderNames.Allow;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x474e4152u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)4) & 0xdfu) == 0x45u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x474e4152u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)4) & 0xdfu) == 0x45u))
{ {
flag = 0x10000000000L; flag = 0x10000000000L;
values = ref _headers._Range; values = ref _headers._Range;
nameStr = HeaderNames.Range;
} }
break; break;
case 6: case 6:
@ -6337,26 +6347,31 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x800000L; flag = 0x800000L;
values = ref _headers._Accept; values = ref _headers._Accept;
nameStr = HeaderNames.Accept;
} }
else if ((firstTerm6 == 0x4b4f4f43u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4549u)) else if ((firstTerm6 == 0x4b4f4f43u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4549u))
{ {
flag = 0x10000000L; flag = 0x10000000L;
values = ref _headers._Cookie; values = ref _headers._Cookie;
nameStr = HeaderNames.Cookie;
} }
else if ((firstTerm6 == 0x45505845u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x5443u)) else if ((firstTerm6 == 0x45505845u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x5443u))
{ {
flag = 0x20000000L; flag = 0x20000000L;
values = ref _headers._Expect; values = ref _headers._Expect;
nameStr = HeaderNames.Expect;
} }
else if ((firstTerm6 == 0x4749524fu) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4e49u)) else if ((firstTerm6 == 0x4749524fu) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4e49u))
{ {
flag = 0x4000000000000L; flag = 0x4000000000000L;
values = ref _headers._Origin; values = ref _headers._Origin;
nameStr = HeaderNames.Origin;
} }
else if ((firstTerm6 == 0x47415250u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x414du)) else if ((firstTerm6 == 0x47415250u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x414du))
{ {
flag = 0x10L; flag = 0x10L;
values = ref _headers._Pragma; values = ref _headers._Pragma;
nameStr = HeaderNames.Pragma;
} }
break; break;
case 7: case 7:
@ -6364,36 +6379,43 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x100000L; flag = 0x100000L;
values = ref _headers._Method; values = ref _headers._Method;
nameStr = HeaderNames.Method;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfffu) == 0x4843533au) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4d45u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x45u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfffu) == 0x4843533au) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4d45u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x45u))
{ {
flag = 0x400000L; flag = 0x400000L;
values = ref _headers._Scheme; values = ref _headers._Scheme;
nameStr = HeaderNames.Scheme;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x49505845u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4552u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x53u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x49505845u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4552u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x53u))
{ {
flag = 0x20000L; flag = 0x20000L;
values = ref _headers._Expires; values = ref _headers._Expires;
nameStr = HeaderNames.Expires;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x45464552u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4552u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x52u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x45464552u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4552u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x52u))
{ {
flag = 0x8000000000L; flag = 0x8000000000L;
values = ref _headers._Referer; values = ref _headers._Referer;
nameStr = HeaderNames.Referer;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x49415254u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x454cu) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x52u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x49415254u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x454cu) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x52u))
{ {
flag = 0x20L; flag = 0x20L;
values = ref _headers._Trailer; values = ref _headers._Trailer;
nameStr = HeaderNames.Trailer;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x52475055u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4441u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x45u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x52475055u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4441u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x45u))
{ {
flag = 0x80L; flag = 0x80L;
values = ref _headers._Upgrade; values = ref _headers._Upgrade;
nameStr = HeaderNames.Upgrade;
} }
else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x4e524157u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4e49u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x47u)) else if (((Unsafe.ReadUnaligned<uint>(ref nameStart) & 0xdfdfdfdfu) == 0x4e524157u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(ushort)))) & 0xdfdfu) == 0x4e49u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)6) & 0xdfu) == 0x47u))
{ {
flag = 0x200L; flag = 0x200L;
values = ref _headers._Warning; values = ref _headers._Warning;
nameStr = HeaderNames.Warning;
} }
break; break;
case 8: case 8:
@ -6402,11 +6424,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x100000000L; flag = 0x100000000L;
values = ref _headers._IfMatch; values = ref _headers._IfMatch;
nameStr = HeaderNames.IfMatch;
} }
else if ((firstTerm8 == 0x45474e41522d4649uL)) else if ((firstTerm8 == 0x45474e41522d4649uL))
{ {
flag = 0x800000000L; flag = 0x800000000L;
values = ref _headers._IfRange; values = ref _headers._IfRange;
nameStr = HeaderNames.IfRange;
} }
break; break;
case 9: case 9:
@ -6414,6 +6438,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x40000000000L; flag = 0x40000000000L;
values = ref _headers._Translate; values = ref _headers._Translate;
nameStr = HeaderNames.Translate;
} }
break; break;
case 10: case 10:
@ -6421,31 +6446,37 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x80000L; flag = 0x80000L;
values = ref _headers._Authority; values = ref _headers._Authority;
nameStr = HeaderNames.Authority;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x495443454e4e4f43uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4e4fu)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x495443454e4e4f43uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4e4fu))
{ {
flag = 0x2L; flag = 0x2L;
values = ref _headers._Connection; values = ref _headers._Connection;
nameStr = HeaderNames.Connection;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfffdfdfdfdfuL) == 0x4547412d52455355uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x544eu)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfffdfdfdfdfuL) == 0x4547412d52455355uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x544eu))
{ {
flag = 0x80000000000L; flag = 0x80000000000L;
values = ref _headers._UserAgent; values = ref _headers._UserAgent;
nameStr = HeaderNames.UserAgent;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfffdfdfdfdfuL) == 0x494c412d5045454buL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4556u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfffdfdfdfdfuL) == 0x494c412d5045454buL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4556u))
{ {
flag = 0x8L; flag = 0x8L;
values = ref _headers._KeepAlive; values = ref _headers._KeepAlive;
nameStr = HeaderNames.KeepAlive;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfdfdfdfuL) == 0x2d54534555514552uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4449u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfdfdfdfuL) == 0x2d54534555514552uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4449u))
{ {
flag = 0x400000000000L; flag = 0x400000000000L;
values = ref _headers._RequestId; values = ref _headers._RequestId;
nameStr = HeaderNames.RequestId;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x4154534543415254uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4554u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x4154534543415254uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4554u))
{ {
flag = 0x2000000000000L; flag = 0x2000000000000L;
values = ref _headers._TraceState; values = ref _headers._TraceState;
nameStr = HeaderNames.TraceState;
} }
break; break;
case 11: case 11:
@ -6453,11 +6484,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x8000L; flag = 0x8000L;
values = ref _headers._ContentMD5; values = ref _headers._ContentMD5;
nameStr = HeaderNames.ContentMD5;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x5241504543415254uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4e45u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)10) & 0xdfu) == 0x54u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x5241504543415254uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(4 * sizeof(ushort)))) & 0xdfdfu) == 0x4e45u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)10) & 0xdfu) == 0x54u))
{ {
flag = 0x1000000000000L; flag = 0x1000000000000L;
values = ref _headers._TraceParent; values = ref _headers._TraceParent;
nameStr = HeaderNames.TraceParent;
} }
break; break;
case 12: case 12:
@ -6465,11 +6498,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x800L; flag = 0x800L;
values = ref _headers._ContentType; values = ref _headers._ContentType;
nameStr = HeaderNames.ContentType;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfffdfdfdfuL) == 0x57524f462d58414duL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x53445241u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfffdfdfdfuL) == 0x57524f462d58414duL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x53445241u))
{ {
flag = 0x2000000000L; flag = 0x2000000000L;
values = ref _headers._MaxForwards; values = ref _headers._MaxForwards;
nameStr = HeaderNames.MaxForwards;
} }
break; break;
case 13: case 13:
@ -6477,26 +6512,31 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x8000000L; flag = 0x8000000L;
values = ref _headers._Authorization; values = ref _headers._Authorization;
nameStr = HeaderNames.Authorization;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfffdfdfdfdfdfuL) == 0x4f432d4548434143uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x4f52544eu) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x4cu)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfffdfdfdfdfdfuL) == 0x4f432d4548434143uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x4f52544eu) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x4cu))
{ {
flag = 0x1L; flag = 0x1L;
values = ref _headers._CacheControl; values = ref _headers._CacheControl;
nameStr = HeaderNames.CacheControl;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfdfdfdfuL) == 0x2d544e45544e4f43uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x474e4152u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x45u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfdfdfdfuL) == 0x2d544e45544e4f43uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x474e4152u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x45u))
{ {
flag = 0x10000L; flag = 0x10000L;
values = ref _headers._ContentRange; values = ref _headers._ContentRange;
nameStr = HeaderNames.ContentRange;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfffdfdfuL) == 0x2d454e4f4e2d4649uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x4354414du) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x48u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfffdfdfuL) == 0x2d454e4f4e2d4649uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x4354414du) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x48u))
{ {
flag = 0x400000000L; flag = 0x400000000L;
values = ref _headers._IfNoneMatch; values = ref _headers._IfNoneMatch;
nameStr = HeaderNames.IfNoneMatch;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfffdfdfdfdfuL) == 0x444f4d2d5453414cuL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x45494649u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x44u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfffdfdfdfdfuL) == 0x444f4d2d5453414cuL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x45494649u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)12) & 0xdfu) == 0x44u))
{ {
flag = 0x40000L; flag = 0x40000L;
values = ref _headers._LastModified; values = ref _headers._LastModified;
nameStr = HeaderNames.LastModified;
} }
break; break;
case 14: case 14:
@ -6504,10 +6544,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x1000000L; flag = 0x1000000L;
values = ref _headers._AcceptCharset; values = ref _headers._AcceptCharset;
nameStr = HeaderNames.AcceptCharset;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfdfdfdfuL) == 0x2d544e45544e4f43uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x474e454cu) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(6 * sizeof(ushort)))) & 0xdfdfu) == 0x4854u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xffdfdfdfdfdfdfdfuL) == 0x2d544e45544e4f43uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x474e454cu) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(6 * sizeof(ushort)))) & 0xdfdfu) == 0x4854u))
{ {
AppendContentLength(value); if (ReferenceEquals(EncodingSelector, KestrelServerOptions.DefaultRequestHeaderEncodingSelector))
{
AppendContentLength(value);
}
else
{
AppendContentLengthCustomEncoding(value, EncodingSelector(HeaderNames.ContentLength));
}
return; return;
} }
break; break;
@ -6517,11 +6565,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x2000000L; flag = 0x2000000L;
values = ref _headers._AcceptEncoding; values = ref _headers._AcceptEncoding;
nameStr = HeaderNames.AcceptEncoding;
} }
else if ((firstTerm15 == 0x4c2d545045434341uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x55474e41u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(6 * sizeof(ushort)))) & 0xdfdfu) == 0x4741u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)14) & 0xdfu) == 0x45u)) else if ((firstTerm15 == 0x4c2d545045434341uL) && ((Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(2 * sizeof(uint)))) & 0xdfdfdfdfu) == 0x55474e41u) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(6 * sizeof(ushort)))) & 0xdfdfu) == 0x4741u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)14) & 0xdfu) == 0x45u))
{ {
flag = 0x4000000L; flag = 0x4000000L;
values = ref _headers._AcceptLanguage; values = ref _headers._AcceptLanguage;
nameStr = HeaderNames.AcceptLanguage;
} }
break; break;
case 16: case 16:
@ -6532,16 +6582,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x1000L; flag = 0x1000L;
values = ref _headers._ContentEncoding; values = ref _headers._ContentEncoding;
nameStr = HeaderNames.ContentEncoding;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfdfuL) == 0x45474155474e414cuL)) else if (((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfdfuL) == 0x45474155474e414cuL))
{ {
flag = 0x2000L; flag = 0x2000L;
values = ref _headers._ContentLanguage; values = ref _headers._ContentLanguage;
nameStr = HeaderNames.ContentLanguage;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfdfuL) == 0x4e4f495441434f4cuL)) else if (((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfdfuL) == 0x4e4f495441434f4cuL))
{ {
flag = 0x4000L; flag = 0x4000L;
values = ref _headers._ContentLocation; values = ref _headers._ContentLocation;
nameStr = HeaderNames.ContentLocation;
} }
} }
break; break;
@ -6550,11 +6603,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x200000000L; flag = 0x200000000L;
values = ref _headers._IfModifiedSince; values = ref _headers._IfModifiedSince;
nameStr = HeaderNames.IfModifiedSince;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x524546534e415254uL) && ((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfffuL) == 0x4e49444f434e452duL) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)16) & 0xdfu) == 0x47u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfdfdfdfuL) == 0x524546534e415254uL) && ((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfffuL) == 0x4e49444f434e452duL) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)16) & 0xdfu) == 0x47u))
{ {
flag = 0x40L; flag = 0x40L;
values = ref _headers._TransferEncoding; values = ref _headers._TransferEncoding;
nameStr = HeaderNames.TransferEncoding;
} }
break; break;
case 19: case 19:
@ -6562,16 +6617,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x800000000000L; flag = 0x800000000000L;
values = ref _headers._CorrelationContext; values = ref _headers._CorrelationContext;
nameStr = HeaderNames.CorrelationContext;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfffdfdfuL) == 0x444f4d4e552d4649uL) && ((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfffdfdfdfdfdfuL) == 0x49532d4445494649uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(8 * sizeof(ushort)))) & 0xdfdfu) == 0x434eu) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)18) & 0xdfu) == 0x45u)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfdfdfdfffdfdfuL) == 0x444f4d4e552d4649uL) && ((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfffdfdfdfdfdfuL) == 0x49532d4445494649uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(8 * sizeof(ushort)))) & 0xdfdfu) == 0x434eu) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)18) & 0xdfu) == 0x45u))
{ {
flag = 0x1000000000L; flag = 0x1000000000L;
values = ref _headers._IfUnmodifiedSince; values = ref _headers._IfUnmodifiedSince;
nameStr = HeaderNames.IfUnmodifiedSince;
} }
else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfffdfdfdfdfdfuL) == 0x55412d59584f5250uL) && ((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfdfuL) == 0x54415a49524f4854uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(8 * sizeof(ushort)))) & 0xdfdfu) == 0x4f49u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)18) & 0xdfu) == 0x4eu)) else if (((Unsafe.ReadUnaligned<ulong>(ref nameStart) & 0xdfdfffdfdfdfdfdfuL) == 0x55412d59584f5250uL) && ((Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof(ulong))) & 0xdfdfdfdfdfdfdfdfuL) == 0x54415a49524f4854uL) && ((Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)(8 * sizeof(ushort)))) & 0xdfdfu) == 0x4f49u) && ((Unsafe.AddByteOffset(ref nameStart, (IntPtr)18) & 0xdfu) == 0x4eu))
{ {
flag = 0x4000000000L; flag = 0x4000000000L;
values = ref _headers._ProxyAuthorization; values = ref _headers._ProxyAuthorization;
nameStr = HeaderNames.ProxyAuthorization;
} }
break; break;
case 25: case 25:
@ -6579,6 +6637,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x200000000000L; flag = 0x200000000000L;
values = ref _headers._UpgradeInsecureRequests; values = ref _headers._UpgradeInsecureRequests;
nameStr = HeaderNames.UpgradeInsecureRequests;
} }
break; break;
case 29: case 29:
@ -6586,6 +6645,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x8000000000000L; flag = 0x8000000000000L;
values = ref _headers._AccessControlRequestMethod; values = ref _headers._AccessControlRequestMethod;
nameStr = HeaderNames.AccessControlRequestMethod;
} }
break; break;
case 30: case 30:
@ -6593,6 +6653,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
flag = 0x10000000000000L; flag = 0x10000000000000L;
values = ref _headers._AccessControlRequestHeaders; values = ref _headers._AccessControlRequestHeaders;
nameStr = HeaderNames.AccessControlRequestHeaders;
} }
break; break;
} }
@ -6622,7 +6683,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
// We didn't have a previous matching header value, or have already added a header, so get the string for this value. // We didn't have a previous matching header value, or have already added a header, so get the string for this value.
var valueStr = value.GetRequestHeaderStringNonNullCharacters(UseLatin1); var valueStr = value.GetRequestHeaderString(nameStr, EncodingSelector);
if ((_bits & flag) == 0) if ((_bits & flag) == 0)
{ {
// We didn't already have a header set, so add a new one. // We didn't already have a header set, so add a new one.
@ -6640,8 +6701,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
// The header was not one of the "known" headers. // The header was not one of the "known" headers.
// Convert value to string first, because passing two spans causes 8 bytes stack zeroing in // Convert value to string first, because passing two spans causes 8 bytes stack zeroing in
// this method with rep stosd, which is slower than necessary. // this method with rep stosd, which is slower than necessary.
var valueStr = value.GetRequestHeaderStringNonNullCharacters(UseLatin1); nameStr = name.GetHeaderName();
AppendUnknownHeaders(name, valueStr); var valueStr = value.GetRequestHeaderString(nameStr, EncodingSelector);
AppendUnknownHeaders(nameStr, valueStr);
} }
} }

View File

@ -369,7 +369,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
ConnectionIdFeature = ConnectionId; ConnectionIdFeature = ConnectionId;
HttpRequestHeaders.Reset(); HttpRequestHeaders.Reset();
HttpRequestHeaders.UseLatin1 = ServerOptions.Latin1RequestHeaders; HttpRequestHeaders.EncodingSelector = ServerOptions.RequestHeaderEncodingSelector;
HttpRequestHeaders.ReuseHeaderValues = !ServerOptions.DisableStringReuse; HttpRequestHeaders.ReuseHeaderValues = !ServerOptions.DisableStringReuse;
HttpResponseHeaders.Reset(); HttpResponseHeaders.Reset();
RequestHeaders = HttpRequestHeaders; RequestHeaders = HttpRequestHeaders;
@ -532,7 +532,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
string key = name.GetHeaderName(); string key = name.GetHeaderName();
var valueStr = value.GetRequestHeaderStringNonNullCharacters(ServerOptions.Latin1RequestHeaders); var valueStr = value.GetRequestHeaderString(key, HttpRequestHeaders.EncodingSelector);
RequestTrailers.Append(key, valueStr); RequestTrailers.Append(key, valueStr);
} }

View File

@ -5,7 +5,9 @@ using System;
using System.Buffers.Text; using System.Buffers.Text;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
@ -17,12 +19,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private long _previousBits = 0; private long _previousBits = 0;
public bool ReuseHeaderValues { get; set; } public bool ReuseHeaderValues { get; set; }
public bool UseLatin1 { get; set; } public Func<string, Encoding> EncodingSelector { get; set; }
public HttpRequestHeaders(bool reuseHeaderValues = true, bool useLatin1 = false) public HttpRequestHeaders(bool reuseHeaderValues = true, Func<string, Encoding> encodingSelector = null)
{ {
ReuseHeaderValues = reuseHeaderValues; ReuseHeaderValues = reuseHeaderValues;
UseLatin1 = useLatin1; EncodingSelector = encodingSelector ?? KestrelServerOptions.DefaultRequestHeaderEncodingSelector;
} }
public void OnHeadersComplete() public void OnHeadersComplete()
@ -87,7 +89,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
parsed < 0 || parsed < 0 ||
consumed != value.Length) consumed != value.Length)
{ {
KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value.GetRequestHeaderStringNonNullCharacters(UseLatin1)); KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value.GetRequestHeaderString(HeaderNames.ContentLength, EncodingSelector));
}
_contentLength = parsed;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void AppendContentLengthCustomEncoding(ReadOnlySpan<byte> value, Encoding customEncoding)
{
if (_contentLength.HasValue)
{
KestrelBadHttpRequestException.Throw(RequestRejectionReason.MultipleContentLengths);
}
// long.MaxValue = 9223372036854775807 (19 chars)
Span<char> decodedChars = stackalloc char[20];
var numChars = customEncoding.GetChars(value, decodedChars);
long parsed = -1;
if (numChars > 19 ||
!long.TryParse(decodedChars.Slice(0, numChars), NumberStyles.Integer, CultureInfo.InvariantCulture, out parsed) ||
parsed < 0)
{
KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value.GetRequestHeaderString(HeaderNames.ContentLength, EncodingSelector));
} }
_contentLength = parsed; _contentLength = parsed;
@ -108,11 +133,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private unsafe void AppendUnknownHeaders(ReadOnlySpan<byte> name, string valueString) private unsafe void AppendUnknownHeaders(string name, string valueString)
{ {
string key = name.GetHeaderName(); Unknown.TryGetValue(name, out var existing);
Unknown.TryGetValue(key, out var existing); Unknown[name] = AppendValue(existing, valueString);
Unknown[key] = AppendValue(existing, valueString);
} }
public Enumerator GetEnumerator() public Enumerator GetEnumerator()

View File

@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
private const ulong _http10VersionLong = 3471766442030158920; // GetAsciiStringAsLong("HTTP/1.0"); const results in better codegen private const ulong _http10VersionLong = 3471766442030158920; // GetAsciiStringAsLong("HTTP/1.0"); const results in better codegen
private const ulong _http11VersionLong = 3543824036068086856; // GetAsciiStringAsLong("HTTP/1.1"); const results in better codegen private const ulong _http11VersionLong = 3543824036068086856; // GetAsciiStringAsLong("HTTP/1.1"); const results in better codegen
private static readonly UTF8EncodingSealed HeaderValueEncoding = new UTF8EncodingSealed(); private static readonly UTF8EncodingSealed DefaultRequestHeaderEncoding = new UTF8EncodingSealed();
private static readonly SpanAction<char, IntPtr> _getHeaderName = GetHeaderName; private static readonly SpanAction<char, IntPtr> _getHeaderName = GetHeaderName;
private static readonly SpanAction<char, IntPtr> _getAsciiStringNonNullCharacters = GetAsciiStringNonNullCharacters; private static readonly SpanAction<char, IntPtr> _getAsciiStringNonNullCharacters = GetAsciiStringNonNullCharacters;
@ -120,11 +120,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
public static string GetAsciiOrUTF8StringNonNullCharacters(this Span<byte> span)
=> GetAsciiOrUTF8StringNonNullCharacters((ReadOnlySpan<byte>)span);
public static string GetAsciiOrUTF8StringNonNullCharacters(this ReadOnlySpan<byte> span) public static string GetAsciiOrUTF8StringNonNullCharacters(this ReadOnlySpan<byte> span)
=> StringUtilities.GetAsciiOrUTF8StringNonNullCharacters(span, HeaderValueEncoding); => StringUtilities.GetAsciiOrUTF8StringNonNullCharacters(span, DefaultRequestHeaderEncoding);
private static unsafe void GetAsciiStringNonNullCharacters(Span<char> buffer, IntPtr state) private static unsafe void GetAsciiStringNonNullCharacters(Span<char> buffer, IntPtr state)
{ {
@ -139,8 +136,34 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
public static string GetRequestHeaderStringNonNullCharacters(this ReadOnlySpan<byte> span, bool useLatin1) => public static string GetRequestHeaderString(this ReadOnlySpan<byte> span, string name, Func<string, Encoding> encodingSelector)
useLatin1 ? span.GetLatin1StringNonNullCharacters() : span.GetAsciiOrUTF8StringNonNullCharacters(HeaderValueEncoding); {
if (ReferenceEquals(KestrelServerOptions.DefaultRequestHeaderEncodingSelector, encodingSelector))
{
return span.GetAsciiOrUTF8StringNonNullCharacters(DefaultRequestHeaderEncoding);
}
var encoding = encodingSelector(name);
if (encoding is null)
{
return span.GetAsciiOrUTF8StringNonNullCharacters(DefaultRequestHeaderEncoding);
}
if (ReferenceEquals(encoding, Encoding.Latin1))
{
return span.GetLatin1StringNonNullCharacters();
}
try
{
return encoding.GetString(span);
}
catch (DecoderFallbackException ex)
{
throw new InvalidOperationException(ex.Message, ex);
}
}
public static string GetAsciiStringEscaped(this ReadOnlySpan<byte> span, int maxChars) public static string GetAsciiStringEscaped(this ReadOnlySpan<byte> span, int maxChars)
{ {

View File

@ -255,8 +255,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel
ConfigurationReader = new ConfigurationReader(Configuration); ConfigurationReader = new ConfigurationReader(Configuration);
Options.Latin1RequestHeaders = ConfigurationReader.Latin1RequestHeaders;
LoadDefaultCert(ConfigurationReader); LoadDefaultCert(ConfigurationReader);
foreach (var endpoint in ConfigurationReader.Endpoints) foreach (var endpoint in ConfigurationReader.Endpoints)

View File

@ -35,12 +35,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
private IDisposable _configChangedRegistration; private IDisposable _configChangedRegistration;
public KestrelServer(IOptions<KestrelServerOptions> options, IEnumerable<IConnectionListenerFactory> transportFactories, ILoggerFactory loggerFactory) public KestrelServer(
IOptions<KestrelServerOptions> options,
IEnumerable<IConnectionListenerFactory> transportFactories,
ILoggerFactory loggerFactory)
: this(transportFactories, null, CreateServiceContext(options, loggerFactory)) : this(transportFactories, null, CreateServiceContext(options, loggerFactory))
{ {
} }
public KestrelServer(IOptions<KestrelServerOptions> options, IEnumerable<IConnectionListenerFactory> transportFactories, IEnumerable<IMultiplexedConnectionListenerFactory> multiplexedFactories, ILoggerFactory loggerFactory) public KestrelServer(
IOptions<KestrelServerOptions> options,
IEnumerable<IConnectionListenerFactory> transportFactories,
IEnumerable<IMultiplexedConnectionListenerFactory> multiplexedFactories,
ILoggerFactory loggerFactory)
: this(transportFactories, multiplexedFactories, CreateServiceContext(options, loggerFactory)) : this(transportFactories, multiplexedFactories, CreateServiceContext(options, loggerFactory))
{ {
} }
@ -52,7 +59,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
} }
// For testing // For testing
internal KestrelServer(IEnumerable<IConnectionListenerFactory> transportFactories, IEnumerable<IMultiplexedConnectionListenerFactory> multiplexedFactories, ServiceContext serviceContext) internal KestrelServer(
IEnumerable<IConnectionListenerFactory> transportFactories,
IEnumerable<IMultiplexedConnectionListenerFactory> multiplexedFactories,
ServiceContext serviceContext)
{ {
if (transportFactories == null) if (transportFactories == null)
{ {

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text;
using Microsoft.AspNetCore.Certificates.Generation; using Microsoft.AspNetCore.Certificates.Generation;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
@ -22,6 +23,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
/// </summary> /// </summary>
public class KestrelServerOptions public class KestrelServerOptions
{ {
// internal to fast-path header decoding when RequestHeaderEncodingSelector is unchanged.
internal static readonly Func<string, Encoding> DefaultRequestHeaderEncodingSelector = _ => null;
private Func<string, Encoding> _requestHeaderEncodingSelector = DefaultRequestHeaderEncodingSelector;
// The following two lists configure the endpoints that Kestrel should listen to. If both lists are empty, the "urls" config setting (e.g. UseUrls) is used. // The following two lists configure the endpoints that Kestrel should listen to. If both lists are empty, the "urls" config setting (e.g. UseUrls) is used.
internal List<ListenOptions> CodeBackedListenOptions { get; } = new List<ListenOptions>(); internal List<ListenOptions> CodeBackedListenOptions { get; } = new List<ListenOptions>();
internal List<ListenOptions> ConfigurationBackedListenOptions { get; } = new List<ListenOptions>(); internal List<ListenOptions> ConfigurationBackedListenOptions { get; } = new List<ListenOptions>();
@ -65,6 +71,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
/// </remarks> /// </remarks>
public bool DisableStringReuse { get; set; } = false; public bool DisableStringReuse { get; set; } = false;
/// <summary>
/// Controls whether to return the AltSvcHeader from on an HTTP/2 or lower response for HTTP/3
/// </summary>
/// <remarks>
/// Defaults to false.
/// </remarks>
public bool EnableAltSvc { get; set; } = false;
/// <summary>
/// Gets or sets a callback that returns the <see cref="Encoding"/> to decode the value for the specified request header name,
/// or <see langword="null"/> to use the default <see cref="UTF8Encoding"/>.
/// </summary>
public Func<string, Encoding> RequestHeaderEncodingSelector
{
get => _requestHeaderEncodingSelector;
set => _requestHeaderEncodingSelector = value ?? throw new ArgumentNullException(nameof(value));
}
/// <summary> /// <summary>
/// Enables the Listen options callback to resolve and use services registered by the application during startup. /// Enables the Listen options callback to resolve and use services registered by the application during startup.
/// Typically initialized by UseKestrel()"/>. /// Typically initialized by UseKestrel()"/>.
@ -78,15 +102,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
/// <summary> /// <summary>
/// Provides a configuration source where endpoints will be loaded from on server start. /// Provides a configuration source where endpoints will be loaded from on server start.
/// The default is null. /// The default is <see langword="null"/>.
/// </summary> /// </summary>
public KestrelConfigurationLoader ConfigurationLoader { get; set; } public KestrelConfigurationLoader ConfigurationLoader { get; set; }
/// <summary>
/// Controls whether to return the AltSvcHeader from on an HTTP/2 or lower response for HTTP/3
/// </summary>
public bool EnableAltSvc { get; set; } = false;
/// <summary> /// <summary>
/// A default configuration action for all endpoints. Use for Listen, configuration, the default url, and URLs. /// A default configuration action for all endpoints. Use for Listen, configuration, the default url, and URLs.
/// </summary> /// </summary>
@ -107,11 +126,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
/// </summary> /// </summary>
internal bool IsDevCertLoaded { get; set; } internal bool IsDevCertLoaded { get; set; }
/// <summary>
/// Treat request headers as Latin-1 or ISO/IEC 8859-1 instead of UTF-8.
/// </summary>
internal bool Latin1RequestHeaders { get; set; }
/// <summary> /// <summary>
/// Specifies a configuration Action to run for each newly created endpoint. Calling this again will replace /// Specifies a configuration Action to run for each newly created endpoint. Calling this again will replace
/// the prior action. /// the prior action.
@ -159,7 +173,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
if (DefaultCertificate == null && !IsDevCertLoaded) if (DefaultCertificate == null && !IsDevCertLoaded)
{ {
IsDevCertLoaded = true; // Only try once IsDevCertLoaded = true; // Only try once
var logger = ApplicationServices.GetRequiredService<ILogger<KestrelServer>>(); var logger = ApplicationServices!.GetRequiredService<ILogger<KestrelServer>>();
try try
{ {
DefaultCertificate = CertificateManager.Instance.ListCertificates(StoreName.My, StoreLocation.CurrentUser, isValid: true) DefaultCertificate = CertificateManager.Instance.ListCertificates(StoreName.My, StoreLocation.CurrentUser, isValid: true)
@ -220,7 +234,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
/// </summary> /// </summary>
/// <param name="config">The configuration section for Kestrel.</param> /// <param name="config">The configuration section for Kestrel.</param>
/// <param name="reloadOnChange"> /// <param name="reloadOnChange">
/// If <see langword="true" />, Kestrel will dynamically update endpoint bindings when configuration changes. /// If <see langword="true"/>, Kestrel will dynamically update endpoint bindings when configuration changes.
/// This will only reload endpoints defined in the "Endpoints" section of your <paramref name="config"/>. Endpoints defined in code will not be reloaded. /// This will only reload endpoints defined in the "Endpoints" section of your <paramref name="config"/>. Endpoints defined in code will not be reloaded.
/// </param> /// </param>
/// <returns>A <see cref="KestrelConfigurationLoader"/> for further endpoint configuration.</returns> /// <returns>A <see cref="KestrelConfigurationLoader"/> for further endpoint configuration.</returns>

View File

@ -8,6 +8,7 @@ using System.Text;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Xunit; using Xunit;
using static CodeGenerator.KnownHeaders; using static CodeGenerator.KnownHeaders;
@ -307,11 +308,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var headers = new HttpRequestHeaders(); var headers = new HttpRequestHeaders();
const string key = "\u00141\u00F3d\017c"; const string key = "\u00141\u00F3d\017c";
var encoding = Encoding.GetEncoding("iso-8859-1");
#pragma warning disable CS0618 // Type or member is obsolete #pragma warning disable CS0618 // Type or member is obsolete
var exception = Assert.Throws<BadHttpRequestException>( var exception = Assert.Throws<BadHttpRequestException>(
#pragma warning restore CS0618 // Type or member is obsolete #pragma warning restore CS0618 // Type or member is obsolete
() => headers.Append(encoding.GetBytes(key), Encoding.ASCII.GetBytes("value"))); () => headers.Append(Encoding.Latin1.GetBytes(key), Encoding.ASCII.GetBytes("value")));
Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
} }
@ -473,7 +473,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Throws<InvalidOperationException>(() => Assert.Throws<InvalidOperationException>(() =>
{ {
var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan();
var nextSpan = Encoding.GetEncoding("iso-8859-1").GetBytes(headerValueUtf16Latin1CrossOver).AsSpan(); var nextSpan = Encoding.Latin1.GetBytes(headerValueUtf16Latin1CrossOver).AsSpan();
Assert.False(nextSpan.SequenceEqual(Encoding.ASCII.GetBytes(headerValueUtf16Latin1CrossOver))); Assert.False(nextSpan.SequenceEqual(Encoding.ASCII.GetBytes(headerValueUtf16Latin1CrossOver)));
@ -490,7 +490,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[MemberData(nameof(KnownRequestHeaders))] [MemberData(nameof(KnownRequestHeaders))]
public void Latin1ValuesAcceptedInLatin1ModeButNotReused(bool reuseValue, KnownHeader header) public void Latin1ValuesAcceptedInLatin1ModeButNotReused(bool reuseValue, KnownHeader header)
{ {
var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue, useLatin1: true); var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue, _ => Encoding.Latin1);
var headerValue = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1 var headerValue = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1
for (var i = 0; i < headerValue.Length; i++) for (var i = 0; i < headerValue.Length; i++)
@ -517,19 +517,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
headerValueUtf16Latin1CrossOver = new string(headerValue.AsSpan().Slice(0, i + 1)); headerValueUtf16Latin1CrossOver = new string(headerValue.AsSpan().Slice(0, i + 1));
} }
headers.Reset();
var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan();
var latinValueSpan = Encoding.GetEncoding("iso-8859-1").GetBytes(headerValueUtf16Latin1CrossOver).AsSpan(); var latinValueSpan = Encoding.Latin1.GetBytes(headerValueUtf16Latin1CrossOver).AsSpan();
Assert.False(latinValueSpan.SequenceEqual(Encoding.ASCII.GetBytes(headerValueUtf16Latin1CrossOver))); Assert.False(latinValueSpan.SequenceEqual(Encoding.ASCII.GetBytes(headerValueUtf16Latin1CrossOver)));
headers.Reset();
headers.Append(headerName, latinValueSpan); headers.Append(headerName, latinValueSpan);
headers.OnHeadersComplete(); headers.OnHeadersComplete();
var parsedHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString(); var parsedHeaderValue1 = ((IHeaderDictionary)headers)[header.Name].ToString();
Assert.Equal(headerValueUtf16Latin1CrossOver, parsedHeaderValue); headers.Reset();
Assert.NotSame(headerValueUtf16Latin1CrossOver, parsedHeaderValue); headers.Append(headerName, latinValueSpan);
headers.OnHeadersComplete();
var parsedHeaderValue2 = ((IHeaderDictionary)headers)[header.Name].ToString();
Assert.Equal(headerValueUtf16Latin1CrossOver, parsedHeaderValue1);
Assert.Equal(parsedHeaderValue1, parsedHeaderValue2);
Assert.NotSame(parsedHeaderValue1, parsedHeaderValue2);
} }
// Reset back to Ascii // Reset back to Ascii
@ -541,7 +546,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[MemberData(nameof(KnownRequestHeaders))] [MemberData(nameof(KnownRequestHeaders))]
public void NullCharactersRejectedInUTF8AndLatin1Mode(bool useLatin1, KnownHeader header) public void NullCharactersRejectedInUTF8AndLatin1Mode(bool useLatin1, KnownHeader header)
{ {
var headers = new HttpRequestHeaders(useLatin1: useLatin1); var headers = new HttpRequestHeaders(encodingSelector: useLatin1 ? _ => Encoding.Latin1 : (Func<string, Encoding>)null);
var valueArray = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1 var valueArray = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1
for (var i = 0; i < valueArray.Length; i++) for (var i = 0; i < valueArray.Length; i++)
@ -569,6 +574,53 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
} }
} }
[Fact]
public void CanSpecifyEncodingBasedOnHeaderName()
{
const string headerValue = "Hello \u03a0";
var acceptNameBytes = Encoding.ASCII.GetBytes(HeaderNames.Accept);
var cookieNameBytes = Encoding.ASCII.GetBytes(HeaderNames.Cookie);
var headerValueBytes = Encoding.UTF8.GetBytes(headerValue);
var headers = new HttpRequestHeaders(encodingSelector: headerName =>
{
// For known headers, the HeaderNames value is passed in.
if (ReferenceEquals(headerName, HeaderNames.Accept))
{
return Encoding.GetEncoding("ASCII", EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback);
}
return Encoding.UTF8;
});
Assert.Throws<InvalidOperationException>(() => headers.Append(acceptNameBytes, headerValueBytes));
headers.Append(cookieNameBytes, headerValueBytes);
headers.OnHeadersComplete();
var parsedAcceptHeaderValue = ((IHeaderDictionary)headers)[HeaderNames.Accept].ToString();
var parsedCookieHeaderValue = ((IHeaderDictionary)headers)[HeaderNames.Cookie].ToString();
Assert.Empty(parsedAcceptHeaderValue);
Assert.Equal(headerValue, parsedCookieHeaderValue);
}
[Fact]
public void CanSpecifyEncodingForContentLength()
{
var contentLengthNameBytes = Encoding.ASCII.GetBytes(HeaderNames.ContentLength);
// Always 32 bits per code point, so not a superset of ASCII
var contentLengthValueBytes = Encoding.UTF32.GetBytes("1337");
var headers = new HttpRequestHeaders(encodingSelector: _ => Encoding.UTF32);
headers.Append(contentLengthNameBytes, contentLengthValueBytes);
headers.OnHeadersComplete();
Assert.Equal(1337, headers.ContentLength);
Assert.Throws<InvalidOperationException>(() =>
new HttpRequestHeaders().Append(contentLengthNameBytes, contentLengthValueBytes));
}
[Fact] [Fact]
public void ValueReuseNeverWhenUnknownHeader() public void ValueReuseNeverWhenUnknownHeader()
{ {

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Net; using System.Net;
using Xunit; using Xunit;
@ -60,5 +61,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// https://github.com/dotnet/aspnetcore/issues/21423 // https://github.com/dotnet/aspnetcore/issues/21423
options.ListenLocalhost(5000); options.ListenLocalhost(5000);
} }
[Fact]
public void SettingRequestHeaderEncodingSelecterThrowsArgumentNullException()
{
var options = new KestrelServerOptions();
var ex = Assert.Throws<ArgumentNullException>(() => options.RequestHeaderEncodingSelector = null);
Assert.Equal("value", ex.ParamName);
}
} }
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.Net.Http.Headers;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[InlineData(new byte[] { 0xef, 0xbf, 0xbd })] // 3 bytes: Replacement character, highest UTF-8 character currently encoded in the UTF-8 code page [InlineData(new byte[] { 0xef, 0xbf, 0xbd })] // 3 bytes: Replacement character, highest UTF-8 character currently encoded in the UTF-8 code page
private void FullUTF8RangeSupported(byte[] encodedBytes) private void FullUTF8RangeSupported(byte[] encodedBytes)
{ {
var s = HttpUtilities.GetRequestHeaderStringNonNullCharacters(encodedBytes.AsSpan(), useLatin1: false); var s = HttpUtilities.GetRequestHeaderString(encodedBytes.AsSpan(), HeaderNames.Accept, KestrelServerOptions.DefaultRequestHeaderEncodingSelector);
Assert.Equal(1, s.Length); Assert.Equal(1, s.Length);
} }
@ -35,7 +36,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var byteRange = Enumerable.Range(1, length).Select(x => (byte)x).ToArray(); var byteRange = Enumerable.Range(1, length).Select(x => (byte)x).ToArray();
Array.Copy(bytes, 0, byteRange, position, bytes.Length); Array.Copy(bytes, 0, byteRange, position, bytes.Length);
Assert.Throws<InvalidOperationException>(() => HttpUtilities.GetRequestHeaderStringNonNullCharacters(byteRange.AsSpan(), useLatin1: false)); Assert.Throws<InvalidOperationException>(() =>
HttpUtilities.GetRequestHeaderString(byteRange.AsSpan(), HeaderNames.Accept, KestrelServerOptions.DefaultRequestHeaderEncodingSelector));
} }
} }
} }

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Security.Authentication; using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https; using Microsoft.AspNetCore.Server.Kestrel.Https;
@ -587,27 +588,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
Assert.True(ran1); Assert.True(ran1);
} }
[Fact]
public void Latin1RequestHeadersReadFromConfig()
{
var options = CreateServerOptions();
var config = new ConfigurationBuilder().AddInMemoryCollection().Build();
Assert.False(options.Latin1RequestHeaders);
options.Configure(config).Load();
Assert.False(options.Latin1RequestHeaders);
options = CreateServerOptions();
config = new ConfigurationBuilder().AddInMemoryCollection(new[]
{
new KeyValuePair<string, string>("Latin1RequestHeaders", "true"),
}).Build();
Assert.False(options.Latin1RequestHeaders);
options.Configure(config).Load();
Assert.True(options.Latin1RequestHeaders);
}
[Fact] [Fact]
public void Reload_IdentifiesEndpointsToStartAndStop() public void Reload_IdentifiesEndpointsToStartAndStop()
{ {

View File

@ -2,7 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
@ -10,6 +12,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
private const int Iterations = 50; private const int Iterations = 50;
private string _headerName;
private byte[] _asciiBytes; private byte[] _asciiBytes;
private byte[] _utf8Bytes; private byte[] _utf8Bytes;
@ -27,24 +30,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
switch (Type) switch (Type)
{ {
case BenchmarkTypes.KeepAlive: case BenchmarkTypes.KeepAlive:
_headerName = HeaderNames.Connection;
// keep-alive // keep-alive
_asciiBytes = new byte[] { 0x6b, 0x65, 0x65, 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65 }; _asciiBytes = new byte[] { 0x6b, 0x65, 0x65, 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65 };
// kéép-álivé // kéép-álivé
_utf8Bytes = new byte[] { 0x6b, 0xc3, 0xa9, 0xc3, 0xa9, 0x70, 0x2d, 0xc3, 0xa1, 0x6c, 0x69, 0x76, 0xc3, 0xa9 }; _utf8Bytes = new byte[] { 0x6b, 0xc3, 0xa9, 0xc3, 0xa9, 0x70, 0x2d, 0xc3, 0xa1, 0x6c, 0x69, 0x76, 0xc3, 0xa9 };
break; break;
case BenchmarkTypes.Accept: case BenchmarkTypes.Accept:
_headerName = HeaderNames.Accept;
// text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7 // text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7
_asciiBytes = new byte[] { 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x38, 0x2c, 0x2a, 0x2f, 0x2a, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x37 }; _asciiBytes = new byte[] { 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x38, 0x2c, 0x2a, 0x2f, 0x2a, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x37 };
// téxt/pláin,téxt/html;q=0.9,ápplicátion/xhtml+xml;q=0.9,ápplicátion/xml;q=0.8,*/*;q=0.7 // téxt/pláin,téxt/html;q=0.9,ápplicátion/xhtml+xml;q=0.9,ápplicátion/xml;q=0.8,*/*;q=0.7
_utf8Bytes = new byte[] { 0x74, 0xc3, 0xa9, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0xc3, 0xa1, 0x69, 0x6e, 0x2c, 0x74, 0xc3, 0xa9, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0xc3, 0xa1, 0x70, 0x70, 0x6c, 0x69, 0x63, 0xc3, 0xa1, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0xc3, 0xa1, 0x70, 0x70, 0x6c, 0x69, 0x63, 0xc3, 0xa1, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x38, 0x2c, 0x2a, 0x2f, 0x2a, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x37 }; _utf8Bytes = new byte[] { 0x74, 0xc3, 0xa9, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0xc3, 0xa1, 0x69, 0x6e, 0x2c, 0x74, 0xc3, 0xa9, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0xc3, 0xa1, 0x70, 0x70, 0x6c, 0x69, 0x63, 0xc3, 0xa1, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x39, 0x2c, 0xc3, 0xa1, 0x70, 0x70, 0x6c, 0x69, 0x63, 0xc3, 0xa1, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x6d, 0x6c, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x38, 0x2c, 0x2a, 0x2f, 0x2a, 0x3b, 0x71, 0x3d, 0x30, 0x2e, 0x37 };
break; break;
case BenchmarkTypes.UserAgent: case BenchmarkTypes.UserAgent:
_headerName = HeaderNames.UserAgent;
// Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 // Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
_asciiBytes = new byte[] { 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0x2f, 0x35, 0x2e, 0x30, 0x20, 0x28, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e, 0x54, 0x20, 0x31, 0x30, 0x2e, 0x30, 0x3b, 0x20, 0x57, 0x4f, 0x57, 0x36, 0x34, 0x29, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x57, 0x65, 0x62, 0x4b, 0x69, 0x74, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36, 0x20, 0x28, 0x4b, 0x48, 0x54, 0x4d, 0x4c, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x47, 0x65, 0x63, 0x6b, 0x6f, 0x29, 0x20, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x2f, 0x35, 0x34, 0x2e, 0x30, 0x2e, 0x32, 0x38, 0x34, 0x30, 0x2e, 0x39, 0x39, 0x20, 0x53, 0x61, 0x66, 0x61, 0x72, 0x69, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36 }; _asciiBytes = new byte[] { 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0x2f, 0x35, 0x2e, 0x30, 0x20, 0x28, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e, 0x54, 0x20, 0x31, 0x30, 0x2e, 0x30, 0x3b, 0x20, 0x57, 0x4f, 0x57, 0x36, 0x34, 0x29, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x57, 0x65, 0x62, 0x4b, 0x69, 0x74, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36, 0x20, 0x28, 0x4b, 0x48, 0x54, 0x4d, 0x4c, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x47, 0x65, 0x63, 0x6b, 0x6f, 0x29, 0x20, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x2f, 0x35, 0x34, 0x2e, 0x30, 0x2e, 0x32, 0x38, 0x34, 0x30, 0x2e, 0x39, 0x39, 0x20, 0x53, 0x61, 0x66, 0x61, 0x72, 0x69, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36 };
// Mozillá/5.0 (Windows NT 10.0; WOW64) áppléWébKit/537.36 (KHTML, liké Gécko) Chromé/54.0.2840.99 Sáfári/537.36 // Mozillá/5.0 (Windows NT 10.0; WOW64) áppléWébKit/537.36 (KHTML, liké Gécko) Chromé/54.0.2840.99 Sáfári/537.36
_utf8Bytes = new byte[] { 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0xc3, 0xa1, 0x2f, 0x35, 0x2e, 0x30, 0x20, 0x28, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e, 0x54, 0x20, 0x31, 0x30, 0x2e, 0x30, 0x3b, 0x20, 0x57, 0x4f, 0x57, 0x36, 0x34, 0x29, 0x20, 0xc3, 0xa1, 0x70, 0x70, 0x6c, 0xc3, 0xa9, 0x57, 0xc3, 0xa9, 0x62, 0x4b, 0x69, 0x74, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36, 0x20, 0x28, 0x4b, 0x48, 0x54, 0x4d, 0x4c, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0xc3, 0xa9, 0x20, 0x47, 0xc3, 0xa9, 0x63, 0x6b, 0x6f, 0x29, 0x20, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0xc3, 0xa9, 0x2f, 0x35, 0x34, 0x2e, 0x30, 0x2e, 0x32, 0x38, 0x34, 0x30, 0x2e, 0x39, 0x39, 0x20, 0x53, 0xc3, 0xa1, 0x66, 0xc3, 0xa1, 0x72, 0x69, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36 }; _utf8Bytes = new byte[] { 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0xc3, 0xa1, 0x2f, 0x35, 0x2e, 0x30, 0x20, 0x28, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e, 0x54, 0x20, 0x31, 0x30, 0x2e, 0x30, 0x3b, 0x20, 0x57, 0x4f, 0x57, 0x36, 0x34, 0x29, 0x20, 0xc3, 0xa1, 0x70, 0x70, 0x6c, 0xc3, 0xa9, 0x57, 0xc3, 0xa9, 0x62, 0x4b, 0x69, 0x74, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36, 0x20, 0x28, 0x4b, 0x48, 0x54, 0x4d, 0x4c, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0xc3, 0xa9, 0x20, 0x47, 0xc3, 0xa9, 0x63, 0x6b, 0x6f, 0x29, 0x20, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0xc3, 0xa9, 0x2f, 0x35, 0x34, 0x2e, 0x30, 0x2e, 0x32, 0x38, 0x34, 0x30, 0x2e, 0x39, 0x39, 0x20, 0x53, 0xc3, 0xa1, 0x66, 0xc3, 0xa1, 0x72, 0x69, 0x2f, 0x35, 0x33, 0x37, 0x2e, 0x33, 0x36 };
break; break;
case BenchmarkTypes.Cookie: case BenchmarkTypes.Cookie:
_headerName = HeaderNames.Cookie;
// prov=20629ccd-8b0f-e8ef-2935-cd26609fc0bc; __qca=P0-1591065732-1479167353442; _ga=GA1.2.1298898376.1479167354; _gat=1; sgt=id=9519gfde_3347_4762_8762_df51458c8ec2; acct=t=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric&s=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric // prov=20629ccd-8b0f-e8ef-2935-cd26609fc0bc; __qca=P0-1591065732-1479167353442; _ga=GA1.2.1298898376.1479167354; _gat=1; sgt=id=9519gfde_3347_4762_8762_df51458c8ec2; acct=t=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric&s=why-is-%e0%a5%a7%e0%a5%a8%e0%a5%a9-numeric
_asciiBytes = new byte[] { 0x70, 0x72, 0x6f, 0x76, 0x3d, 0x32, 0x30, 0x36, 0x32, 0x39, 0x63, 0x63, 0x64, 0x2d, 0x38, 0x62, 0x30, 0x66, 0x2d, 0x65, 0x38, 0x65, 0x66, 0x2d, 0x32, 0x39, 0x33, 0x35, 0x2d, 0x63, 0x64, 0x32, 0x36, 0x36, 0x30, 0x39, 0x66, 0x63, 0x30, 0x62, 0x63, 0x3b, 0x20, 0x5f, 0x5f, 0x71, 0x63, 0x61, 0x3d, 0x50, 0x30, 0x2d, 0x31, 0x35, 0x39, 0x31, 0x30, 0x36, 0x35, 0x37, 0x33, 0x32, 0x2d, 0x31, 0x34, 0x37, 0x39, 0x31, 0x36, 0x37, 0x33, 0x35, 0x33, 0x34, 0x34, 0x32, 0x3b, 0x20, 0x5f, 0x67, 0x61, 0x3d, 0x47, 0x41, 0x31, 0x2e, 0x32, 0x2e, 0x31, 0x32, 0x39, 0x38, 0x38, 0x39, 0x38, 0x33, 0x37, 0x36, 0x2e, 0x31, 0x34, 0x37, 0x39, 0x31, 0x36, 0x37, 0x33, 0x35, 0x34, 0x3b, 0x20, 0x5f, 0x67, 0x61, 0x74, 0x3d, 0x31, 0x3b, 0x20, 0x73, 0x67, 0x74, 0x3d, 0x69, 0x64, 0x3d, 0x39, 0x35, 0x31, 0x39, 0x67, 0x66, 0x64, 0x65, 0x5f, 0x33, 0x33, 0x34, 0x37, 0x5f, 0x34, 0x37, 0x36, 0x32, 0x5f, 0x38, 0x37, 0x36, 0x32, 0x5f, 0x64, 0x66, 0x35, 0x31, 0x34, 0x35, 0x38, 0x63, 0x38, 0x65, 0x63, 0x32, 0x3b, 0x20, 0x61, 0x63, 0x63, 0x74, 0x3d, 0x74, 0x3d, 0x77, 0x68, 0x79, 0x2d, 0x69, 0x73, 0x2d, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x37, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x38, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x39, 0x2d, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x26, 0x73, 0x3d, 0x77, 0x68, 0x79, 0x2d, 0x69, 0x73, 0x2d, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x37, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x38, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x39, 0x2d, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63 }; _asciiBytes = new byte[] { 0x70, 0x72, 0x6f, 0x76, 0x3d, 0x32, 0x30, 0x36, 0x32, 0x39, 0x63, 0x63, 0x64, 0x2d, 0x38, 0x62, 0x30, 0x66, 0x2d, 0x65, 0x38, 0x65, 0x66, 0x2d, 0x32, 0x39, 0x33, 0x35, 0x2d, 0x63, 0x64, 0x32, 0x36, 0x36, 0x30, 0x39, 0x66, 0x63, 0x30, 0x62, 0x63, 0x3b, 0x20, 0x5f, 0x5f, 0x71, 0x63, 0x61, 0x3d, 0x50, 0x30, 0x2d, 0x31, 0x35, 0x39, 0x31, 0x30, 0x36, 0x35, 0x37, 0x33, 0x32, 0x2d, 0x31, 0x34, 0x37, 0x39, 0x31, 0x36, 0x37, 0x33, 0x35, 0x33, 0x34, 0x34, 0x32, 0x3b, 0x20, 0x5f, 0x67, 0x61, 0x3d, 0x47, 0x41, 0x31, 0x2e, 0x32, 0x2e, 0x31, 0x32, 0x39, 0x38, 0x38, 0x39, 0x38, 0x33, 0x37, 0x36, 0x2e, 0x31, 0x34, 0x37, 0x39, 0x31, 0x36, 0x37, 0x33, 0x35, 0x34, 0x3b, 0x20, 0x5f, 0x67, 0x61, 0x74, 0x3d, 0x31, 0x3b, 0x20, 0x73, 0x67, 0x74, 0x3d, 0x69, 0x64, 0x3d, 0x39, 0x35, 0x31, 0x39, 0x67, 0x66, 0x64, 0x65, 0x5f, 0x33, 0x33, 0x34, 0x37, 0x5f, 0x34, 0x37, 0x36, 0x32, 0x5f, 0x38, 0x37, 0x36, 0x32, 0x5f, 0x64, 0x66, 0x35, 0x31, 0x34, 0x35, 0x38, 0x63, 0x38, 0x65, 0x63, 0x32, 0x3b, 0x20, 0x61, 0x63, 0x63, 0x74, 0x3d, 0x74, 0x3d, 0x77, 0x68, 0x79, 0x2d, 0x69, 0x73, 0x2d, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x37, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x38, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x39, 0x2d, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x26, 0x73, 0x3d, 0x77, 0x68, 0x79, 0x2d, 0x69, 0x73, 0x2d, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x37, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x38, 0x25, 0x65, 0x30, 0x25, 0x61, 0x35, 0x25, 0x61, 0x39, 0x2d, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63 };
// prov=20629ccd-8b0f-é8éf-2935-cd26609fc0bc; __qcá=P0-1591065732-1479167353442; _gá=Gá1.2.1298898376.1479167354; _gát=1; sgt=id=9519gfdé_3347_4762_8762_df51458c8éc2; ácct=t=why-is-%é0%á5%á7%é0%á5%á8%é0%á5%á9-numéric&s=why-is-%é0%á5%á7%é0%á5%á8%é0%á5%á9-numéric // prov=20629ccd-8b0f-é8éf-2935-cd26609fc0bc; __qcá=P0-1591065732-1479167353442; _gá=Gá1.2.1298898376.1479167354; _gát=1; sgt=id=9519gfdé_3347_4762_8762_df51458c8éc2; ácct=t=why-is-%é0%á5%á7%é0%á5%á8%é0%á5%á9-numéric&s=why-is-%é0%á5%á7%é0%á5%á8%é0%á5%á9-numéric
@ -67,7 +74,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{ {
for (uint i = 0; i < Iterations; i++) for (uint i = 0; i < Iterations; i++)
{ {
HttpUtilities.GetRequestHeaderStringNonNullCharacters(_utf8Bytes, useLatin1: false); HttpUtilities.GetRequestHeaderString(_utf8Bytes, _headerName, KestrelServerOptions.DefaultRequestHeaderEncodingSelector);
} }
} }

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Microsoft.Net.Http.Headers;
namespace CodeGenerator namespace CodeGenerator
{ {
@ -230,23 +231,39 @@ namespace CodeGenerator
firstTermVar = ""; firstTermVar = "";
} }
string GenerateIfBody(KnownHeader header, string extraIndent = "")
{
if (header.Identifier == "ContentLength")
{
return $@"
{extraIndent}if (ReferenceEquals(EncodingSelector, KestrelServerOptions.DefaultRequestHeaderEncodingSelector))
{extraIndent}{{
{extraIndent} AppendContentLength(value);
{extraIndent}}}
{extraIndent}else
{extraIndent}{{
{extraIndent} AppendContentLengthCustomEncoding(value, EncodingSelector(HeaderNames.ContentLength));
{extraIndent}}}
{extraIndent}return;";
}
else
{
return $@"
{extraIndent}flag = {header.FlagBit()};
{extraIndent}values = ref _headers._{header.Identifier};
{extraIndent}nameStr = HeaderNames.{header.Identifier};";
}
}
var groups = values.GroupBy(header => header.EqualIgnoreCaseBytesFirstTerm()); var groups = values.GroupBy(header => header.EqualIgnoreCaseBytesFirstTerm());
return start + $@"{Each(groups, (byFirstTerm, i) => $@"{(byFirstTerm.Count() == 1 ? $@"{Each(byFirstTerm, header => $@" return start + $@"{Each(groups, (byFirstTerm, i) => $@"{(byFirstTerm.Count() == 1 ? $@"{Each(byFirstTerm, header => $@"
{(i > 0 ? "else " : "")}if ({header.EqualIgnoreCaseBytes(firstTermVar)}) {(i > 0 ? "else " : "")}if ({header.EqualIgnoreCaseBytes(firstTermVar)})
{{{(header.Identifier == "ContentLength" ? $@" {{{GenerateIfBody(header)}
AppendContentLength(value);
return;" : $@"
flag = {header.FlagBit()};
values = ref _headers._{header.Identifier};")}
}}")}" : $@" }}")}" : $@"
if ({byFirstTerm.Key.Replace(firstTermVarExpression, firstTermVar)}) if ({byFirstTerm.Key.Replace(firstTermVarExpression, firstTermVar)})
{{{Each(byFirstTerm, (header, i) => $@" {{{Each(byFirstTerm, (header, i) => $@"
{(i > 0 ? "else " : "")}if ({header.EqualIgnoreCaseBytesSecondTermOnwards()}) {(i > 0 ? "else " : "")}if ({header.EqualIgnoreCaseBytesSecondTermOnwards()})
{{{(header.Identifier == "ContentLength" ? $@" {{{GenerateIfBody(header, extraIndent: " ")}
AppendContentLength(value);
return;" : $@"
flag = {header.FlagBit()};
values = ref _headers._{header.Identifier};")}
}}")} }}")}
}}")}")}"; }}")}")}";
} }
@ -986,6 +1003,7 @@ $@" private void Clear(long bitsToClear)
public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value) public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
{{ {{
ref byte nameStart = ref MemoryMarshal.GetReference(name); ref byte nameStart = ref MemoryMarshal.GetReference(name);
var nameStr = string.Empty;
ref StringValues values = ref Unsafe.AsRef<StringValues>(null); ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
var flag = 0L; var flag = 0L;
@ -1017,7 +1035,7 @@ $@" private void Clear(long bitsToClear)
}} }}
// We didn't have a previous matching header value, or have already added a header, so get the string for this value. // We didn't have a previous matching header value, or have already added a header, so get the string for this value.
var valueStr = value.GetRequestHeaderStringNonNullCharacters(UseLatin1); var valueStr = value.GetRequestHeaderString(nameStr, EncodingSelector);
if ((_bits & flag) == 0) if ((_bits & flag) == 0)
{{ {{
// We didn't already have a header set, so add a new one. // We didn't already have a header set, so add a new one.
@ -1035,8 +1053,9 @@ $@" private void Clear(long bitsToClear)
// The header was not one of the ""known"" headers. // The header was not one of the ""known"" headers.
// Convert value to string first, because passing two spans causes 8 bytes stack zeroing in // Convert value to string first, because passing two spans causes 8 bytes stack zeroing in
// this method with rep stosd, which is slower than necessary. // this method with rep stosd, which is slower than necessary.
var valueStr = value.GetRequestHeaderStringNonNullCharacters(UseLatin1); nameStr = name.GetHeaderName();
AppendUnknownHeaders(name, valueStr); var valueStr = value.GetRequestHeaderString(nameStr, EncodingSelector);
AppendUnknownHeaders(nameStr, valueStr);
}} }}
}}" : "")} }}" : "")}

View File

@ -4609,7 +4609,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Fact] [Fact]
public async Task HEADERS_Received_Latin1_AcceptedWhenLatin1OptionIsConfigured() public async Task HEADERS_Received_Latin1_AcceptedWhenLatin1OptionIsConfigured()
{ {
_serviceContext.ServerOptions.Latin1RequestHeaders = true; _serviceContext.ServerOptions.RequestHeaderEncodingSelector = _ => Encoding.Latin1;
await InitializeConnectionAsync(context => await InitializeConnectionAsync(context =>
{ {

View File

@ -406,7 +406,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
void IHttpHeadersHandler.OnHeader(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value) void IHttpHeadersHandler.OnHeader(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
{ {
_decodedHeaders[name.GetAsciiStringNonNullCharacters()] = value.GetRequestHeaderStringNonNullCharacters(useLatin1: _serviceContext.ServerOptions.Latin1RequestHeaders); var nameStr = name.GetHeaderName();
_decodedHeaders[nameStr] = value.GetRequestHeaderString(nameStr, _serviceContext.ServerOptions.RequestHeaderEncodingSelector);
} }
void IHttpHeadersHandler.OnHeadersComplete(bool endStream) { } void IHttpHeadersHandler.OnHeadersComplete(bool endStream) { }

View File

@ -356,7 +356,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public void OnStaticIndexedHeader(int index) public void OnStaticIndexedHeader(int index)
{ {
var knownHeader = H3StaticTable.GetHeaderFieldAt(index); var knownHeader = H3StaticTable.GetHeaderFieldAt(index);
_decodedHeaders[((Span<byte>)knownHeader.Name).GetAsciiStringNonNullCharacters()] = HttpUtilities.GetAsciiOrUTF8StringNonNullCharacters(knownHeader.Value); _decodedHeaders[((Span<byte>)knownHeader.Name).GetAsciiStringNonNullCharacters()] = HttpUtilities.GetAsciiOrUTF8StringNonNullCharacters((ReadOnlySpan<byte>)knownHeader.Value);
} }
public void OnStaticIndexedHeader(int index, ReadOnlySpan<byte> value) public void OnStaticIndexedHeader(int index, ReadOnlySpan<byte> value)

View File

@ -2000,7 +2000,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
{ {
var testContext = new TestServiceContext(LoggerFactory); var testContext = new TestServiceContext(LoggerFactory);
testContext.ServerOptions.Latin1RequestHeaders = true; testContext.ServerOptions.RequestHeaderEncodingSelector = _ => Encoding.Latin1;
await using (var server = new TestServer(context => await using (var server = new TestServer(context =>
{ {
@ -2058,6 +2058,42 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
} }
} }
[Fact]
public async Task CustomRequestHeaderEncodingSelectorCanBeConfigured()
{
var testContext = new TestServiceContext(LoggerFactory);
testContext.ServerOptions.RequestHeaderEncodingSelector = _ => Encoding.UTF32;
await using (var server = new TestServer(context =>
{
Assert.Equal("£", context.Request.Headers["X-Test"]);
return Task.CompletedTask;
}, testContext))
{
using (var connection = server.CreateConnection())
{
await connection.Send(
"GET / HTTP/1.1",
"Host:",
"X-Test: ");
await connection.Stream.WriteAsync(Encoding.UTF32.GetBytes("£")).DefaultTimeout();
await connection.Send("",
"",
"");
await connection.Receive(
"HTTP/1.1 200 OK",
$"Date: {testContext.DateHeaderValue}",
"Content-Length: 0",
"",
"");
}
}
}
public static TheoryData<string, string> HostHeaderData => HttpParsingData.HostHeaderData; public static TheoryData<string, string> HostHeaderData => HttpParsingData.HostHeaderData;
private class IntAsClass private class IntAsClass

View File

@ -15,6 +15,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{ {
internal static class StringUtilities internal static class StringUtilities
{ {
private static readonly SpanAction<char, IntPtr> s_getAsciiOrUtf8StringNonNullCharacters = GetAsciiStringNonNullCharacters;
private static string GetAsciiOrUTF8StringNonNullCharacters(this Span<byte> span, Encoding defaultEncoding) private static string GetAsciiOrUTF8StringNonNullCharacters(this Span<byte> span, Encoding defaultEncoding)
=> GetAsciiOrUTF8StringNonNullCharacters((ReadOnlySpan<byte>)span, defaultEncoding); => GetAsciiOrUTF8StringNonNullCharacters((ReadOnlySpan<byte>)span, defaultEncoding);
@ -52,15 +54,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
} }
} }
private static readonly SpanAction<char, IntPtr> s_getAsciiOrUtf8StringNonNullCharacters = GetAsciiOrUTF8StringNonNullCharacters; private static unsafe void GetAsciiStringNonNullCharacters(Span<char> buffer, IntPtr state)
private static unsafe void GetAsciiOrUTF8StringNonNullCharacters(Span<char> buffer, IntPtr state)
{ {
fixed (char* output = &MemoryMarshal.GetReference(buffer)) fixed (char* output = &MemoryMarshal.GetReference(buffer))
{ {
// This version if AsciiUtilities returns null if there are any null (0 byte) characters // This version if AsciiUtilities returns false if there are any null ('\0') or non-Ascii
// in the string // character (> 127) in the string.
if (!StringUtilities.TryGetAsciiString((byte*)state.ToPointer(), output, buffer.Length)) if (!TryGetAsciiString((byte*)state.ToPointer(), output, buffer.Length))
{ {
// Mark resultString for UTF-8 encoding // Mark resultString for UTF-8 encoding
output[0] = '\0'; output[0] = '\0';