Merge branch 'master' into johluo/migrate-more-extensions-logging

This commit is contained in:
John Luo 2020-04-01 23:35:01 -07:00 committed by GitHub
commit 5f6fbed915
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 2365 additions and 742 deletions

View File

@ -13,201 +13,201 @@
<Uri>https://github.com/dotnet/blazor</Uri>
<Sha>dd7fb4d3931d556458f62642c2edfc59f6295bfb</Sha>
</Dependency>
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="5.0.0-preview.4.20201.1">
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="5.0.0-preview.4.20201.4">
<Uri>https://github.com/dotnet/aspnetcore-tooling</Uri>
<Sha>96c3140396e48633ddccf327129b55abde0b1b47</Sha>
<Sha>4ec71cb57e45db101bbd4ffcf64dafa1711de0af</Sha>
</Dependency>
<Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="5.0.0-preview.4.20201.1">
<Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="5.0.0-preview.4.20201.4">
<Uri>https://github.com/dotnet/aspnetcore-tooling</Uri>
<Sha>96c3140396e48633ddccf327129b55abde0b1b47</Sha>
<Sha>4ec71cb57e45db101bbd4ffcf64dafa1711de0af</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Razor" Version="5.0.0-preview.4.20201.1">
<Dependency Name="Microsoft.CodeAnalysis.Razor" Version="5.0.0-preview.4.20201.4">
<Uri>https://github.com/dotnet/aspnetcore-tooling</Uri>
<Sha>96c3140396e48633ddccf327129b55abde0b1b47</Sha>
<Sha>4ec71cb57e45db101bbd4ffcf64dafa1711de0af</Sha>
</Dependency>
<Dependency Name="Microsoft.NET.Sdk.Razor" Version="5.0.0-preview.4.20201.1">
<Dependency Name="Microsoft.NET.Sdk.Razor" Version="5.0.0-preview.4.20201.4">
<Uri>https://github.com/dotnet/aspnetcore-tooling</Uri>
<Sha>96c3140396e48633ddccf327129b55abde0b1b47</Sha>
<Sha>4ec71cb57e45db101bbd4ffcf64dafa1711de0af</Sha>
</Dependency>
<Dependency Name="dotnet-ef" Version="5.0.0-preview.4.20181.3">
<Dependency Name="dotnet-ef" Version="5.0.0-preview.4.20201.1">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>7eac3aac8aa7956eb80c524409a075fb1efa1ada</Sha>
<Sha>0f28f7168a1a6b1f34ccc4546eb6d5d667fee011</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.4.20181.3">
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.4.20201.1">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>7eac3aac8aa7956eb80c524409a075fb1efa1ada</Sha>
<Sha>0f28f7168a1a6b1f34ccc4546eb6d5d667fee011</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-preview.4.20181.3">
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-preview.4.20201.1">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>7eac3aac8aa7956eb80c524409a075fb1efa1ada</Sha>
<Sha>0f28f7168a1a6b1f34ccc4546eb6d5d667fee011</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-preview.4.20181.3">
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-preview.4.20201.1">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>7eac3aac8aa7956eb80c524409a075fb1efa1ada</Sha>
<Sha>0f28f7168a1a6b1f34ccc4546eb6d5d667fee011</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.4.20181.3">
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.4.20201.1">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>7eac3aac8aa7956eb80c524409a075fb1efa1ada</Sha>
<Sha>0f28f7168a1a6b1f34ccc4546eb6d5d667fee011</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-preview.4.20181.3">
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-preview.4.20201.1">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>7eac3aac8aa7956eb80c524409a075fb1efa1ada</Sha>
<Sha>0f28f7168a1a6b1f34ccc4546eb6d5d667fee011</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.4.20181.3">
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.4.20201.1">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>7eac3aac8aa7956eb80c524409a075fb1efa1ada</Sha>
<Sha>0f28f7168a1a6b1f34ccc4546eb6d5d667fee011</Sha>
</Dependency>
<Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Internal.Extensions.Refs" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Microsoft.Internal.Extensions.Refs" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
<Uri>https://github.com/dotnet/runtime</Uri>
@ -316,25 +316,25 @@
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>e1fa5d7648d46f067e265211fc2c695d409fe788</Sha>
</Dependency>
<Dependency Name="Internal.AspNetCore.Analyzers" Version="5.0.0-preview.4.20201.1" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Dependency Name="Internal.AspNetCore.Analyzers" Version="5.0.0-preview.4.20201.2" CoherentParentDependency="Microsoft.AspNetCore.Razor.Language">
<Uri>https://github.com/dotnet/extensions</Uri>
<Sha>050d3aea0c8b18579c426d7ff2cb196953540327</Sha>
<Sha>03c40031d618f923aa88da125cb078aabde9ebb1</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.20171.1">
<Dependency Name="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.20180.5">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>7dbc907fa03eacf4c57f827cb4235d77b7ed4fcd</Sha>
<Sha>09bb9d929120b402348c9a0e9c8c951e824059aa</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20171.1">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20180.5">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>7dbc907fa03eacf4c57f827cb4235d77b7ed4fcd</Sha>
<Sha>09bb9d929120b402348c9a0e9c8c951e824059aa</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20171.1">
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20180.5">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>7dbc907fa03eacf4c57f827cb4235d77b7ed4fcd</Sha>
<Sha>09bb9d929120b402348c9a0e9c8c951e824059aa</Sha>
</Dependency>
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.6.0-3.20177.6" CoherentParentDependency="Microsoft.Extensions.Logging">
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.6.0-3.20201.6" CoherentParentDependency="Microsoft.Extensions.Logging">
<Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>c9f2423cb5a2ab1ee8de0ef10e536d7672b1a2ea</Sha>
<Sha>8167e4880190407325d6cf7282f6bb62267abc56</Sha>
</Dependency>
</ToolsetDependencies>
</Dependencies>

View File

@ -62,9 +62,9 @@
-->
<PropertyGroup Label="Automated">
<!-- Packages from dotnet/arcade -->
<MicrosoftDotNetGenAPIPackageVersion>5.0.0-beta.20171.1</MicrosoftDotNetGenAPIPackageVersion>
<MicrosoftDotNetGenAPIPackageVersion>5.0.0-beta.20180.5</MicrosoftDotNetGenAPIPackageVersion>
<!-- Packages from dotnet/roslyn -->
<MicrosoftNetCompilersToolsetPackageVersion>3.6.0-3.20177.6</MicrosoftNetCompilersToolsetPackageVersion>
<MicrosoftNetCompilersToolsetPackageVersion>3.6.0-3.20201.6</MicrosoftNetCompilersToolsetPackageVersion>
<!-- Packages from dotnet/core-setup -->
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-preview.4-runtime.20201.1</MicrosoftExtensionsDependencyModelPackageVersion>
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-preview.4.20201.1</MicrosoftNETCoreAppInternalPackageVersion>
@ -96,58 +96,58 @@
<!-- Packages from dotnet/blazor -->
<MicrosoftAspNetCoreBlazorMonoPackageVersion>3.2.0-preview1.20067.1</MicrosoftAspNetCoreBlazorMonoPackageVersion>
<!-- Packages from dotnet/extensions -->
<InternalAspNetCoreAnalyzersPackageVersion>5.0.0-preview.4.20201.1</InternalAspNetCoreAnalyzersPackageVersion>
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>5.0.0-preview.4.20201.1</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsCachingSqlServerPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsCachingSqlServerPackageVersion>
<MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsHostingAbstractionsPackageVersion>
<MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsHostingPackageVersion>
<MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsHttpPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingEventLogPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.4.20201.1</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftInternalExtensionsRefsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftInternalExtensionsRefsPackageVersion>
<InternalAspNetCoreAnalyzersPackageVersion>5.0.0-preview.4.20201.2</InternalAspNetCoreAnalyzersPackageVersion>
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>5.0.0-preview.4.20201.2</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsCachingSqlServerPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsCachingSqlServerPackageVersion>
<MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsHostingAbstractionsPackageVersion>
<MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsHostingPackageVersion>
<MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsHttpPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingEventLogPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.4.20201.2</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftInternalExtensionsRefsPackageVersion>5.0.0-preview.4.20201.2</MicrosoftInternalExtensionsRefsPackageVersion>
<!-- Packages from dotnet/efcore -->
<dotnetefPackageVersion>5.0.0-preview.4.20181.3</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.4.20181.3</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.4.20181.3</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.4.20181.3</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.4.20181.3</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.4.20181.3</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.4.20181.3</MicrosoftEntityFrameworkCorePackageVersion>
<dotnetefPackageVersion>5.0.0-preview.4.20201.1</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.4.20201.1</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.4.20201.1</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.4.20201.1</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.4.20201.1</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.4.20201.1</MicrosoftEntityFrameworkCorePackageVersion>
<!-- Packages from dotnet/aspnetcore-tooling -->
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>5.0.0-preview.4.20201.1</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
<MicrosoftAspNetCoreRazorLanguagePackageVersion>5.0.0-preview.4.20201.1</MicrosoftAspNetCoreRazorLanguagePackageVersion>
<MicrosoftCodeAnalysisRazorPackageVersion>5.0.0-preview.4.20201.1</MicrosoftCodeAnalysisRazorPackageVersion>
<MicrosoftNETSdkRazorPackageVersion>5.0.0-preview.4.20201.1</MicrosoftNETSdkRazorPackageVersion>
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>5.0.0-preview.4.20201.4</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
<MicrosoftAspNetCoreRazorLanguagePackageVersion>5.0.0-preview.4.20201.4</MicrosoftAspNetCoreRazorLanguagePackageVersion>
<MicrosoftCodeAnalysisRazorPackageVersion>5.0.0-preview.4.20201.4</MicrosoftCodeAnalysisRazorPackageVersion>
<MicrosoftNETSdkRazorPackageVersion>5.0.0-preview.4.20201.4</MicrosoftNETSdkRazorPackageVersion>
</PropertyGroup>
<!--

View File

@ -2,15 +2,16 @@
usage()
{
echo "Usage: $0 [BuildArch] [LinuxCodeName] [lldbx.y] [--skipunmount] --rootfsdir <directory>]"
echo "Usage: $0 [BuildArch] [CodeName] [lldbx.y] [--skipunmount] --rootfsdir <directory>]"
echo "BuildArch can be: arm(default), armel, arm64, x86"
echo "LinuxCodeName - optional, Code name for Linux, can be: trusty, xenial(default), zesty, bionic, alpine. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen."
echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine"
echo "CodeName - optional, Code name for Linux, can be: trusty, xenial(default), zesty, bionic, alpine. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen."
echo " for FreeBSD can be: freebsd11 or freebsd12."
echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine and FReeBSD"
echo "--skipunmount - optional, will skip the unmount of rootfs folder."
exit 1
}
__LinuxCodeName=xenial
__CodeName=xenial
__CrossDir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
__InitialDir=$PWD
__BuildArch=arm
@ -53,6 +54,15 @@ __AlpinePackages+=" krb5-dev"
__AlpinePackages+=" openssl-dev"
__AlpinePackages+=" zlib-dev"
__FreeBSDBase="12.1-RELEASE"
__FreeBSDPkg="1.10.5"
__FreeBSDPackages="libunwind"
__FreeBSDPackages+=" icu"
__FreeBSDPackages+=" libinotify"
__FreeBSDPackages+=" lttng-ust"
__FreeBSDPackages+=" llvm-90"
__FreeBSDPackages+=" krb5"
__UnprocessedBuildArgs=
while :; do
if [ $# -le 0 ]; then
@ -81,7 +91,7 @@ while :; do
__BuildArch=armel
__UbuntuArch=armel
__UbuntuRepo="http://ftp.debian.org/debian/"
__LinuxCodeName=jessie
__CodeName=jessie
;;
x86)
__BuildArch=x86
@ -110,36 +120,36 @@ while :; do
unset __LLDB_Package
;;
trusty) # Ubuntu 14.04
if [ "$__LinuxCodeName" != "jessie" ]; then
__LinuxCodeName=trusty
if [ "$__CodeName" != "jessie" ]; then
__CodeName=trusty
fi
;;
xenial) # Ubuntu 16.04
if [ "$__LinuxCodeName" != "jessie" ]; then
__LinuxCodeName=xenial
if [ "$__CodeName" != "jessie" ]; then
__CodeName=xenial
fi
;;
zesty) # Ubuntu 17.04
if [ "$__LinuxCodeName" != "jessie" ]; then
__LinuxCodeName=zesty
if [ "$__CodeName" != "jessie" ]; then
__CodeName=zesty
fi
;;
bionic) # Ubuntu 18.04
if [ "$__LinuxCodeName" != "jessie" ]; then
__LinuxCodeName=bionic
if [ "$__CodeName" != "jessie" ]; then
__CodeName=bionic
fi
;;
jessie) # Debian 8
__LinuxCodeName=jessie
__CodeName=jessie
__UbuntuRepo="http://ftp.debian.org/debian/"
;;
stretch) # Debian 9
__LinuxCodeName=stretch
__CodeName=stretch
__UbuntuRepo="http://ftp.debian.org/debian/"
__LLDB_Package="liblldb-6.0-dev"
;;
buster) # Debian 10
__LinuxCodeName=buster
__CodeName=buster
__UbuntuRepo="http://ftp.debian.org/debian/"
__LLDB_Package="liblldb-6.0-dev"
;;
@ -149,14 +159,22 @@ while :; do
usage;
exit 1;
fi
__LinuxCodeName=
__CodeName=
__UbuntuRepo=
__Tizen=tizen
;;
alpine)
__LinuxCodeName=alpine
__CodeName=alpine
__UbuntuRepo=
;;
freebsd11)
__FreeBSDBase="11.3-RELEASE"
;&
freebsd12)
__CodeName=freebsd
__BuildArch=x64
__SkipUnmount=1
;;
--skipunmount)
__SkipUnmount=1
;;
@ -192,7 +210,7 @@ if [ -d "$__RootfsDir" ]; then
rm -rf $__RootfsDir
fi
if [[ "$__LinuxCodeName" == "alpine" ]]; then
if [[ "$__CodeName" == "alpine" ]]; then
__ApkToolsVersion=2.9.1
__AlpineVersion=3.9
__ApkToolsDir=$(mktemp -d)
@ -218,9 +236,24 @@ if [[ "$__LinuxCodeName" == "alpine" ]]; then
add $__AlpinePackagesEdgeTesting
rm -r $__ApkToolsDir
elif [[ -n $__LinuxCodeName ]]; then
qemu-debootstrap --arch $__UbuntuArch $__LinuxCodeName $__RootfsDir $__UbuntuRepo
cp $__CrossDir/$__BuildArch/sources.list.$__LinuxCodeName $__RootfsDir/etc/apt/sources.list
elif [[ "$__CodeName" == "freebsd" ]]; then
mkdir -p $__RootfsDir/usr/local/etc
wget -O - https://download.freebsd.org/ftp/releases/amd64/${__FreeBSDBase}/base.txz | tar -C $__RootfsDir -Jxf - ./lib ./usr/lib ./usr/libdata ./usr/include ./usr/share/keys ./etc ./bin/freebsd-version
# For now, ask for 11 ABI even on 12. This can be revisited later.
echo "ABI = \"FreeBSD:11:amd64\"; FINGERPRINTS = \"${__RootfsDir}/usr/share/keys\"; REPOS_DIR = [\"${__RootfsDir}/etc/pkg\"]; REPO_AUTOUPDATE = NO; RUN_SCRIPTS = NO;" > ${__RootfsDir}/usr/local/etc/pkg.conf
echo "FreeBSD: { url: "pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly", mirror_type: \"srv\", signature_type: \"fingerprints\", fingerprints: \"${__RootfsDir}/usr/share/keys/pkg\", enabled: yes }" > ${__RootfsDir}/etc/pkg/FreeBSD.conf
mkdir -p $__RootfsDir/tmp
# get and build package manager
wget -O - https://github.com/freebsd/pkg/archive/${__FreeBSDPkg}.tar.gz | tar -C $__RootfsDir/tmp -zxf -
cd $__RootfsDir/tmp/pkg-${__FreeBSDPkg}
./autogen.sh && ./configure --prefix=$__RootfsDir/host && make install
rm -rf $__RootfsDir/tmp/pkg-${__FreeBSDPkg}
# install packages we need.
$__RootfsDir/host/sbin/pkg -r $__RootfsDir -C $__RootfsDir/usr/local/etc/pkg.conf update
$__RootfsDir/host/sbin/pkg -r $__RootfsDir -C $__RootfsDir/usr/local/etc/pkg.conf install --yes $__FreeBSDPackages
elif [[ -n $__CodeName ]]; then
qemu-debootstrap --arch $__UbuntuArch $__CodeName $__RootfsDir $__UbuntuRepo
cp $__CrossDir/$__BuildArch/sources.list.$__CodeName $__RootfsDir/etc/apt/sources.list
chroot $__RootfsDir apt-get update
chroot $__RootfsDir apt-get -f -y install
chroot $__RootfsDir apt-get -y install $__UbuntuPackages
@ -230,7 +263,7 @@ elif [[ -n $__LinuxCodeName ]]; then
umount $__RootfsDir/*
fi
if [[ "$__BuildArch" == "arm" && "$__LinuxCodeName" == "trusty" ]]; then
if [[ "$__BuildArch" == "arm" && "$__CodeName" == "trusty" ]]; then
pushd $__RootfsDir
patch -p1 < $__CrossDir/$__BuildArch/trusty.patch
patch -p1 < $__CrossDir/$__BuildArch/trusty-lttng-2.4.patch

View File

@ -67,12 +67,12 @@ function Write-PipelineTaskError {
}
if(($Type -ne 'error') -and ($Type -ne 'warning')) {
Write-Host $Message
return
Write-Host $Message
return
}
$PSBoundParameters.Remove('Force') | Out-Null
if(-not $PSBoundParameters.ContainsKey('Type')) {
$PSBoundParameters.Add('Type', 'error')
$PSBoundParameters.Add('Type', 'error')
}
Write-LogIssue @PSBoundParameters
}

View File

@ -33,6 +33,10 @@ try {
$disableConfigureToolsetImport = $true
$LASTEXITCODE = 0
# `tools.ps1` checks $ci to perform some actions. Since the SDL
# scripts don't necessarily execute in the same agent that run the
# build.ps1/sh script this variable isn't automatically set.
$ci = $true
. $PSScriptRoot\..\tools.ps1
#Replace repo names to the format of org/repo

View File

@ -6,10 +6,6 @@ param(
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version 2.0
# `tools.ps1` checks $ci to perform some actions. Since the post-build
# scripts don't necessarily execute in the same agent that run the
# build.ps1/sh script this variable isn't automatically set.
$ci = $true
$disableConfigureToolsetImport = $true
function ExtractArtifacts {
@ -29,6 +25,10 @@ function ExtractArtifacts {
}
try {
# `tools.ps1` checks $ci to perform some actions. Since the SDL
# scripts don't necessarily execute in the same agent that run the
# build.ps1/sh script this variable isn't automatically set.
$ci = $true
. $PSScriptRoot\..\tools.ps1
$ExtractPackage = {

View File

@ -12,6 +12,10 @@ Set-StrictMode -Version 2.0
$disableConfigureToolsetImport = $true
$LASTEXITCODE = 0
# `tools.ps1` checks $ci to perform some actions. Since the SDL
# scripts don't necessarily execute in the same agent that run the
# build.ps1/sh script this variable isn't automatically set.
$ci = $true
. $PSScriptRoot\..\tools.ps1
# Don't display the console progress UI - it's a huge perf hit
@ -58,6 +62,6 @@ try {
}
catch {
Write-Host $_.ScriptStackTrace
Write-PipelineTelemetryError -Category 'Sdl' -Message $_
Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_
ExitWithExitCode 1
}

View File

@ -12,6 +12,10 @@ $disableConfigureToolsetImport = $true
$LASTEXITCODE = 0
try {
# `tools.ps1` checks $ci to perform some actions. Since the SDL
# scripts don't necessarily execute in the same agent that run the
# build.ps1/sh script this variable isn't automatically set.
$ci = $true
. $PSScriptRoot\..\tools.ps1
# We create the temp directory where we'll store the sdl-config repository
@ -62,4 +66,4 @@ catch {
Write-Host $_.ScriptStackTrace
Write-PipelineTelemetryError -Category 'Sdl' -Message $_
ExitWithExitCode 1
}
}

View File

@ -16,6 +16,10 @@ $disableConfigureToolsetImport = $true
$LASTEXITCODE = 0
try {
# `tools.ps1` checks $ci to perform some actions. Since the SDL
# scripts don't necessarily execute in the same agent that run the
# build.ps1/sh script this variable isn't automatically set.
$ci = $true
. $PSScriptRoot\..\tools.ps1
# We store config files in the r directory of .gdn
@ -64,6 +68,6 @@ try {
}
catch {
Write-Host $_.ScriptStackTrace
Write-PipelineTelemetryError -Category 'Sdl' -Message $_
Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_
ExitWithExitCode 1
}
}

View File

@ -9,8 +9,8 @@ variables:
- name: PublicDevRelease_31_Channel_Id
value: 128
# .NET Core 5 Dev
- name: NetCore_5_Dev_Channel_Id
# .NET 5 Dev
- name: Net_5_Dev_Channel_Id
value: 131
# .NET Eng - Validation
@ -96,4 +96,4 @@ variables:
- name: skipComponentGovernanceDetection
value: true
- name: runCodesignValidationInjection
value: false
value: false

View File

@ -27,7 +27,7 @@ parameters:
# needs to be updated with the new channel ID
NetEngLatestChannelId: 2
NetEngValidationChannelId: 9
NetCoreDev5ChannelId: 131
NetDev5ChannelId: 131
GeneralTestingChannelId: 529
NETCoreToolingDevChannelId: 548
NETCoreToolingReleaseChannelId: 549
@ -35,8 +35,10 @@ parameters:
NETCoreExperimentalChannelId: 562
NetEngServicesIntChannelId: 678
NetEngServicesProdChannelId: 679
Net5Preview1ChannelId: 737
Net5Preview2ChannelId: 738
Net5Preview3ChannelId: 739
NetCoreSDK313xxChannelId: 759
NetCoreSDK313xxInternalChannelId: 760
stages:
- stage: Validate
@ -63,7 +65,7 @@ stages:
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1
arguments: -PromoteToChannels "$(InitialChannels)[$(PromoteToMaestroChannelId)]"
-AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetCoreDev5ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview1ChannelId}},${{parameters.Net5Preview2ChannelId}}
-AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview2ChannelId}},${{parameters.Net5Preview3ChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}}
- job:
displayName: NuGet Validation
@ -198,23 +200,9 @@ stages:
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
stageName: 'NetCore_Dev5_Publish'
channelName: '.NET Core 5 Dev'
channelName: '.NET 5 Dev'
akaMSChannelName: 'net5/dev'
channelId: ${{ parameters.NetCoreDev5ChannelId }}
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
dependsOn: ${{ parameters.publishDependsOn }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
stageName: 'Net5_Preview1_Publish'
channelName: '.NET 5 Preview 1'
akaMSChannelName: 'net5/preview1'
channelId: ${{ parameters.Net5Preview1ChannelId }}
channelId: ${{ parameters.NetDev5ChannelId }}
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
@ -233,6 +221,20 @@ stages:
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
dependsOn: ${{ parameters.publishDependsOn }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
stageName: 'Net5_Preview3_Publish'
channelName: '.NET 5 Preview 3'
akaMSChannelName: 'net5/preview3'
channelId: ${{ parameters.Net5Preview3ChannelId }}
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
@ -352,3 +354,29 @@ stages:
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json'
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
dependsOn: ${{ parameters.publishDependsOn }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
stageName: 'NETCore_SDK_313xx_Publishing'
channelName: '.NET Core SDK 3.1.3xx'
channelId: ${{ parameters.NetCoreSDK313xxChannelId }}
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json'
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
dependsOn: ${{ parameters.publishDependsOn }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
stageName: 'NETCore_SDK_313xx_Internal_Publishing'
channelName: '.NET Core SDK 3.1.3xx Internal'
channelId: ${{ parameters.NetCoreSDK313xxInternalChannelId }}
transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json'

View File

@ -22,6 +22,7 @@
<ItemGroup Condition="'$(IsRequiredCheck)' == 'true' AND '$(TargetArchitecture)' == 'x64'">
<HelixAvailableTargetQueue Include="Ubuntu.1604.Amd64.Open" Platform="Linux" />
<HelixAvailableTargetQueue Include="Windows.10.Amd64.Open" Platform="Windows" />
<HelixAvailableTargetQueue Include="OSX.1014.Amd64.Open" Platform="Linux" />
</ItemGroup>
<!-- daily scheduled only queues -->

View File

@ -25,7 +25,7 @@
},
"msbuild-sdks": {
"Yarn.MSBuild": "1.15.2",
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20171.1",
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20171.1"
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20180.5",
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20180.5"
}
}

View File

@ -10,6 +10,12 @@
<Reference Include="Mono.WebAssembly.Interop" />
<Reference Include="Microsoft.AspNetCore.Components.Web" />
<Reference Include="Microsoft.Extensions.Options" />
<!--
Supress a "BUILD001: Reference to 'Microsoft.Extensions.Configuration' was removed since the last stable release
of this package." warning.
-->
<SuppressBaselineReference Include="Microsoft.Extensions.Configuration" />
</ItemGroup>
<ItemGroup>

View File

@ -115,10 +115,25 @@ namespace Microsoft.AspNetCore.TestHost
// This could throw an error if there was a pending server read. Needs to
// happen before completing the response so the response returns the error.
var requestBodyInProgress = RequestBodyReadInProgress();
if (requestBodyInProgress)
{
// If request is still in progress then abort it.
CancelRequestBody();
}
// Matches Kestrel server: response is completed before request is drained
await CompleteResponseAsync();
await CompleteRequestAsync(requestBodyInProgress);
if (!requestBodyInProgress)
{
// Writer was already completed in send request callback.
await _requestPipe.Reader.CompleteAsync();
// Don't wait for request to drain. It could block indefinitely. In a real server
// we would wait for a timeout and then kill the socket.
// Potential future improvement: add logging that the request timed out
}
_application.DisposeContext(_testContext, exception: null);
}
catch (Exception ex)
@ -165,24 +180,6 @@ namespace Microsoft.AspNetCore.TestHost
CancelRequestBody();
}
private async Task CompleteRequestAsync(bool requestBodyInProgress)
{
if (requestBodyInProgress)
{
// If request is still in progress then abort it.
CancelRequestBody();
}
else
{
// Writer was already completed in send request callback.
await _requestPipe.Reader.CompleteAsync();
}
// Don't wait for request to drain. It could block indefinitely. In a real server
// we would wait for a timeout and then kill the socket.
// Potential future improvement: add logging that the request timed out
}
private bool RequestBodyReadInProgress()
{
try

View File

@ -212,7 +212,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
}
[ConditionalFact]
[SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/20153")]
public async Task DetectsOverriddenServer()
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters(Fixture.InProcessTestSite);
@ -230,7 +229,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
}
[ConditionalFact]
[SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/20153")]
public async Task LogsStartupExceptionExitError()
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters(Fixture.InProcessTestSite);
@ -709,7 +707,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
[InlineData("DOTNET_ENVIRONMENT", "deVelopment")]
[InlineData("ASPNETCORE_DETAILEDERRORS", "1")]
[InlineData("ASPNETCORE_DETAILEDERRORS", "TRUE")]
[SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/20153")]
public async Task ExceptionIsLoggedToEventLogAndPutInResponseWhenDeveloperExceptionPageIsEnabled(string environmentVariable, string value)
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
@ -734,7 +731,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
[ConditionalFact]
[RequiresNewHandler]
[SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/20153")]
public async Task ExceptionIsLoggedToEventLogAndPutInResponseWhenDeveloperExceptionPageIsEnabledViaWebConfig()
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
@ -762,7 +758,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
[RequiresNewHandler]
[InlineData("ThrowInStartup")]
[InlineData("ThrowInStartupGenericHost")]
[SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/20153")]
public async Task ExceptionIsLoggedToEventLogAndPutInResponseDuringHostingStartupProcess(string startupType)
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
@ -785,7 +780,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
[ConditionalFact]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
[RequiresNewHandler]
[SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/20153")]
public async Task ExceptionIsNotLoggedToResponseWhenStartupHookIsDisabled()
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
@ -808,7 +802,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
[ConditionalFact]
[RequiresNewHandler]
[SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/20153")]
public async Task ExceptionIsLoggedToEventLogDoesNotWriteToResponse()
{
var deploymentParameters = Fixture.GetBaseDeploymentParameters();

View File

@ -127,6 +127,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
{
public KestrelServerOptions() { }
public bool AddServerHeader { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public bool AllowResponseHeaderCompression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public bool AllowSynchronousIO { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public System.IServiceProvider ApplicationServices { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader ConfigurationLoader { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }

View File

@ -599,4 +599,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
<data name="TransportNotFound" xml:space="preserve">
<value>Unable to resolve service for type 'Microsoft.AspNetCore.Connections.IConnectionListenerFactory' while attempting to activate 'Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer'.</value>
</data>
<data name="GreaterThanOrEqualToZeroRequired" xml:space="preserve">
<value>A value greater than or equal to zero is required.</value>
</data>
</root>

View File

@ -39,9 +39,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
}
/// <summary>
/// Limits the size of the header compression table, in octets, the HPACK decoder on the server can use.
/// Limits the size of the header compression tables, in octets, the HPACK encoder and decoder on the server can use.
/// <para>
/// Value must be greater than 0, defaults to 4096
/// Value must be greater than or equal to 0, defaults to 4096
/// </para>
/// </summary>
public int HeaderTableSize
@ -49,9 +49,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
get => _headerTableSize;
set
{
if (value <= 0)
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value), value, CoreStrings.GreaterThanZeroRequired);
throw new ArgumentOutOfRangeException(nameof(value), value, CoreStrings.GreaterThanOrEqualToZeroRequired);
}
_headerTableSize = value;

View File

@ -4,7 +4,6 @@
using System;
using System.Net.Http;
using System.Net.Http.HPack;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
{
@ -13,57 +12,105 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
/// <summary>
/// Begin encoding headers in the first HEADERS frame.
/// </summary>
public static bool BeginEncodeHeaders(int statusCode, Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
public static bool BeginEncodeHeaders(int statusCode, HPackEncoder hpackEncoder, Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
{
if (!HPackEncoder.EncodeStatusHeader(statusCode, buffer, out var statusCodeLength))
length = 0;
if (!hpackEncoder.EnsureDynamicTableSizeUpdate(buffer, out var sizeUpdateLength))
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
length += sizeUpdateLength;
if (!EncodeStatusHeader(statusCode, hpackEncoder, buffer.Slice(length), out var statusCodeLength))
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
length += statusCodeLength;
if (!headersEnumerator.MoveNext())
{
length = statusCodeLength;
return true;
}
// We're ok with not throwing if no headers were encoded because we've already encoded the status.
// There is a small chance that the header will encode if there is no other content in the next HEADERS frame.
var done = EncodeHeaders(headersEnumerator, buffer.Slice(statusCodeLength), throwIfNoneEncoded: false, out var headersLength);
length = statusCodeLength + headersLength;
var done = EncodeHeadersCore(hpackEncoder, headersEnumerator, buffer.Slice(length), throwIfNoneEncoded: false, out var headersLength);
length += headersLength;
return done;
}
/// <summary>
/// Begin encoding headers in the first HEADERS frame.
/// </summary>
public static bool BeginEncodeHeaders(Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
public static bool BeginEncodeHeaders(HPackEncoder hpackEncoder, Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
{
length = 0;
if (!hpackEncoder.EnsureDynamicTableSizeUpdate(buffer, out var sizeUpdateLength))
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
length += sizeUpdateLength;
if (!headersEnumerator.MoveNext())
{
length = 0;
return true;
}
return EncodeHeaders(headersEnumerator, buffer, throwIfNoneEncoded: true, out length);
var done = EncodeHeadersCore(hpackEncoder, headersEnumerator, buffer.Slice(length), throwIfNoneEncoded: true, out var headersLength);
length += headersLength;
return done;
}
/// <summary>
/// Continue encoding headers in the next HEADERS frame. The enumerator should already have a current value.
/// </summary>
public static bool ContinueEncodeHeaders(Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
public static bool ContinueEncodeHeaders(HPackEncoder hpackEncoder, Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
{
return EncodeHeaders(headersEnumerator, buffer, throwIfNoneEncoded: true, out length);
return EncodeHeadersCore(hpackEncoder, headersEnumerator, buffer, throwIfNoneEncoded: true, out length);
}
private static bool EncodeHeaders(Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, bool throwIfNoneEncoded, out int length)
private static bool EncodeStatusHeader(int statusCode, HPackEncoder hpackEncoder, Span<byte> buffer, out int length)
{
switch (statusCode)
{
case 200:
case 204:
case 206:
case 304:
case 400:
case 404:
case 500:
// Status codes which exist in the HTTP/2 StaticTable.
return HPackEncoder.EncodeIndexedHeaderField(H2StaticTable.StatusIndex[statusCode], buffer, out length);
default:
const string name = ":status";
var value = StatusCodes.ToStatusString(statusCode);
return hpackEncoder.EncodeHeader(buffer, H2StaticTable.Status200, HeaderEncodingHint.Index, name, value, out length);
}
}
private static bool EncodeHeadersCore(HPackEncoder hpackEncoder, Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, bool throwIfNoneEncoded, out int length)
{
var currentLength = 0;
do
{
if (!EncodeHeader(headersEnumerator.KnownHeaderType, headersEnumerator.Current.Key, headersEnumerator.Current.Value, buffer.Slice(currentLength), out int headerLength))
var staticTableId = headersEnumerator.HPackStaticTableId;
var name = headersEnumerator.Current.Key;
var value = headersEnumerator.Current.Value;
var hint = ResolveHeaderEncodingHint(staticTableId, name);
if (!hpackEncoder.EncodeHeader(
buffer.Slice(currentLength),
staticTableId,
hint,
name,
value,
out var headerLength))
{
// The the header wasn't written and no headers have been written then the header is too large.
// If the header wasn't written, and no headers have been written, then the header is too large.
// Throw an error to avoid an infinite loop of attempting to write large header.
if (currentLength == 0 && throwIfNoneEncoded)
{
@ -79,79 +126,48 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
while (headersEnumerator.MoveNext());
length = currentLength;
return true;
}
private static bool EncodeHeader(KnownHeaderType knownHeaderType, string name, string value, Span<byte> buffer, out int length)
private static HeaderEncodingHint ResolveHeaderEncodingHint(int staticTableId, string name)
{
var hPackStaticTableId = GetResponseHeaderStaticTableId(knownHeaderType);
if (hPackStaticTableId == -1)
HeaderEncodingHint hint;
if (IsSensitive(staticTableId, name))
{
return HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingNewName(name, value, buffer, out length);
hint = HeaderEncodingHint.NeverIndex;
}
else if (IsNotDynamicallyIndexed(staticTableId))
{
hint = HeaderEncodingHint.IgnoreIndex;
}
else
{
return HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexing(hPackStaticTableId, value, buffer, out length);
hint = HeaderEncodingHint.Index;
}
return hint;
}
private static int GetResponseHeaderStaticTableId(KnownHeaderType responseHeaderType)
private static bool IsSensitive(int staticTableIndex, string name)
{
switch (responseHeaderType)
// Set-Cookie could contain sensitive data.
if (staticTableIndex == H2StaticTable.SetCookie)
{
case KnownHeaderType.CacheControl:
return H2StaticTable.CacheControl;
case KnownHeaderType.Date:
return H2StaticTable.Date;
case KnownHeaderType.TransferEncoding:
return H2StaticTable.TransferEncoding;
case KnownHeaderType.Via:
return H2StaticTable.Via;
case KnownHeaderType.Allow:
return H2StaticTable.Allow;
case KnownHeaderType.ContentType:
return H2StaticTable.ContentType;
case KnownHeaderType.ContentEncoding:
return H2StaticTable.ContentEncoding;
case KnownHeaderType.ContentLanguage:
return H2StaticTable.ContentLanguage;
case KnownHeaderType.ContentLocation:
return H2StaticTable.ContentLocation;
case KnownHeaderType.ContentRange:
return H2StaticTable.ContentRange;
case KnownHeaderType.Expires:
return H2StaticTable.Expires;
case KnownHeaderType.LastModified:
return H2StaticTable.LastModified;
case KnownHeaderType.AcceptRanges:
return H2StaticTable.AcceptRanges;
case KnownHeaderType.Age:
return H2StaticTable.Age;
case KnownHeaderType.ETag:
return H2StaticTable.ETag;
case KnownHeaderType.Location:
return H2StaticTable.Location;
case KnownHeaderType.ProxyAuthenticate:
return H2StaticTable.ProxyAuthenticate;
case KnownHeaderType.RetryAfter:
return H2StaticTable.RetryAfter;
case KnownHeaderType.Server:
return H2StaticTable.Server;
case KnownHeaderType.SetCookie:
return H2StaticTable.SetCookie;
case KnownHeaderType.Vary:
return H2StaticTable.Vary;
case KnownHeaderType.WWWAuthenticate:
return H2StaticTable.WwwAuthenticate;
case KnownHeaderType.AccessControlAllowOrigin:
return H2StaticTable.AccessControlAllowOrigin;
case KnownHeaderType.ContentLength:
return H2StaticTable.ContentLength;
default:
return -1;
return true;
}
if (string.Equals(name, "Content-Disposition", StringComparison.OrdinalIgnoreCase))
{
return true;
}
return false;
}
private static bool IsNotDynamicallyIndexed(int staticTableIndex)
{
// Content-Length is added to static content. Content length is different for each
// file, and is unlikely to be reused because of browser caching.
return staticTableIndex == H2StaticTable.ContentLength;
}
}
}

View File

@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
httpLimits.MinResponseDataRate,
context.ConnectionId,
context.MemoryPool,
context.ServiceContext.Log);
context.ServiceContext);
var inputOptions = new PipeOptions(pool: context.MemoryPool,
readerScheduler: context.ServiceContext.Scheduler,
@ -743,6 +743,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
}
}
// Maximum HPack encoder size is limited by Http2Limits.HeaderTableSize, configured max the server.
//
// Note that the client HPack decoder doesn't care about the ACK so we don't need to lock sending the
// ACK and updating the table size on the server together.
// The client will wait until a size agreed upon by it (sent in SETTINGS_HEADER_TABLE_SIZE) and the
// server (sent as a dynamic table size update in the next HEADERS frame) is received before applying
// the new size.
_frameWriter.UpdateMaxHeaderTableSize(Math.Min(_clientSettings.HeaderTableSize, (uint)Limits.Http2.HeaderTableSize));
return ackTask.AsTask();
}
catch (Http2SettingsParameterOutOfRangeException ex)

View File

@ -38,6 +38,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
private readonly ITimeoutControl _timeoutControl;
private readonly MinDataRate _minResponseDataRate;
private readonly TimingPipeFlusher _flusher;
private readonly HPackEncoder _hpackEncoder;
private uint _maxFrameSize = Http2PeerSettings.MinAllowedMaxFrameSize;
private byte[] _headerEncodingBuffer;
@ -55,7 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
MinDataRate minResponseDataRate,
string connectionId,
MemoryPool<byte> memoryPool,
IKestrelTrace log)
ServiceContext serviceContext)
{
// Allow appending more data to the PipeWriter when a flush is pending.
_outputWriter = new ConcurrentPipeWriter(outputPipeWriter, memoryPool, _writeLock);
@ -63,12 +64,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_http2Connection = http2Connection;
_connectionOutputFlowControl = connectionOutputFlowControl;
_connectionId = connectionId;
_log = log;
_log = serviceContext.Log;
_timeoutControl = timeoutControl;
_minResponseDataRate = minResponseDataRate;
_flusher = new TimingPipeFlusher(_outputWriter, timeoutControl, log);
_flusher = new TimingPipeFlusher(_outputWriter, timeoutControl, serviceContext.Log);
_outgoingFrame = new Http2Frame();
_headerEncodingBuffer = new byte[_maxFrameSize];
_hpackEncoder = new HPackEncoder(serviceContext.ServerOptions.AllowResponseHeaderCompression);
}
public void UpdateMaxHeaderTableSize(uint maxHeaderTableSize)
{
lock (_writeLock)
{
_hpackEncoder.UpdateMaxHeaderTableSize(maxHeaderTableSize);
}
}
public void UpdateMaxFrameSize(uint maxFrameSize)
@ -175,7 +186,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_headersEnumerator.Initialize(headers);
_outgoingFrame.PrepareHeaders(headerFrameFlags, streamId);
var buffer = _headerEncodingBuffer.AsSpan();
var done = HPackHeaderWriter.BeginEncodeHeaders(statusCode, _headersEnumerator, buffer, out var payloadLength);
var done = HPackHeaderWriter.BeginEncodeHeaders(statusCode, _hpackEncoder, _headersEnumerator, buffer, out var payloadLength);
FinishWritingHeaders(streamId, payloadLength, done);
}
catch (HPackEncodingException hex)
@ -201,7 +212,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_headersEnumerator.Initialize(headers);
_outgoingFrame.PrepareHeaders(Http2HeadersFrameFlags.END_STREAM, streamId);
var buffer = _headerEncodingBuffer.AsSpan();
var done = HPackHeaderWriter.BeginEncodeHeaders(_headersEnumerator, buffer, out var payloadLength);
var done = HPackHeaderWriter.BeginEncodeHeaders(_hpackEncoder, _headersEnumerator, buffer, out var payloadLength);
FinishWritingHeaders(streamId, payloadLength, done);
}
catch (HPackEncodingException hex)
@ -230,7 +241,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
{
_outgoingFrame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
done = HPackHeaderWriter.ContinueEncodeHeaders(_headersEnumerator, buffer, out payloadLength);
done = HPackHeaderWriter.ContinueEncodeHeaders(_hpackEncoder, _headersEnumerator, buffer, out payloadLength);
_outgoingFrame.PayloadLength = payloadLength;
if (done)

View File

@ -3,6 +3,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Net.Http.HPack;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.Extensions.Primitives;
@ -15,8 +16,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
private HttpResponseTrailers.Enumerator _trailersEnumerator;
private IEnumerator<KeyValuePair<string, StringValues>> _genericEnumerator;
private StringValues.Enumerator _stringValuesEnumerator;
private KnownHeaderType _knownHeaderType;
public KnownHeaderType KnownHeaderType { get; private set; }
public int HPackStaticTableId => GetResponseHeaderStaticTableId(_knownHeaderType);
public KeyValuePair<string, string> Current { get; private set; }
object IEnumerator.Current => Current;
@ -33,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_stringValuesEnumerator = default;
Current = default;
KnownHeaderType = default;
_knownHeaderType = default;
}
public void Initialize(HttpResponseTrailers headers)
@ -45,7 +47,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_stringValuesEnumerator = default;
Current = default;
KnownHeaderType = default;
_knownHeaderType = default;
}
public void Initialize(IDictionary<string, StringValues> headers)
@ -57,7 +59,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_stringValuesEnumerator = default;
Current = default;
KnownHeaderType = default;
_knownHeaderType = default;
}
public bool MoveNext()
@ -110,7 +112,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
else
{
enumerator = _genericEnumerator.Current.Value.GetEnumerator();
KnownHeaderType = default;
_knownHeaderType = default;
return true;
}
}
@ -124,7 +126,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
else
{
enumerator = _trailersEnumerator.Current.Value.GetEnumerator();
KnownHeaderType = _trailersEnumerator.CurrentKnownType;
_knownHeaderType = _trailersEnumerator.CurrentKnownType;
return true;
}
}
@ -138,7 +140,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
else
{
enumerator = _headersEnumerator.Current.Value.GetEnumerator();
KnownHeaderType = _headersEnumerator.CurrentKnownType;
_knownHeaderType = _headersEnumerator.CurrentKnownType;
return true;
}
}
@ -159,11 +161,68 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_headersEnumerator.Reset();
}
_stringValuesEnumerator = default;
KnownHeaderType = default;
_knownHeaderType = default;
}
public void Dispose()
{
}
internal static int GetResponseHeaderStaticTableId(KnownHeaderType responseHeaderType)
{
switch (responseHeaderType)
{
case KnownHeaderType.CacheControl:
return H2StaticTable.CacheControl;
case KnownHeaderType.Date:
return H2StaticTable.Date;
case KnownHeaderType.TransferEncoding:
return H2StaticTable.TransferEncoding;
case KnownHeaderType.Via:
return H2StaticTable.Via;
case KnownHeaderType.Allow:
return H2StaticTable.Allow;
case KnownHeaderType.ContentType:
return H2StaticTable.ContentType;
case KnownHeaderType.ContentEncoding:
return H2StaticTable.ContentEncoding;
case KnownHeaderType.ContentLanguage:
return H2StaticTable.ContentLanguage;
case KnownHeaderType.ContentLocation:
return H2StaticTable.ContentLocation;
case KnownHeaderType.ContentRange:
return H2StaticTable.ContentRange;
case KnownHeaderType.Expires:
return H2StaticTable.Expires;
case KnownHeaderType.LastModified:
return H2StaticTable.LastModified;
case KnownHeaderType.AcceptRanges:
return H2StaticTable.AcceptRanges;
case KnownHeaderType.Age:
return H2StaticTable.Age;
case KnownHeaderType.ETag:
return H2StaticTable.ETag;
case KnownHeaderType.Location:
return H2StaticTable.Location;
case KnownHeaderType.ProxyAuthenticate:
return H2StaticTable.ProxyAuthenticate;
case KnownHeaderType.RetryAfter:
return H2StaticTable.RetryAfter;
case KnownHeaderType.Server:
return H2StaticTable.Server;
case KnownHeaderType.SetCookie:
return H2StaticTable.SetCookie;
case KnownHeaderType.Vary:
return H2StaticTable.Vary;
case KnownHeaderType.WWWAuthenticate:
return H2StaticTable.WwwAuthenticate;
case KnownHeaderType.AccessControlAllowOrigin:
return H2StaticTable.AccessControlAllowOrigin;
case KnownHeaderType.ContentLength:
return H2StaticTable.ContentLength;
default:
return -1;
}
}
}
}

View File

@ -38,6 +38,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
/// </remarks>
public bool AddServerHeader { get; set; } = true;
/// <summary>
/// Gets or sets a value that controls whether dynamic compression of response headers is allowed.
/// For more information about the security considerations of HPack dynamic header compression, visit
/// https://tools.ietf.org/html/rfc7541#section-7.
/// </summary>
/// <remarks>
/// Defaults to true.
/// </remarks>
public bool AllowResponseHeaderCompression { get; set; } = true;
/// <summary>
/// Gets or sets a value that controls whether synchronous IO is allowed for the <see cref="HttpContext.Request"/> and <see cref="HttpContext.Response"/>
/// </summary>

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Core components of ASP.NET Core Kestrel cross-platform web server.</Description>
@ -16,9 +16,10 @@
<Compile Include="$(SharedSourceRoot)CertificateGeneration\**\*.cs" />
<Compile Include="$(SharedSourceRoot)ValueTaskExtensions\**\*.cs" />
<Compile Include="$(SharedSourceRoot)UrlDecoder\**\*.cs" />
<Compile Include="$(SharedSourceRoot)runtime\*.cs" Link="Shared\runtime\%(Filename)%(Extension)"/>
<Compile Include="$(SharedSourceRoot)runtime\Http2\**\*.cs" Link="Shared\runtime\Http2\%(Filename)%(Extension)"/>
<Compile Include="$(SharedSourceRoot)runtime\Http3\**\*.cs" Link="Shared\runtime\Http3\%(Filename)%(Extension)"/>
<Compile Include="$(SharedSourceRoot)runtime\*.cs" Link="Shared\runtime\%(Filename)%(Extension)" />
<Compile Include="$(SharedSourceRoot)runtime\Http2\**\*.cs" Link="Shared\runtime\Http2\%(Filename)%(Extension)" />
<Compile Include="$(SharedSourceRoot)runtime\Http3\**\*.cs" Link="Shared\runtime\Http3\%(Filename)%(Extension)" />
<Compile Include="$(SharedSourceRoot)Hpack\**\*.cs" Link="Shared\Hpack\%(Filename)%(Extension)" />
<Compile Include="$(SharedSourceRoot)ServerInfrastructure\**\*.cs" LinkBase="Shared\" />
<Compile Include="$(RepoRoot)src\Shared\TaskToApm.cs" Link="Internal\TaskToApm.cs" />
</ItemGroup>

View File

@ -1,199 +1,199 @@
// 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.
//// 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.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
using Microsoft.Extensions.Primitives;
using Xunit;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
//using Microsoft.Extensions.Primitives;
//using Xunit;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
public class HPackHeaderWriterTests
{
public static TheoryData<KeyValuePair<string, string>[], byte[], int?> SinglePayloadData
{
get
{
var data = new TheoryData<KeyValuePair<string, string>[], byte[], int?>();
//namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
//{
// public class HPackHeaderWriterTests
// {
// public static TheoryData<KeyValuePair<string, string>[], byte[], int?> SinglePayloadData
// {
// get
// {
// var data = new TheoryData<KeyValuePair<string, string>[], byte[], int?>();
// Lowercase header name letters only
data.Add(
new[]
{
new KeyValuePair<string, string>("CustomHeader", "CustomValue"),
},
new byte[]
{
// 0 12 c u s t o m
0x00, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
// h e a d e r 11 C
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0b, 0x43,
// u s t o m V a l
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x56, 0x61, 0x6c,
// u e
0x75, 0x65
},
null);
// Lowercase header name letters only
data.Add(
new[]
{
new KeyValuePair<string, string>("CustomHeader!#$%&'*+-.^_`|~", "CustomValue"),
},
new byte[]
{
// 0 27 c u s t o m
0x00, 0x1b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
// h e a d e r ! #
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x21, 0x23,
// $ % & ' * + - .
0x24, 0x25, 0x26, 0x27, 0x2a, 0x2b, 0x2d, 0x2e,
// ^ _ ` | ~ 11 C u
0x5e, 0x5f, 0x60, 0x7c, 0x7e, 0x0b, 0x43, 0x75,
// s t o m V a l u
0x73, 0x74, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75,
// e
0x65
},
null);
// Single Payload
data.Add(
new[]
{
new KeyValuePair<string, string>("date", "Mon, 24 Jul 2017 19:22:30 GMT"),
new KeyValuePair<string, string>("content-type", "text/html; charset=utf-8"),
new KeyValuePair<string, string>("server", "Kestrel")
},
new byte[]
{
0x88, 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1d,
0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x34, 0x20,
0x4a, 0x75, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x37,
0x20, 0x31, 0x39, 0x3a, 0x32, 0x32, 0x3a, 0x33,
0x30, 0x20, 0x47, 0x4d, 0x54, 0x00, 0x0c, 0x63,
0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74,
0x79, 0x70, 0x65, 0x18, 0x74, 0x65, 0x78, 0x74,
0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x20, 0x63,
0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x75,
0x74, 0x66, 0x2d, 0x38, 0x00, 0x06, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x07, 0x4b, 0x65, 0x73,
0x74, 0x72, 0x65, 0x6c
},
200);
// // Lowercase header name letters only
// data.Add(
// new[]
// {
// new KeyValuePair<string, string>("CustomHeader", "CustomValue"),
// },
// new byte[]
// {
// // 0 12 c u s t o m
// 0x00, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
// // h e a d e r 11 C
// 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0b, 0x43,
// // u s t o m V a l
// 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x56, 0x61, 0x6c,
// // u e
// 0x75, 0x65
// },
// null);
// // Lowercase header name letters only
// data.Add(
// new[]
// {
// new KeyValuePair<string, string>("CustomHeader!#$%&'*+-.^_`|~", "CustomValue"),
// },
// new byte[]
// {
// // 0 27 c u s t o m
// 0x00, 0x1b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
// // h e a d e r ! #
// 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x21, 0x23,
// // $ % & ' * + - .
// 0x24, 0x25, 0x26, 0x27, 0x2a, 0x2b, 0x2d, 0x2e,
// // ^ _ ` | ~ 11 C u
// 0x5e, 0x5f, 0x60, 0x7c, 0x7e, 0x0b, 0x43, 0x75,
// // s t o m V a l u
// 0x73, 0x74, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75,
// // e
// 0x65
// },
// null);
// // Single Payload
// data.Add(
// new[]
// {
// new KeyValuePair<string, string>("date", "Mon, 24 Jul 2017 19:22:30 GMT"),
// new KeyValuePair<string, string>("content-type", "text/html; charset=utf-8"),
// new KeyValuePair<string, string>("server", "Kestrel")
// },
// new byte[]
// {
// 0x88, 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1d,
// 0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x34, 0x20,
// 0x4a, 0x75, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x37,
// 0x20, 0x31, 0x39, 0x3a, 0x32, 0x32, 0x3a, 0x33,
// 0x30, 0x20, 0x47, 0x4d, 0x54, 0x00, 0x0c, 0x63,
// 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74,
// 0x79, 0x70, 0x65, 0x18, 0x74, 0x65, 0x78, 0x74,
// 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x20, 0x63,
// 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x75,
// 0x74, 0x66, 0x2d, 0x38, 0x00, 0x06, 0x73, 0x65,
// 0x72, 0x76, 0x65, 0x72, 0x07, 0x4b, 0x65, 0x73,
// 0x74, 0x72, 0x65, 0x6c
// },
// 200);
return data;
}
}
// return data;
// }
// }
[Theory]
[MemberData(nameof(SinglePayloadData))]
public void EncodesHeadersInSinglePayloadWhenSpaceAvailable(KeyValuePair<string, string>[] headers, byte[] expectedPayload, int? statusCode)
{
var payload = new byte[1024];
var length = 0;
if (statusCode.HasValue)
{
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(statusCode.Value, GetHeadersEnumerator(headers), payload, out length));
}
else
{
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out length));
}
Assert.Equal(expectedPayload.Length, length);
// [Theory]
// [MemberData(nameof(SinglePayloadData))]
// public void EncodesHeadersInSinglePayloadWhenSpaceAvailable(KeyValuePair<string, string>[] headers, byte[] expectedPayload, int? statusCode)
// {
// var payload = new byte[1024];
// var length = 0;
// if (statusCode.HasValue)
// {
// Assert.True(HPackHeaderWriter.BeginEncodeHeaders(statusCode.Value, GetHeadersEnumerator(headers), payload, out length));
// }
// else
// {
// Assert.True(HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out length));
// }
// Assert.Equal(expectedPayload.Length, length);
for (var i = 0; i < length; i++)
{
Assert.True(expectedPayload[i] == payload[i], $"{expectedPayload[i]} != {payload[i]} at {i} (len {length})");
}
// for (var i = 0; i < length; i++)
// {
// Assert.True(expectedPayload[i] == payload[i], $"{expectedPayload[i]} != {payload[i]} at {i} (len {length})");
// }
Assert.Equal(expectedPayload, new ArraySegment<byte>(payload, 0, length));
}
// Assert.Equal(expectedPayload, new ArraySegment<byte>(payload, 0, length));
// }
[Theory]
[InlineData(true)]
[InlineData(false)]
public void EncodesHeadersInMultiplePayloadsWhenSpaceNotAvailable(bool exactSize)
{
var statusCode = 200;
var headers = new[]
{
new KeyValuePair<string, string>("date", "Mon, 24 Jul 2017 19:22:30 GMT"),
new KeyValuePair<string, string>("content-type", "text/html; charset=utf-8"),
new KeyValuePair<string, string>("server", "Kestrel")
};
// [Theory]
// [InlineData(true)]
// [InlineData(false)]
// public void EncodesHeadersInMultiplePayloadsWhenSpaceNotAvailable(bool exactSize)
// {
// var statusCode = 200;
// var headers = new[]
// {
// new KeyValuePair<string, string>("date", "Mon, 24 Jul 2017 19:22:30 GMT"),
// new KeyValuePair<string, string>("content-type", "text/html; charset=utf-8"),
// new KeyValuePair<string, string>("server", "Kestrel")
// };
var expectedStatusCodePayload = new byte[]
{
0x88
};
// var expectedStatusCodePayload = new byte[]
// {
// 0x88
// };
var expectedDateHeaderPayload = new byte[]
{
0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1d, 0x4d,
0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x34, 0x20, 0x4a,
0x75, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x37, 0x20,
0x31, 0x39, 0x3a, 0x32, 0x32, 0x3a, 0x33, 0x30,
0x20, 0x47, 0x4d, 0x54
};
// var expectedDateHeaderPayload = new byte[]
// {
// 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1d, 0x4d,
// 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x34, 0x20, 0x4a,
// 0x75, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x37, 0x20,
// 0x31, 0x39, 0x3a, 0x32, 0x32, 0x3a, 0x33, 0x30,
// 0x20, 0x47, 0x4d, 0x54
// };
var expectedContentTypeHeaderPayload = new byte[]
{
0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x18, 0x74,
0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
0x3b, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,
0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38
};
// var expectedContentTypeHeaderPayload = new byte[]
// {
// 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
// 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x18, 0x74,
// 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
// 0x3b, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,
// 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38
// };
var expectedServerHeaderPayload = new byte[]
{
0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x07, 0x4b, 0x65, 0x73, 0x74, 0x72, 0x65, 0x6c
};
// var expectedServerHeaderPayload = new byte[]
// {
// 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
// 0x07, 0x4b, 0x65, 0x73, 0x74, 0x72, 0x65, 0x6c
// };
Span<byte> payload = new byte[1024];
var offset = 0;
var headerEnumerator = GetHeadersEnumerator(headers);
// Span<byte> payload = new byte[1024];
// var offset = 0;
// var headerEnumerator = GetHeadersEnumerator(headers);
// When !exactSize, slices are one byte short of fitting the next header
var sliceLength = expectedStatusCodePayload.Length + (exactSize ? 0 : expectedDateHeaderPayload.Length - 1);
Assert.False(HPackHeaderWriter.BeginEncodeHeaders(statusCode, headerEnumerator, payload.Slice(offset, sliceLength), out var length));
Assert.Equal(expectedStatusCodePayload.Length, length);
Assert.Equal(expectedStatusCodePayload, payload.Slice(0, length).ToArray());
// // When !exactSize, slices are one byte short of fitting the next header
// var sliceLength = expectedStatusCodePayload.Length + (exactSize ? 0 : expectedDateHeaderPayload.Length - 1);
// Assert.False(HPackHeaderWriter.BeginEncodeHeaders(statusCode, headerEnumerator, payload.Slice(offset, sliceLength), out var length));
// Assert.Equal(expectedStatusCodePayload.Length, length);
// Assert.Equal(expectedStatusCodePayload, payload.Slice(0, length).ToArray());
offset += length;
// offset += length;
sliceLength = expectedDateHeaderPayload.Length + (exactSize ? 0 : expectedContentTypeHeaderPayload.Length - 1);
Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedDateHeaderPayload.Length, length);
Assert.Equal(expectedDateHeaderPayload, payload.Slice(offset, length).ToArray());
// sliceLength = expectedDateHeaderPayload.Length + (exactSize ? 0 : expectedContentTypeHeaderPayload.Length - 1);
// Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
// Assert.Equal(expectedDateHeaderPayload.Length, length);
// Assert.Equal(expectedDateHeaderPayload, payload.Slice(offset, length).ToArray());
offset += length;
// offset += length;
sliceLength = expectedContentTypeHeaderPayload.Length + (exactSize ? 0 : expectedServerHeaderPayload.Length - 1);
Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedContentTypeHeaderPayload.Length, length);
Assert.Equal(expectedContentTypeHeaderPayload, payload.Slice(offset, length).ToArray());
// sliceLength = expectedContentTypeHeaderPayload.Length + (exactSize ? 0 : expectedServerHeaderPayload.Length - 1);
// Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
// Assert.Equal(expectedContentTypeHeaderPayload.Length, length);
// Assert.Equal(expectedContentTypeHeaderPayload, payload.Slice(offset, length).ToArray());
offset += length;
// offset += length;
sliceLength = expectedServerHeaderPayload.Length;
Assert.True(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedServerHeaderPayload.Length, length);
Assert.Equal(expectedServerHeaderPayload, payload.Slice(offset, length).ToArray());
}
// sliceLength = expectedServerHeaderPayload.Length;
// Assert.True(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
// Assert.Equal(expectedServerHeaderPayload.Length, length);
// Assert.Equal(expectedServerHeaderPayload, payload.Slice(offset, length).ToArray());
// }
private static Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
{
var groupedHeaders = headers
.GroupBy(k => k.Key)
.ToDictionary(g => g.Key, g => new StringValues(g.Select(gg => gg.Value).ToArray()));
// private static Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
// {
// var groupedHeaders = headers
// .GroupBy(k => k.Key)
// .ToDictionary(g => g.Key, g => new StringValues(g.Select(gg => gg.Value).ToArray()));
var enumerator = new Http2HeadersEnumerator();
enumerator.Initialize(groupedHeaders);
return enumerator;
}
}
}
// var enumerator = new Http2HeadersEnumerator();
// enumerator.Initialize(groupedHeaders);
// return enumerator;
// }
// }
//}

View File

@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
// Arrange
var pipe = new Pipe(new PipeOptions(_dirtyMemoryPool, PipeScheduler.Inline, PipeScheduler.Inline));
var frameWriter = new Http2FrameWriter(pipe.Writer, null, null, null, null, null, null, _dirtyMemoryPool, new Mock<IKestrelTrace>().Object);
var frameWriter = CreateFrameWriter(pipe);
// Act
await frameWriter.WriteWindowUpdateAsync(1, 1);
@ -52,12 +52,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(new byte[] { 0x00, 0x00, 0x00, 0x01 }, payload.Skip(Http2FrameReader.HeaderLength).Take(4).ToArray());
}
private Http2FrameWriter CreateFrameWriter(Pipe pipe)
{
var serviceContext = new Internal.ServiceContext
{
ServerOptions = new KestrelServerOptions(),
Log = new Mock<IKestrelTrace>().Object
};
return new Http2FrameWriter(pipe.Writer, null, null, null, null, null, null, _dirtyMemoryPool, serviceContext);
}
[Fact]
public async Task WriteGoAway_UnsetsReservedBit()
{
// Arrange
var pipe = new Pipe(new PipeOptions(_dirtyMemoryPool, PipeScheduler.Inline, PipeScheduler.Inline));
var frameWriter = new Http2FrameWriter(pipe.Writer, null, null, null, null, null, null, _dirtyMemoryPool, new Mock<IKestrelTrace>().Object);
var frameWriter = CreateFrameWriter(pipe);
// Act
await frameWriter.WriteGoAwayAsync(1, Http2ErrorCode.NO_ERROR);

View File

@ -0,0 +1,479 @@
// 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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.HPack;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
using Microsoft.Extensions.Primitives;
using Xunit;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
public class Http2HPackEncoderTests
{
[Fact]
public void BeginEncodeHeaders_Status302_NewIndexValue()
{
Span<byte> buffer = new byte[1024 * 16];
var headers = new HttpResponseHeaders();
var enumerator = new Http2HeadersEnumerator();
enumerator.Initialize(headers);
var hpackEncoder = new HPackEncoder();
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(302, hpackEncoder, enumerator, buffer, out var length));
var result = buffer.Slice(0, length).ToArray();
var hex = BitConverter.ToString(result);
Assert.Equal("48-03-33-30-32", hex);
var statusHeader = GetHeaderEntry(hpackEncoder, 0);
Assert.Equal(":status", statusHeader.Name);
Assert.Equal("302", statusHeader.Value);
}
[Fact]
public void BeginEncodeHeaders_CacheControlPrivate_NewIndexValue()
{
Span<byte> buffer = new byte[1024 * 16];
var headers = new HttpResponseHeaders();
headers.HeaderCacheControl = "private";
var enumerator = new Http2HeadersEnumerator();
enumerator.Initialize(headers);
var hpackEncoder = new HPackEncoder();
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(302, hpackEncoder, enumerator, buffer, out var length));
var result = buffer.Slice(5, length - 5).ToArray();
var hex = BitConverter.ToString(result);
Assert.Equal("58-07-70-72-69-76-61-74-65", hex);
var statusHeader = GetHeaderEntry(hpackEncoder, 0);
Assert.Equal("Cache-Control", statusHeader.Name);
Assert.Equal("private", statusHeader.Value);
}
[Fact]
public void BeginEncodeHeaders_MaxHeaderTableSizeExceeded_EvictionsToFit()
{
// Test follows example https://tools.ietf.org/html/rfc7541#appendix-C.5
Span<byte> buffer = new byte[1024 * 16];
var headers = new HttpResponseHeaders();
headers.HeaderCacheControl = "private";
headers.HeaderDate = "Mon, 21 Oct 2013 20:13:21 GMT";
headers.HeaderLocation = "https://www.example.com";
var enumerator = new Http2HeadersEnumerator();
var hpackEncoder = new HPackEncoder(maxHeaderTableSize: 256);
// First response
enumerator.Initialize(headers);
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(302, hpackEncoder, enumerator, buffer, out var length));
var result = buffer.Slice(0, length).ToArray();
var hex = BitConverter.ToString(result);
Assert.Equal(
"48-03-33-30-32-58-07-70-72-69-76-61-74-65-61-1D-" +
"4D-6F-6E-2C-20-32-31-20-4F-63-74-20-32-30-31-33-" +
"20-32-30-3A-31-33-3A-32-31-20-47-4D-54-6E-17-68-" +
"74-74-70-73-3A-2F-2F-77-77-77-2E-65-78-61-6D-70-" +
"6C-65-2E-63-6F-6D", hex);
var entries = GetHeaderEntries(hpackEncoder);
Assert.Collection(entries,
e =>
{
Assert.Equal("Location", e.Name);
Assert.Equal("https://www.example.com", e.Value);
},
e =>
{
Assert.Equal("Date", e.Name);
Assert.Equal("Mon, 21 Oct 2013 20:13:21 GMT", e.Value);
},
e =>
{
Assert.Equal("Cache-Control", e.Name);
Assert.Equal("private", e.Value);
},
e =>
{
Assert.Equal(":status", e.Name);
Assert.Equal("302", e.Value);
});
// Second response
enumerator.Initialize(headers);
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(307, hpackEncoder, enumerator, buffer, out length));
result = buffer.Slice(0, length).ToArray();
hex = BitConverter.ToString(result);
Assert.Equal("48-03-33-30-37-C1-C0-BF", hex);
entries = GetHeaderEntries(hpackEncoder);
Assert.Collection(entries,
e =>
{
Assert.Equal(":status", e.Name);
Assert.Equal("307", e.Value);
},
e =>
{
Assert.Equal("Location", e.Name);
Assert.Equal("https://www.example.com", e.Value);
},
e =>
{
Assert.Equal("Date", e.Name);
Assert.Equal("Mon, 21 Oct 2013 20:13:21 GMT", e.Value);
},
e =>
{
Assert.Equal("Cache-Control", e.Name);
Assert.Equal("private", e.Value);
});
// Third response
headers.HeaderDate = "Mon, 21 Oct 2013 20:13:22 GMT";
headers.HeaderContentEncoding = "gzip";
headers.HeaderSetCookie = "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1";
enumerator.Initialize(headers);
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(200, hpackEncoder, enumerator, buffer, out length));
result = buffer.Slice(0, length).ToArray();
hex = BitConverter.ToString(result);
Assert.Equal(
"88-C1-61-1D-4D-6F-6E-2C-20-32-31-20-4F-63-74-20-" +
"32-30-31-33-20-32-30-3A-31-33-3A-32-32-20-47-4D-" +
"54-5A-04-67-7A-69-70-C1-1F-28-38-66-6F-6F-3D-41-" +
"53-44-4A-4B-48-51-4B-42-5A-58-4F-51-57-45-4F-50-" +
"49-55-41-58-51-57-45-4F-49-55-3B-20-6D-61-78-2D-" +
"61-67-65-3D-33-36-30-30-3B-20-76-65-72-73-69-6F-" +
"6E-3D-31", hex);
entries = GetHeaderEntries(hpackEncoder);
Assert.Collection(entries,
e =>
{
Assert.Equal("Content-Encoding", e.Name);
Assert.Equal("gzip", e.Value);
},
e =>
{
Assert.Equal("Date", e.Name);
Assert.Equal("Mon, 21 Oct 2013 20:13:22 GMT", e.Value);
},
e =>
{
Assert.Equal(":status", e.Name);
Assert.Equal("307", e.Value);
},
e =>
{
Assert.Equal("Location", e.Name);
Assert.Equal("https://www.example.com", e.Value);
});
}
[Theory]
[InlineData("Set-Cookie", true)]
[InlineData("Content-Disposition", true)]
[InlineData("Content-Length", false)]
public void BeginEncodeHeaders_ExcludedHeaders_NotAddedToTable(string headerName, bool neverIndex)
{
Span<byte> buffer = new byte[1024 * 16];
var headers = new HttpResponseHeaders();
headers.Append(headerName, "1");
var enumerator = new Http2HeadersEnumerator();
enumerator.Initialize(headers);
var hpackEncoder = new HPackEncoder(maxHeaderTableSize: Http2PeerSettings.DefaultHeaderTableSize);
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, enumerator, buffer, out _));
if (neverIndex)
{
Assert.Equal(0x10, buffer[0] & 0x10);
}
else
{
Assert.Equal(0, buffer[0] & 0x40);
}
Assert.Empty(GetHeaderEntries(hpackEncoder));
}
[Fact]
public void BeginEncodeHeaders_HeaderExceedHeaderTableSize_NoIndexAndNoHeaderEntry()
{
Span<byte> buffer = new byte[1024 * 16];
var headers = new HttpResponseHeaders();
headers.Append("x-Custom", new string('!', (int)Http2PeerSettings.DefaultHeaderTableSize));
var enumerator = new Http2HeadersEnumerator();
enumerator.Initialize(headers);
var hpackEncoder = new HPackEncoder();
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(200, hpackEncoder, enumerator, buffer, out var length));
Assert.Empty(GetHeaderEntries(hpackEncoder));
}
public static TheoryData<KeyValuePair<string, string>[], byte[], int?> SinglePayloadData
{
get
{
var data = new TheoryData<KeyValuePair<string, string>[], byte[], int?>();
// Lowercase header name letters only
data.Add(
new[]
{
new KeyValuePair<string, string>("CustomHeader", "CustomValue"),
},
new byte[]
{
// 12 c u s t o m
0x40, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
// h e a d e r 11 C
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0b, 0x43,
// u s t o m V a l
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x56, 0x61, 0x6c,
// u e
0x75, 0x65
},
null);
// Lowercase header name letters only
data.Add(
new[]
{
new KeyValuePair<string, string>("CustomHeader!#$%&'*+-.^_`|~", "CustomValue"),
},
new byte[]
{
// 27 c u s t o m
0x40, 0x1b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
// h e a d e r ! #
0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x21, 0x23,
// $ % & ' * + - .
0x24, 0x25, 0x26, 0x27, 0x2a, 0x2b, 0x2d, 0x2e,
// ^ _ ` | ~ 11 C u
0x5e, 0x5f, 0x60, 0x7c, 0x7e, 0x0b, 0x43, 0x75,
// s t o m V a l u
0x73, 0x74, 0x6f, 0x6d, 0x56, 0x61, 0x6c, 0x75,
// e
0x65
},
null);
// Single Payload
data.Add(
new[]
{
new KeyValuePair<string, string>("date", "Mon, 24 Jul 2017 19:22:30 GMT"),
new KeyValuePair<string, string>("content-type", "text/html; charset=utf-8"),
new KeyValuePair<string, string>("server", "Kestrel")
},
new byte[]
{
0x88, 0x40, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1d,
0x4d, 0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x34, 0x20,
0x4a, 0x75, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x37,
0x20, 0x31, 0x39, 0x3a, 0x32, 0x32, 0x3a, 0x33,
0x30, 0x20, 0x47, 0x4d, 0x54, 0x40, 0x0c, 0x63,
0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74,
0x79, 0x70, 0x65, 0x18, 0x74, 0x65, 0x78, 0x74,
0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3b, 0x20, 0x63,
0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x75,
0x74, 0x66, 0x2d, 0x38, 0x40, 0x06, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x07, 0x4b, 0x65, 0x73,
0x74, 0x72, 0x65, 0x6c
},
200);
return data;
}
}
[Theory]
[MemberData(nameof(SinglePayloadData))]
public void EncodesHeadersInSinglePayloadWhenSpaceAvailable(KeyValuePair<string, string>[] headers, byte[] expectedPayload, int? statusCode)
{
HPackEncoder hpackEncoder = new HPackEncoder();
var payload = new byte[1024];
var length = 0;
if (statusCode.HasValue)
{
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(statusCode.Value, hpackEncoder, GetHeadersEnumerator(headers), payload, out length));
}
else
{
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, GetHeadersEnumerator(headers), payload, out length));
}
Assert.Equal(expectedPayload.Length, length);
for (var i = 0; i < length; i++)
{
Assert.True(expectedPayload[i] == payload[i], $"{expectedPayload[i]} != {payload[i]} at {i} (len {length})");
}
Assert.Equal(expectedPayload, new ArraySegment<byte>(payload, 0, length));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void EncodesHeadersInMultiplePayloadsWhenSpaceNotAvailable(bool exactSize)
{
var statusCode = 200;
var headers = new[]
{
new KeyValuePair<string, string>("date", "Mon, 24 Jul 2017 19:22:30 GMT"),
new KeyValuePair<string, string>("content-type", "text/html; charset=utf-8"),
new KeyValuePair<string, string>("server", "Kestrel")
};
var expectedStatusCodePayload = new byte[]
{
0x88
};
var expectedDateHeaderPayload = new byte[]
{
0x40, 0x04, 0x64, 0x61, 0x74, 0x65, 0x1d, 0x4d,
0x6f, 0x6e, 0x2c, 0x20, 0x32, 0x34, 0x20, 0x4a,
0x75, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x37, 0x20,
0x31, 0x39, 0x3a, 0x32, 0x32, 0x3a, 0x33, 0x30,
0x20, 0x47, 0x4d, 0x54
};
var expectedContentTypeHeaderPayload = new byte[]
{
0x40, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x18, 0x74,
0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
0x3b, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,
0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38
};
var expectedServerHeaderPayload = new byte[]
{
0x40, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x07, 0x4b, 0x65, 0x73, 0x74, 0x72, 0x65, 0x6c
};
var hpackEncoder = new HPackEncoder();
Span<byte> payload = new byte[1024];
var offset = 0;
var headerEnumerator = GetHeadersEnumerator(headers);
// When !exactSize, slices are one byte short of fitting the next header
var sliceLength = expectedStatusCodePayload.Length + (exactSize ? 0 : expectedDateHeaderPayload.Length - 1);
Assert.False(HPackHeaderWriter.BeginEncodeHeaders(statusCode, hpackEncoder, headerEnumerator, payload.Slice(offset, sliceLength), out var length));
Assert.Equal(expectedStatusCodePayload.Length, length);
Assert.Equal(expectedStatusCodePayload, payload.Slice(0, length).ToArray());
offset += length;
sliceLength = expectedDateHeaderPayload.Length + (exactSize ? 0 : expectedContentTypeHeaderPayload.Length - 1);
Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(hpackEncoder, headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedDateHeaderPayload.Length, length);
Assert.Equal(expectedDateHeaderPayload, payload.Slice(offset, length).ToArray());
offset += length;
sliceLength = expectedContentTypeHeaderPayload.Length + (exactSize ? 0 : expectedServerHeaderPayload.Length - 1);
Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(hpackEncoder, headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedContentTypeHeaderPayload.Length, length);
Assert.Equal(expectedContentTypeHeaderPayload, payload.Slice(offset, length).ToArray());
offset += length;
sliceLength = expectedServerHeaderPayload.Length;
Assert.True(HPackHeaderWriter.ContinueEncodeHeaders(hpackEncoder, headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedServerHeaderPayload.Length, length);
Assert.Equal(expectedServerHeaderPayload, payload.Slice(offset, length).ToArray());
}
[Fact]
public void BeginEncodeHeaders_MaxHeaderTableSizeUpdated_SizeUpdateInHeaders()
{
Span<byte> buffer = new byte[1024 * 16];
var hpackEncoder = new HPackEncoder();
hpackEncoder.UpdateMaxHeaderTableSize(100);
var enumerator = new Http2HeadersEnumerator();
// First request
enumerator.Initialize(new Dictionary<string, StringValues>());
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, enumerator, buffer, out var length));
Assert.Equal(2, length);
const byte DynamicTableSizeUpdateMask = 0xe0;
var integerDecoder = new IntegerDecoder();
Assert.False(integerDecoder.BeginTryDecode((byte)(buffer[0] & ~DynamicTableSizeUpdateMask), prefixLength: 5, out _));
Assert.True(integerDecoder.TryDecode(buffer[1], out var result));
Assert.Equal(100, result);
// Second request
enumerator.Initialize(new Dictionary<string, StringValues>());
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, enumerator, buffer, out length));
Assert.Equal(0, length);
}
private static Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
{
var groupedHeaders = headers
.GroupBy(k => k.Key)
.ToDictionary(g => g.Key, g => new StringValues(g.Select(gg => gg.Value).ToArray()));
var enumerator = new Http2HeadersEnumerator();
enumerator.Initialize(groupedHeaders);
return enumerator;
}
private EncoderHeaderEntry GetHeaderEntry(HPackEncoder encoder, int index)
{
var entry = encoder.Head;
while (index-- >= 0)
{
entry = entry.Before;
}
return entry;
}
private List<EncoderHeaderEntry> GetHeaderEntries(HPackEncoder encoder)
{
var headers = new List<EncoderHeaderEntry>();
var entry = encoder.Head;
while (entry.Before != encoder.Head)
{
entry = entry.Before;
headers.Add(entry);
};
return headers;
}
}
}

View File

@ -333,11 +333,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Theory]
[InlineData(int.MinValue)]
[InlineData(-1)]
[InlineData(0)]
public void Http2HeaderTableSizeInvalid(int value)
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => new KestrelServerLimits().Http2.HeaderTableSize = value);
Assert.StartsWith(CoreStrings.GreaterThanZeroRequired, ex.Message);
Assert.StartsWith(CoreStrings.GreaterThanOrEqualToZeroRequired, ex.Message);
}
[Fact]

View File

@ -8,6 +8,7 @@ using System.Diagnostics;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Net.Http.HPack;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
@ -24,28 +25,25 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
public class Http2ConnectionBenchmark
public abstract class Http2ConnectionBenchmarkBase
{
private MemoryPool<byte> _memoryPool;
private HttpRequestHeaders _httpRequestHeaders;
private Http2Connection _connection;
private HPackEncoder _hpackEncoder;
private Http2HeadersEnumerator _requestHeadersEnumerator;
private int _currentStreamId;
private byte[] _headersBuffer;
private DuplexPipe.DuplexPipePair _connectionPair;
private Http2Frame _httpFrame;
private string _responseData;
private int _dataWritten;
[Params(0, 10, 1024 * 1024)]
public int ResponseDataLength { get; set; }
protected abstract Task ProcessRequest(HttpContext httpContext);
[GlobalSetup]
public void GlobalSetup()
public virtual void GlobalSetup()
{
_memoryPool = SlabMemoryPoolFactory.Create();
_httpFrame = new Http2Frame();
_responseData = new string('!', ResponseDataLength);
var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
@ -58,6 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
_httpRequestHeaders.Append(HeaderNames.Authority, new StringValues("localhost:80"));
_headersBuffer = new byte[1024 * 16];
_hpackEncoder = new HPackEncoder();
var serviceContext = new ServiceContext
{
@ -83,7 +82,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
_currentStreamId = 1;
_ = _connection.ProcessRequestsAsync(new DummyApplication(c => ResponseDataLength == 0 ? Task.CompletedTask : c.Response.WriteAsync(_responseData), new MockHttpContextFactory()));
_ = _connection.ProcessRequestsAsync(new DummyApplication(ProcessRequest, new MockHttpContextFactory()));
_connectionPair.Application.Output.Write(Http2Connection.ClientPreface);
_connectionPair.Application.Output.WriteSettings(new Http2PeerSettings
@ -102,11 +101,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
}
[Benchmark]
public async Task EmptyRequest()
public async Task MakeRequest()
{
_requestHeadersEnumerator.Initialize(_httpRequestHeaders);
_requestHeadersEnumerator.MoveNext();
_connectionPair.Application.Output.WriteStartStream(streamId: _currentStreamId, _requestHeadersEnumerator, _headersBuffer, endStream: true, frame: _httpFrame);
_connectionPair.Application.Output.WriteStartStream(streamId: _currentStreamId, _hpackEncoder, _requestHeadersEnumerator, _headersBuffer, endStream: true, frame: _httpFrame);
await _connectionPair.Application.Output.FlushAsync();
while (true)

View File

@ -0,0 +1,29 @@
// 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.
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
public class Http2ConnectionBenchmark : Http2ConnectionBenchmarkBase
{
[Params(0, 128, 1024)]
public int ResponseDataLength { get; set; }
private string _responseData;
[GlobalSetup]
public override void GlobalSetup()
{
base.GlobalSetup();
_responseData = new string('!', ResponseDataLength);
}
protected override Task ProcessRequest(HttpContext httpContext)
{
return ResponseDataLength == 0 ? Task.CompletedTask : httpContext.Response.WriteAsync(_responseData);
}
}
}

View File

@ -0,0 +1,48 @@
// 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.
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Performance
{
public class Http2ConnectionHeadersBenchmark : Http2ConnectionBenchmarkBase
{
[Params(1, 4, 32)]
public int HeadersCount { get; set; }
[Params(true, false)]
public bool HeadersChange { get; set; }
private int _headerIndex;
private string[] _headerNames;
[GlobalSetup]
public override void GlobalSetup()
{
base.GlobalSetup();
_headerNames = new string[HeadersCount * (HeadersChange ? 1000 : 1)];
for (var i = 0; i < _headerNames.Length; i++)
{
_headerNames[i] = "CustomHeader" + i;
}
}
protected override Task ProcessRequest(HttpContext httpContext)
{
for (var i = 0; i < HeadersCount; i++)
{
var headerName = _headerNames[_headerIndex % HeadersCount];
httpContext.Response.Headers[headerName] = "The quick brown fox jumps over the lazy dog.";
if (HeadersChange)
{
_headerIndex++;
}
}
return Task.CompletedTask;
}
}
}

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
minResponseDataRate: null,
"TestConnectionId",
_memoryPool,
new KestrelTrace(NullLogger.Instance));
new Core.Internal.ServiceContext());
_responseHeaders = new HttpResponseHeaders();
_responseHeaders.HeaderContentType = "application/json";

View File

@ -25,13 +25,13 @@ namespace Microsoft.AspNetCore.Testing
writer.Write(payload);
}
public static void WriteStartStream(this PipeWriter writer, int streamId, Http2HeadersEnumerator headers, byte[] headerEncodingBuffer, bool endStream, Http2Frame frame = null)
public static void WriteStartStream(this PipeWriter writer, int streamId, HPackEncoder hpackEncoder, Http2HeadersEnumerator headers, byte[] headerEncodingBuffer, bool endStream, Http2Frame frame = null)
{
frame ??= new Http2Frame();
frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
var buffer = headerEncodingBuffer.AsSpan();
var done = HPackHeaderWriter.BeginEncodeHeaders(headers, buffer, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, headers, buffer, out var length);
frame.PayloadLength = length;
if (done)
@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Testing
{
frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
done = HPackHeaderWriter.ContinueEncodeHeaders(headers, buffer, out length);
done = HPackHeaderWriter.ContinueEncodeHeaders(hpackEncoder, headers, buffer, out length);
frame.PayloadLength = length;
if (done)

View File

@ -14,10 +14,12 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@ -58,7 +60,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendWindowUpdateAsync(streamId: 1, 65535);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -90,7 +92,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, GetHeaders(responseBodySize: 3), endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
@ -101,7 +103,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(5, GetHeaders(responseBodySize: 3), endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 5);
@ -197,7 +199,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -274,7 +276,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, requestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -293,7 +295,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, requestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -323,7 +325,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
serverTcs.SetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -356,7 +358,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -371,7 +373,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _helloBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -415,7 +417,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
appDelegateTcs.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -438,7 +440,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
appDelegateTcs.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -475,7 +477,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
serverTcs.SetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -593,7 +595,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[length], endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
// The client's settings is still defaulted to Http2PeerSettings.MinAllowedMaxFrameSize so the echo response will come back in two separate frames
@ -622,7 +624,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -648,7 +650,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -691,7 +693,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -812,7 +814,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _noData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -840,7 +842,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var stream1DataFrame1 = await ExpectAsync(Http2FrameType.DATA,
@ -851,7 +853,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _helloBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
var stream3DataFrame1 = await ExpectAsync(Http2FrameType.DATA,
@ -920,7 +922,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -972,7 +974,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 0);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
@ -1050,7 +1052,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
stream3ReadFinished.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -1065,7 +1067,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
stream1ReadFinished.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1092,7 +1094,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataWithPaddingAsync(1, _helloWorldBytes, padLength, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -1137,7 +1139,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1196,7 +1198,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1265,7 +1267,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1440,7 +1442,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _postRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1482,7 +1484,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1532,7 +1534,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1636,7 +1638,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1657,7 +1659,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1691,7 +1693,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1706,7 +1708,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1726,7 +1728,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersWithPaddingAsync(1, _browserRequestHeaders, padLength, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1743,7 +1745,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersWithPriorityAsync(1, _browserRequestHeaders, priority: 42, streamDependency: 0, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1763,7 +1765,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersWithPaddingAndPriorityAsync(1, _browserRequestHeaders, padLength, priority: 42, streamDependency: 0, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1789,7 +1791,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The second stream should end first, since the first one is waiting for the request body.
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1801,7 +1803,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, _requestTrailers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1835,7 +1837,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1885,17 +1887,163 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
finishSecondRequest.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
finishFirstRequest.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
}
[Fact]
public async Task HEADERS_HeaderTableSizeLimitZero_Received_DynamicTableUpdate()
{
_serviceContext.ServerOptions.Limits.Http2.HeaderTableSize = 0;
await InitializeConnectionAsync(_noopApplication, expectedSettingsCount: 4);
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
_hpackEncoder.UpdateMaxHeaderTableSize(0);
var headerFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
const byte DynamicTableSizeUpdateMask = 0xe0;
var integerDecoder = new IntegerDecoder();
Assert.True(integerDecoder.BeginTryDecode((byte)(headerFrame.Payload.Span[0] & ~DynamicTableSizeUpdateMask), prefixLength: 5, out var result));
// Dynamic table update from the server
Assert.Equal(0, result);
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
}
[Fact]
public async Task HEADERS_ResponseSetsIgnoreIndexAndNeverIndexValues_HeadersParsed()
{
await InitializeConnectionAsync(c =>
{
c.Response.ContentLength = 0;
c.Response.Headers[HeaderNames.SetCookie] = "SetCookie!";
c.Response.Headers[HeaderNames.ContentDisposition] = "ContentDisposition!";
return Task.CompletedTask;
});
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var frame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 90,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
var handler = new TestHttpHeadersHandler();
var hpackDecoder = new HPackDecoder();
hpackDecoder.Decode(new ReadOnlySequence<byte>(frame.Payload), endHeaders: true, handler);
hpackDecoder.CompleteDecode();
Assert.Equal("200", handler.Headers[":status"]);
Assert.Equal("SetCookie!", handler.Headers[HeaderNames.SetCookie]);
Assert.Equal("ContentDisposition!", handler.Headers[HeaderNames.ContentDisposition]);
Assert.Equal("0", handler.Headers[HeaderNames.ContentLength]);
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
frame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 60,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
handler = new TestHttpHeadersHandler();
hpackDecoder.Decode(new ReadOnlySequence<byte>(frame.Payload), endHeaders: true, handler);
hpackDecoder.CompleteDecode();
Assert.Equal("200", handler.Headers[":status"]);
Assert.Equal("SetCookie!", handler.Headers[HeaderNames.SetCookie]);
Assert.Equal("ContentDisposition!", handler.Headers[HeaderNames.ContentDisposition]);
Assert.Equal("0", handler.Headers[HeaderNames.ContentLength]);
await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
}
private class TestHttpHeadersHandler : IHttpHeadersHandler
{
public readonly Dictionary<string, StringValues> Headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
public void OnHeader(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
{
var nameString = Encoding.ASCII.GetString(name);
var valueString = Encoding.ASCII.GetString(value);
if (Headers.TryGetValue(nameString, out var values))
{
var l = values.ToList();
l.Add(valueString);
Headers[nameString] = new StringValues(l.ToArray());
}
else
{
Headers[nameString] = new StringValues(valueString);
}
}
public void OnHeadersComplete(bool endStream)
{
throw new NotImplementedException();
}
public void OnStaticIndexedHeader(int index)
{
throw new NotImplementedException();
}
public void OnStaticIndexedHeader(int index, ReadOnlySpan<byte> value)
{
throw new NotImplementedException();
}
}
[Fact]
public async Task HEADERS_DisableDynamicHeaderCompression_HeadersNotCompressed()
{
_serviceContext.ServerOptions.AllowResponseHeaderCompression = false;
await InitializeConnectionAsync(_noopApplication);
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
}
@ -1918,7 +2066,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
requestBlocker.SetResult(0);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1961,7 +2109,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2004,7 +2152,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -2228,7 +2376,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2373,7 +2521,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2511,7 +2659,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2536,7 +2684,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The headers, but not the data for stream 3, can be sent prior to any window updates.
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
@ -2615,12 +2763,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
});
async Task VerifyStreamBackpressure(int streamId)
async Task VerifyStreamBackpressure(int streamId, int headersLength)
{
await StartStreamAsync(streamId, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: headersLength,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: streamId);
@ -2633,9 +2781,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.False(writeTasks[streamId].IsCompleted);
}
await VerifyStreamBackpressure(1);
await VerifyStreamBackpressure(3);
await VerifyStreamBackpressure(5);
await VerifyStreamBackpressure(1, 32);
await VerifyStreamBackpressure(3, 2);
await VerifyStreamBackpressure(5, 2);
await SendRstStreamAsync(1);
await writeTasks[1].DefaultTimeout();
@ -2913,6 +3061,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
CreateConnection();
_connection.ServerSettings.HeaderTableSize = 0;
_connection.ServerSettings.MaxConcurrentStreams = 1;
_connection.ServerSettings.MaxHeaderListSize = 4 * 1024;
_connection.ServerSettings.InitialWindowSize = 1024 * 1024 * 10;
@ -2923,23 +3072,27 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendSettingsAsync();
var frame = await ExpectAsync(Http2FrameType.SETTINGS,
withLength: Http2FrameReader.SettingSize * 3,
withLength: Http2FrameReader.SettingSize * 4,
withFlags: 0,
withStreamId: 0);
// Only non protocol defaults are sent
var settings = Http2FrameReader.ReadSettings(frame.PayloadSequence);
Assert.Equal(3, settings.Count);
Assert.Equal(4, settings.Count);
var setting = settings[0];
Assert.Equal(Http2SettingsParameter.SETTINGS_HEADER_TABLE_SIZE, setting.Parameter);
Assert.Equal(0u, setting.Value);
setting = settings[1];
Assert.Equal(Http2SettingsParameter.SETTINGS_MAX_CONCURRENT_STREAMS, setting.Parameter);
Assert.Equal(1u, setting.Value);
setting = settings[1];
setting = settings[2];
Assert.Equal(Http2SettingsParameter.SETTINGS_INITIAL_WINDOW_SIZE, setting.Parameter);
Assert.Equal(1024 * 1024 * 10u, setting.Value);
setting = settings[2];
setting = settings[3];
Assert.Equal(Http2SettingsParameter.SETTINGS_MAX_HEADER_LIST_SIZE, setting.Parameter);
Assert.Equal(4 * 1024u, setting.Value);
@ -3100,7 +3253,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_connection.ServerSettings.MaxFrameSize = Http2PeerSettings.MaxAllowedMaxFrameSize;
// This includes the default response headers such as :status, etc
var defaultResponseHeaderLength = 33;
var defaultResponseHeaderLength = 32;
var headerValueLength = Http2PeerSettings.MinAllowedMaxFrameSize;
// First byte is always 0
// Second byte is the length of header name which is 1
@ -3170,7 +3323,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3204,7 +3357,56 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2SettingsFrameFlags.ACK,
withStreamId: 0);
await StopConnectionAsync(expectedLastStreamId: 0, ignoreNonGoAwayFrames: false);
// Start request
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headerFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
// Headers start with :status = 200
Assert.Equal(0x88, headerFrame.Payload.Span[0]);
await StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
}
[Fact]
public async Task SETTINGS_Received_WithLargeHeaderTableSizeLimit_ChangesHeaderTableSize()
{
_serviceContext.ServerOptions.Limits.Http2.HeaderTableSize = 40000;
await InitializeConnectionAsync(_noopApplication, expectedSettingsCount: 4);
// Update client settings
_clientSettings.HeaderTableSize = 65536; // Chrome's default, larger than the 4kb spec default
await SendSettingsAsync();
// ACK
await ExpectAsync(Http2FrameType.SETTINGS,
withLength: 0,
withFlags: (byte)Http2SettingsFrameFlags.ACK,
withStreamId: 0);
// Start request
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headerFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 40,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
const byte DynamicTableSizeUpdateMask = 0xe0;
var integerDecoder = new IntegerDecoder();
Assert.False(integerDecoder.BeginTryDecode((byte)(headerFrame.Payload.Span[0] & ~DynamicTableSizeUpdateMask), prefixLength: 5, out _));
Assert.False(integerDecoder.TryDecode(headerFrame.Payload.Span[1], out _));
Assert.False(integerDecoder.TryDecode(headerFrame.Payload.Span[2], out _));
Assert.True(integerDecoder.TryDecode(headerFrame.Payload.Span[3], out var result));
Assert.Equal(40000, result);
await StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
}
[Fact]
@ -3319,7 +3521,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3332,7 +3534,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await SendDataAsync(3, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -3405,7 +3607,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3428,13 +3630,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The headers, but not the data for the stream, can still be sent.
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await StartStreamAsync(5, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 5);
@ -3493,12 +3695,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
});
async Task VerifyStreamBackpressure(int streamId)
async Task VerifyStreamBackpressure(int streamId, int headersLength)
{
await StartStreamAsync(streamId, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: headersLength,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: streamId);
@ -3511,9 +3713,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.False(writeTasks[streamId].IsCompleted);
}
await VerifyStreamBackpressure(1);
await VerifyStreamBackpressure(3);
await VerifyStreamBackpressure(5);
await VerifyStreamBackpressure(1, 32);
await VerifyStreamBackpressure(3, 2);
await VerifyStreamBackpressure(5, 2);
// Close all pipes and wait for response to drain
_pair.Application.Output.Complete();
@ -3731,7 +3933,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3788,7 +3990,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3827,7 +4029,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3879,7 +4081,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _twoContinuationsRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3906,7 +4108,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The second stream should end first, since the first one is waiting for the request body.
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -3929,7 +4131,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendContinuationAsync(1, Http2ContinuationFrameFlags.END_HEADERS, trailers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -4027,7 +4229,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendEmptyContinuationFrameAsync(1, Http2ContinuationFrameFlags.END_HEADERS);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -4042,7 +4244,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 12343,
withLength: 12342,
withFlags: (byte)Http2HeadersFrameFlags.END_STREAM,
withStreamId: 1);
var continuationFrame1 = await ExpectAsync(Http2FrameType.CONTINUATION,
@ -4201,7 +4403,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -4251,7 +4453,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -4284,8 +4486,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: false);
await SendDataAsync(1, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
var f = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -4298,7 +4500,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await SendDataAsync(3, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -4388,7 +4590,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);

View File

@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 52,
withLength: 51,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 53,
withLength: 52,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -131,7 +131,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 57,
withLength: 56,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 58,
withLength: 57,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -193,7 +193,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 100,
withLength: 99,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -235,7 +235,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -297,7 +297,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -326,7 +326,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -355,7 +355,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 47,
withLength: 46,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -386,7 +386,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 47,
withLength: 46,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -417,7 +417,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 47,
withLength: 46,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -448,7 +448,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 47,
withLength: 46,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -570,7 +570,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -611,7 +611,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -655,7 +655,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[8], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -698,7 +698,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[8], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -751,7 +751,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[8], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -983,7 +983,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1015,7 +1015,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.RST_STREAM,
@ -1054,7 +1054,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1092,7 +1092,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1125,7 +1125,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1160,7 +1160,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1198,7 +1198,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1236,7 +1236,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1276,7 +1276,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1323,7 +1323,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1361,7 +1361,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1397,7 +1397,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1441,7 +1441,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1475,7 +1475,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1508,7 +1508,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1552,7 +1552,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1591,7 +1591,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 41,
withLength: 40,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1634,7 +1634,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1674,7 +1674,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[6], endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 41,
withLength: 40,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1733,7 +1733,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[6], endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 41,
withLength: 40,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1788,7 +1788,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1814,7 +1814,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1852,7 +1852,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_STREAM | Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
@ -1883,7 +1883,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame1 = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var trailersFrame1 = await ExpectAsync(Http2FrameType.HEADERS,
@ -1894,12 +1894,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
var headersFrame2 = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 3);
var trailersFrame2 = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 25,
withLength: 1,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1930,7 +1930,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1980,7 +1980,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2039,7 +2039,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2074,7 +2074,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2124,7 +2124,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true).DefaultTimeout();
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1).DefaultTimeout();
@ -2189,7 +2189,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2235,7 +2235,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2269,7 +2269,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -2532,7 +2532,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -2623,7 +2623,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2671,7 +2671,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// Just the StatusCode gets written before aborting in the continuation frame
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.NONE,
withStreamId: 1);
@ -2700,7 +2700,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2743,7 +2743,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2789,7 +2789,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2835,7 +2835,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2884,7 +2884,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2937,7 +2937,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2987,7 +2987,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3037,7 +3037,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3080,7 +3080,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3126,7 +3126,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3168,7 +3168,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3213,7 +3213,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3279,7 +3279,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3325,7 +3325,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3361,7 +3361,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3413,7 +3413,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3465,7 +3465,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3498,7 +3498,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// Don't receive content length because we called WriteAsync which caused an invalid response
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS | (byte)Http2HeadersFrameFlags.END_STREAM,
withStreamId: 1);
@ -3531,7 +3531,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3583,7 +3583,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3639,7 +3639,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var trailersFrame = await ExpectAsync(Http2FrameType.HEADERS,
@ -3705,7 +3705,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3761,7 +3761,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3826,7 +3826,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3885,7 +3885,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3941,7 +3941,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -4003,7 +4003,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4077,7 +4077,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4153,7 +4153,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4224,7 +4224,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 38,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4296,7 +4296,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4380,7 +4380,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4461,7 +4461,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4548,7 +4548,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4608,7 +4608,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, LatinHeaderData, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);

View File

@ -121,6 +121,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
internal readonly Http2PeerSettings _clientSettings = new Http2PeerSettings();
internal readonly HPackDecoder _hpackDecoder;
internal readonly HPackEncoder _hpackEncoder;
private readonly byte[] _headerEncodingBuffer = new byte[Http2PeerSettings.MinAllowedMaxFrameSize];
internal readonly TimeoutControl _timeoutControl;
@ -165,6 +166,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
public Http2TestBase()
{
_hpackDecoder = new HPackDecoder((int)_clientSettings.HeaderTableSize, MaxRequestHeaderFieldSize);
_hpackEncoder = new HPackEncoder();
_timeoutControl = new TimeoutControl(_mockTimeoutHandler.Object);
_mockTimeoutControl = new Mock<MockTimeoutControlBase>(_timeoutControl) { CallBase = true };
@ -501,7 +503,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
_runningStreams[streamId] = tcs;
writableBuffer.WriteStartStream(streamId, GetHeadersEnumerator(headers), _headerEncodingBuffer, endStream);
writableBuffer.WriteStartStream(streamId, _hpackEncoder, GetHeadersEnumerator(headers), _headerEncodingBuffer, endStream);
return FlushAsync(writableBuffer);
}
@ -541,7 +543,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
extendedHeader[0] = padLength;
var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(_hpackEncoder, GetHeadersEnumerator(headers), payload, out var length);
var padding = buffer.Slice(extendedHeaderLength + length, padLength);
padding.Fill(0);
@ -584,7 +586,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
extendedHeader[4] = priority;
var payload = buffer.Slice(extendedHeaderLength);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(_hpackEncoder, GetHeadersEnumerator(headers), payload, out var length);
frame.PayloadLength = extendedHeaderLength + length;
@ -631,7 +633,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
extendedHeader[5] = priority;
var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(_hpackEncoder, GetHeadersEnumerator(headers), payload, out var length);
var padding = buffer.Slice(extendedHeaderLength + length, padLength);
padding.Fill(0);
@ -745,7 +747,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
frame.PrepareHeaders(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = HPackHeaderWriter.BeginEncodeHeaders(headersEnumerator, buffer.Span, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(_hpackEncoder, headersEnumerator, buffer.Span, out var length);
frame.PayloadLength = length;
Http2FrameWriter.WriteHeader(frame, outputWriter);
@ -815,7 +817,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
frame.PrepareContinuation(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = HPackHeaderWriter.ContinueEncodeHeaders(headersEnumerator, buffer.Span, out var length);
var done = HPackHeaderWriter.ContinueEncodeHeaders(_hpackEncoder, headersEnumerator, buffer.Span, out var length);
frame.PayloadLength = length;
Http2FrameWriter.WriteHeader(frame, outputWriter);
@ -843,7 +845,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
frame.PrepareContinuation(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), buffer.Span, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(_hpackEncoder, GetHeadersEnumerator(headers), buffer.Span, out var length);
frame.PayloadLength = length;
Http2FrameWriter.WriteHeader(frame, outputWriter);

View File

@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_mockTimeoutControl.Verify(c => c.SetTimeout(It.IsAny<long>(), TimeoutReason.RequestHeaders), Times.Once);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 36,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -283,7 +283,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -390,7 +390,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -445,7 +445,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -501,7 +501,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -513,7 +513,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -567,7 +567,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -616,7 +616,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -669,7 +669,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -682,7 +682,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -738,7 +738,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -756,7 +756,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 2,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -813,7 +813,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -885,7 +885,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 33,
withLength: 32,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -902,7 +902,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
backpressureTcs.SetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 6,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);

View File

@ -1118,7 +1118,7 @@ namespace Interop.FunctionalTests
Assert.Equal(oneKbString + i, response.Headers.GetValues("header" + i).Single());
}
Assert.Single(TestSink.Writes.Where(context => context.Message.Contains("sending HEADERS frame for stream ID 1 with length 15612 and flags END_STREAM")));
Assert.Single(TestSink.Writes.Where(context => context.Message.Contains("sending HEADERS frame for stream ID 1 with length 15610 and flags END_STREAM")));
Assert.Equal(2, TestSink.Writes.Where(context => context.Message.Contains("sending CONTINUATION frame for stream ID 1 with length 15585 and flags NONE")).Count());
Assert.Single(TestSink.Writes.Where(context => context.Message.Contains("sending CONTINUATION frame for stream ID 1 with length 14546 and flags END_HEADERS")));

View File

@ -0,0 +1,73 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
namespace System.Net.Http.HPack
{
[DebuggerDisplay("Name = {Name} Value = {Value}")]
internal class EncoderHeaderEntry
{
// Header name and value
public string Name;
public string Value;
// Chained list of headers in the same bucket
public EncoderHeaderEntry Next;
public int Hash;
// Compute dynamic table index
public int Index;
// Doubly linked list
public EncoderHeaderEntry Before;
public EncoderHeaderEntry After;
/// <summary>
/// Initialize header values. An entry will be reinitialized when reused.
/// </summary>
public void Initialize(int hash, string name, string value, int index, EncoderHeaderEntry next)
{
Debug.Assert(name != null);
Debug.Assert(value != null);
Name = name;
Value = value;
Index = index;
Hash = hash;
Next = next;
}
public uint CalculateSize()
{
return (uint)HeaderField.GetLength(Name.Length, Value.Length);
}
/// <summary>
/// Remove entry from the linked list and reset header values.
/// </summary>
public void Remove()
{
Before.After = After;
After.Before = Before;
Before = null;
After = null;
Next = null;
Hash = 0;
Name = null;
Value = null;
}
/// <summary>
/// Add before an entry in the linked list.
/// </summary>
public void AddBefore(EncoderHeaderEntry existingEntry)
{
After = existingEntry;
Before = existingEntry.Before;
Before.After = this;
After.Before = this;
}
}
}

View File

@ -0,0 +1,295 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Diagnostics;
namespace System.Net.Http.HPack
{
internal partial class HPackEncoder
{
public const int DefaultHeaderTableSize = 4096;
// Internal for testing
internal readonly EncoderHeaderEntry Head;
private readonly bool _allowDynamicCompression;
private readonly EncoderHeaderEntry[] _headerBuckets;
private readonly byte _hashMask;
private uint _headerTableSize;
private uint _maxHeaderTableSize;
private bool _pendingTableSizeUpdate;
private EncoderHeaderEntry? _removed;
public HPackEncoder(bool allowDynamicCompression = true, uint maxHeaderTableSize = DefaultHeaderTableSize)
{
_allowDynamicCompression = allowDynamicCompression;
_maxHeaderTableSize = maxHeaderTableSize;
Head = new EncoderHeaderEntry();
Head.Initialize(-1, string.Empty, string.Empty, int.MaxValue, null);
// Bucket count balances memory usage and the expected low number of headers (constrained by the header table size).
// Performance with different bucket counts hasn't been measured in detail.
_headerBuckets = new EncoderHeaderEntry[16];
_hashMask = (byte)(_headerBuckets.Length - 1);
Head.Before = Head.After = Head;
}
public void UpdateMaxHeaderTableSize(uint maxHeaderTableSize)
{
if (_maxHeaderTableSize != maxHeaderTableSize)
{
_maxHeaderTableSize = maxHeaderTableSize;
// Dynamic table size update will be written next HEADERS frame
_pendingTableSizeUpdate = true;
// Check capacity and remove entries that exceed the new capacity
EnsureCapacity(0);
}
}
public bool EnsureDynamicTableSizeUpdate(Span<byte> buffer, out int length)
{
// Check if there is a table size update that should be encoded
if (_pendingTableSizeUpdate)
{
bool success = EncodeDynamicTableSizeUpdate((int)_maxHeaderTableSize, buffer, out length);
_pendingTableSizeUpdate = false;
return success;
}
length = 0;
return true;
}
public bool EncodeHeader(Span<byte> buffer, int staticTableIndex, HeaderEncodingHint encodingHint, string name, string value, out int bytesWritten)
{
Debug.Assert(!_pendingTableSizeUpdate, "Dynamic table size update should be encoded before headers.");
// Never index sensitive value.
if (encodingHint == HeaderEncodingHint.NeverIndex)
{
int index = ResolveDynamicTableIndex(staticTableIndex, name);
return index == -1
? EncodeLiteralHeaderFieldNeverIndexingNewName(name, value, buffer, out bytesWritten)
: EncodeLiteralHeaderFieldNeverIndexing(index, value, buffer, out bytesWritten);
}
// No dynamic table. Only use the static table.
if (!_allowDynamicCompression || _maxHeaderTableSize == 0 || encodingHint == HeaderEncodingHint.IgnoreIndex)
{
return staticTableIndex == -1
? EncodeLiteralHeaderFieldWithoutIndexingNewName(name, value, buffer, out bytesWritten)
: EncodeLiteralHeaderFieldWithoutIndexing(staticTableIndex, value, buffer, out bytesWritten);
}
// Header is greater than the maximum table size.
// Don't attempt to add dynamic header as all existing dynamic headers will be removed.
if (HeaderField.GetLength(name.Length, value.Length) > _maxHeaderTableSize)
{
int index = ResolveDynamicTableIndex(staticTableIndex, name);
return index == -1
? EncodeLiteralHeaderFieldWithoutIndexingNewName(name, value, buffer, out bytesWritten)
: EncodeLiteralHeaderFieldWithoutIndexing(index, value, buffer, out bytesWritten);
}
return EncodeDynamicHeader(buffer, staticTableIndex, name, value, out bytesWritten);
}
private int ResolveDynamicTableIndex(int staticTableIndex, string name)
{
if (staticTableIndex != -1)
{
// Prefer static table index.
return staticTableIndex;
}
return CalculateDynamicTableIndex(name);
}
private bool EncodeDynamicHeader(Span<byte> buffer, int staticTableIndex, string name, string value, out int bytesWritten)
{
EncoderHeaderEntry? headerField = GetEntry(name, value);
if (headerField != null)
{
// Already exists in dynamic table. Write index.
int index = CalculateDynamicTableIndex(headerField.Index);
return EncodeIndexedHeaderField(index, buffer, out bytesWritten);
}
else
{
// Doesn't exist in dynamic table. Add new entry to dynamic table.
uint headerSize = (uint)HeaderField.GetLength(name.Length, value.Length);
int index = ResolveDynamicTableIndex(staticTableIndex, name);
bool success = index == -1
? EncodeLiteralHeaderFieldIndexingNewName(name, value, buffer, out bytesWritten)
: EncodeLiteralHeaderFieldIndexing(index, value, buffer, out bytesWritten);
if (success)
{
EnsureCapacity(headerSize);
AddHeaderEntry(name, value, headerSize);
}
return success;
}
}
/// <summary>
/// Ensure there is capacity for the new header. If there is not enough capacity then remove
/// existing headers until space is available.
/// </summary>
private void EnsureCapacity(uint headerSize)
{
Debug.Assert(headerSize <= _maxHeaderTableSize, "Header is bigger than dynamic table size.");
while (_maxHeaderTableSize - _headerTableSize < headerSize)
{
EncoderHeaderEntry? removed = RemoveHeaderEntry();
Debug.Assert(removed != null);
// Removed entries are tracked to be reused.
PushRemovedEntry(removed);
}
}
private EncoderHeaderEntry? GetEntry(string name, string value)
{
if (_headerTableSize == 0)
{
return null;
}
int hash = name.GetHashCode();
int bucketIndex = CalculateBucketIndex(hash);
for (EncoderHeaderEntry? e = _headerBuckets[bucketIndex]; e != null; e = e.Next)
{
// We've already looked up entries based on a hash of the name.
// Compare value before name as it is more likely to be different.
if (e.Hash == hash &&
string.Equals(value, e.Value, StringComparison.Ordinal) &&
string.Equals(name, e.Name, StringComparison.Ordinal))
{
return e;
}
}
return null;
}
private int CalculateDynamicTableIndex(string name)
{
if (_headerTableSize == 0)
{
return -1;
}
int hash = name.GetHashCode();
int bucketIndex = CalculateBucketIndex(hash);
for (EncoderHeaderEntry? e = _headerBuckets[bucketIndex]; e != null; e = e.Next)
{
if (e.Hash == hash && string.Equals(name, e.Name, StringComparison.Ordinal))
{
return CalculateDynamicTableIndex(e.Index);
}
}
return -1;
}
private int CalculateDynamicTableIndex(int index)
{
return index == -1 ? -1 : index - Head.Before.Index + 1 + H2StaticTable.Count;
}
private void AddHeaderEntry(string name, string value, uint headerSize)
{
Debug.Assert(headerSize <= _maxHeaderTableSize, "Header is bigger than dynamic table size.");
Debug.Assert(headerSize <= _maxHeaderTableSize - _headerTableSize, "Not enough room in dynamic table.");
int hash = name.GetHashCode();
int bucketIndex = CalculateBucketIndex(hash);
EncoderHeaderEntry? oldEntry = _headerBuckets[bucketIndex];
// Attempt to reuse removed entry
EncoderHeaderEntry? newEntry = PopRemovedEntry() ?? new EncoderHeaderEntry();
newEntry.Initialize(hash, name, value, Head.Before.Index - 1, oldEntry);
_headerBuckets[bucketIndex] = newEntry;
newEntry.AddBefore(Head);
_headerTableSize += headerSize;
}
private void PushRemovedEntry(EncoderHeaderEntry removed)
{
if (_removed != null)
{
removed.Next = _removed;
}
_removed = removed;
}
private EncoderHeaderEntry? PopRemovedEntry()
{
if (_removed != null)
{
EncoderHeaderEntry? removed = _removed;
_removed = _removed.Next;
return removed;
}
return null;
}
/// <summary>
/// Remove the oldest entry.
/// </summary>
private EncoderHeaderEntry? RemoveHeaderEntry()
{
if (_headerTableSize == 0)
{
return null;
}
EncoderHeaderEntry? eldest = Head.After;
int hash = eldest.Hash;
int bucketIndex = CalculateBucketIndex(hash);
EncoderHeaderEntry? prev = _headerBuckets[bucketIndex];
EncoderHeaderEntry? e = prev;
while (e != null)
{
EncoderHeaderEntry next = e.Next;
if (e == eldest)
{
if (prev == eldest)
{
_headerBuckets[bucketIndex] = next;
}
else
{
prev.Next = next;
}
_headerTableSize -= eldest.CalculateSize();
eldest.Remove();
return eldest;
}
prev = e;
e = next;
}
return null;
}
private int CalculateBucketIndex(int hash)
{
return hash & _hashMask;
}
}
/// <summary>
/// Hint for how the header should be encoded as HPack. This value can be overriden.
/// For example, a header that is larger than the dynamic table won't be indexed.
/// </summary>
internal enum HeaderEncodingHint
{
Index,
IgnoreIndex,
NeverIndex
}
}

View File

@ -0,0 +1,3 @@
HPack dynamic compression. These files are kept separate to help avoid ASP.NET Core dependencies being added to them.
Runtime currently doesn't implement HPack dynamic compression. These files will move into runtime shareable code in the future when support is added to runtime.

View File

@ -0,0 +1,151 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Globalization;
using System.Text;
namespace System.Net.Http.HPack
{
internal static partial class StatusCodes
{
public static string ToStatusString(int statusCode)
{
switch (statusCode)
{
case (int)HttpStatusCode.Continue:
return "100";
case (int)HttpStatusCode.SwitchingProtocols:
return "101";
case (int)HttpStatusCode.Processing:
return "102";
case (int)HttpStatusCode.OK:
return "200";
case (int)HttpStatusCode.Created:
return "201";
case (int)HttpStatusCode.Accepted:
return "202";
case (int)HttpStatusCode.NonAuthoritativeInformation:
return "203";
case (int)HttpStatusCode.NoContent:
return "204";
case (int)HttpStatusCode.ResetContent:
return "205";
case (int)HttpStatusCode.PartialContent:
return "206";
case (int)HttpStatusCode.MultiStatus:
return "207";
case (int)HttpStatusCode.AlreadyReported:
return "208";
case (int)HttpStatusCode.IMUsed:
return "226";
case (int)HttpStatusCode.MultipleChoices:
return "300";
case (int)HttpStatusCode.MovedPermanently:
return "301";
case (int)HttpStatusCode.Found:
return "302";
case (int)HttpStatusCode.SeeOther:
return "303";
case (int)HttpStatusCode.NotModified:
return "304";
case (int)HttpStatusCode.UseProxy:
return "305";
case (int)HttpStatusCode.Unused:
return "306";
case (int)HttpStatusCode.TemporaryRedirect:
return "307";
case (int)HttpStatusCode.PermanentRedirect:
return "308";
case (int)HttpStatusCode.BadRequest:
return "400";
case (int)HttpStatusCode.Unauthorized:
return "401";
case (int)HttpStatusCode.PaymentRequired:
return "402";
case (int)HttpStatusCode.Forbidden:
return "403";
case (int)HttpStatusCode.NotFound:
return "404";
case (int)HttpStatusCode.MethodNotAllowed:
return "405";
case (int)HttpStatusCode.NotAcceptable:
return "406";
case (int)HttpStatusCode.ProxyAuthenticationRequired:
return "407";
case (int)HttpStatusCode.RequestTimeout:
return "408";
case (int)HttpStatusCode.Conflict:
return "409";
case (int)HttpStatusCode.Gone:
return "410";
case (int)HttpStatusCode.LengthRequired:
return "411";
case (int)HttpStatusCode.PreconditionFailed:
return "412";
case (int)HttpStatusCode.RequestEntityTooLarge:
return "413";
case (int)HttpStatusCode.RequestUriTooLong:
return "414";
case (int)HttpStatusCode.UnsupportedMediaType:
return "415";
case (int)HttpStatusCode.RequestedRangeNotSatisfiable:
return "416";
case (int)HttpStatusCode.ExpectationFailed:
return "417";
case (int)418:
return "418";
case (int)419:
return "419";
case (int)HttpStatusCode.MisdirectedRequest:
return "421";
case (int)HttpStatusCode.UnprocessableEntity:
return "422";
case (int)HttpStatusCode.Locked:
return "423";
case (int)HttpStatusCode.FailedDependency:
return "424";
case (int)HttpStatusCode.UpgradeRequired:
return "426";
case (int)HttpStatusCode.PreconditionRequired:
return "428";
case (int)HttpStatusCode.TooManyRequests:
return "429";
case (int)HttpStatusCode.RequestHeaderFieldsTooLarge:
return "431";
case (int)HttpStatusCode.UnavailableForLegalReasons:
return "451";
case (int)HttpStatusCode.InternalServerError:
return "500";
case (int)HttpStatusCode.NotImplemented:
return "501";
case (int)HttpStatusCode.BadGateway:
return "502";
case (int)HttpStatusCode.ServiceUnavailable:
return "503";
case (int)HttpStatusCode.GatewayTimeout:
return "504";
case (int)HttpStatusCode.HttpVersionNotSupported:
return "505";
case (int)HttpStatusCode.VariantAlsoNegotiates:
return "506";
case (int)HttpStatusCode.InsufficientStorage:
return "507";
case (int)HttpStatusCode.LoopDetected:
return "508";
case (int)HttpStatusCode.NotExtended:
return "510";
case (int)HttpStatusCode.NetworkAuthenticationRequired:
return "511";
default:
return statusCode.ToString(CultureInfo.InvariantCulture);
}
}
}
}

View File

@ -8,7 +8,7 @@ using System.Diagnostics;
namespace System.Net.Http.HPack
{
internal static class HPackEncoder
internal partial class HPackEncoder
{
// Things we should add:
// * Huffman encoding
@ -109,6 +109,70 @@ namespace System.Net.Http.HPack
return false;
}
/// <summary>Encodes a "Literal Header Field never Indexing".</summary>
public static bool EncodeLiteralHeaderFieldNeverIndexing(int index, string value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-6.2.3
// ------------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 0 | 1 | Index (4+) |
// +---+---+-----------------------+
// | H | Value Length (7+) |
// +---+---------------------------+
// | Value String (Length octets) |
// +-------------------------------+
if ((uint)destination.Length >= 2)
{
destination[0] = 0x10;
if (IntegerEncoder.Encode(index, 4, destination, out int indexLength))
{
Debug.Assert(indexLength >= 1);
if (EncodeStringLiteral(value, destination.Slice(indexLength), out int nameLength))
{
bytesWritten = indexLength + nameLength;
return true;
}
}
}
bytesWritten = 0;
return false;
}
/// <summary>Encodes a "Literal Header Field with Indexing".</summary>
public static bool EncodeLiteralHeaderFieldIndexing(int index, string value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-6.2.2
// ------------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | 0 | 1 | Index (6+) |
// +---+---+-----------------------+
// | H | Value Length (7+) |
// +---+---------------------------+
// | Value String (Length octets) |
// +-------------------------------+
if ((uint)destination.Length >= 2)
{
destination[0] = 0x40;
if (IntegerEncoder.Encode(index, 6, destination, out int indexLength))
{
Debug.Assert(indexLength >= 1);
if (EncodeStringLiteral(value, destination.Slice(indexLength), out int nameLength))
{
bytesWritten = indexLength + nameLength;
return true;
}
}
}
bytesWritten = 0;
return false;
}
/// <summary>
/// Encodes a "Literal Header Field without Indexing", but only the index portion;
/// a subsequent call to <c>EncodeStringLiteral</c> must be used to encode the associated value.
@ -144,6 +208,27 @@ namespace System.Net.Http.HPack
return false;
}
/// <summary>Encodes a "Literal Header Field with Indexing - New Name".</summary>
public static bool EncodeLiteralHeaderFieldIndexingNewName(string name, string value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-6.2.2
// ------------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | 0 | 1 | 0 |
// +---+---+-----------------------+
// | H | Name Length (7+) |
// +---+---------------------------+
// | Name String (Length octets) |
// +---+---------------------------+
// | H | Value Length (7+) |
// +---+---------------------------+
// | Value String (Length octets) |
// +-------------------------------+
return EncodeLiteralHeaderNewNameCore(0x40, name, value, destination, out bytesWritten);
}
/// <summary>Encodes a "Literal Header Field without Indexing - New Name".</summary>
public static bool EncodeLiteralHeaderFieldWithoutIndexingNewName(string name, string value, Span<byte> destination, out int bytesWritten)
{
@ -162,9 +247,35 @@ namespace System.Net.Http.HPack
// | Value String (Length octets) |
// +-------------------------------+
return EncodeLiteralHeaderNewNameCore(0, name, value, destination, out bytesWritten);
}
/// <summary>Encodes a "Literal Header Field never Indexing - New Name".</summary>
public static bool EncodeLiteralHeaderFieldNeverIndexingNewName(string name, string value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-6.2.3
// ------------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 0 | 1 | 0 |
// +---+---+-----------------------+
// | H | Name Length (7+) |
// +---+---------------------------+
// | Name String (Length octets) |
// +---+---------------------------+
// | H | Value Length (7+) |
// +---+---------------------------+
// | Value String (Length octets) |
// +-------------------------------+
return EncodeLiteralHeaderNewNameCore(0x10, name, value, destination, out bytesWritten);
}
private static bool EncodeLiteralHeaderNewNameCore(byte mask, string name, string value, Span<byte> destination, out int bytesWritten)
{
if ((uint)destination.Length >= 3)
{
destination[0] = 0;
destination[0] = mask;
if (EncodeLiteralHeaderName(name, destination.Slice(1), out int nameLength) &&
EncodeStringLiteral(value, destination.Slice(1 + nameLength), out int valueLength))
{
@ -372,6 +483,25 @@ namespace System.Net.Http.HPack
return false;
}
public static bool EncodeDynamicTableSizeUpdate(int value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-6.3
// ----------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 1 | Max size (5+) |
// +---+---------------------------+
if (destination.Length != 0)
{
destination[0] = 0x20;
return IntegerEncoder.Encode(value, 5, destination, out bytesWritten);
}
bytesWritten = 0;
return false;
}
public static bool EncodeStringLiterals(ReadOnlySpan<string> values, string? separator, Span<byte> destination, out int bytesWritten)
{
bytesWritten = 0;

View File

@ -7,7 +7,7 @@ using System.Text;
namespace System.Net.Http.HPack
{
internal static class StatusCodes
internal static partial class StatusCodes
{
// This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static

View File

@ -424,7 +424,7 @@ namespace Microsoft.DotNet.OpenApi.Add.Tests
{
var project = CreateBasicProject(withOpenApi: false);
var app = GetApplication(realHttp: true);
var app = GetApplication();
var url = BrokenUrl;
var run = app.Execute(new[] { "add", "url", url });

View File

@ -106,7 +106,8 @@ namespace Microsoft.DotNet.OpenApi.Tests
{ PackageUrl, Tuple.Create<string, ContentDispositionHeaderValue>(PackageUrlContent, null) },
{ NoDispositionUrl, Tuple.Create<string, ContentDispositionHeaderValue>(Content, null) },
{ NoExtensionUrl, Tuple.Create(Content, noExtension) },
{ NoSegmentUrl, Tuple.Create(Content, justAttachments) }
{ NoSegmentUrl, Tuple.Create(Content, justAttachments) },
{ BrokenUrl, null }
};
}
@ -139,10 +140,14 @@ namespace Microsoft.DotNet.OpenApi.Tests
public Task<IHttpResponseMessageWrapper> GetResponseAsync(string url)
{
var result = _results[url];
byte[] byteArray = Encoding.ASCII.GetBytes(result.Item1);
var stream = new MemoryStream(byteArray);
MemoryStream stream = null;
if(result != null)
{
byte[] byteArray = Encoding.ASCII.GetBytes(result.Item1);
stream = new MemoryStream(byteArray);
}
return Task.FromResult<IHttpResponseMessageWrapper>(new TestHttpResponseMessageWrapper(stream, result.Item2));
return Task.FromResult<IHttpResponseMessageWrapper>(new TestHttpResponseMessageWrapper(stream, result?.Item2));
}
}
@ -154,7 +159,17 @@ namespace Microsoft.DotNet.OpenApi.Tests
public bool IsSuccessCode()
{
return true;
switch(StatusCode)
{
case HttpStatusCode.OK:
case HttpStatusCode.Created:
case HttpStatusCode.NoContent:
case HttpStatusCode.Accepted:
return true;
case HttpStatusCode.NotFound:
default:
return false;
}
}
private readonly ContentDispositionHeaderValue _contentDisposition;
@ -164,6 +179,10 @@ namespace Microsoft.DotNet.OpenApi.Tests
ContentDispositionHeaderValue header)
{
Stream = Task.FromResult<Stream>(stream);
if (header is null && stream is null)
{
StatusCode = HttpStatusCode.NotFound;
}
_contentDisposition = header;
}