Skip to content

Commit 9e67b7b

Browse files
gfoidlhalter73
authored andcommitted
Use C#'s ReadOnlySpan static data optimization in more places (#14447)
1 parent 178197e commit 9e67b7b

File tree

18 files changed

+200
-47
lines changed

18 files changed

+200
-47
lines changed

src/Http/WebUtilities/src/FormPipeReader.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class FormPipeReader
2929
private const int DefaultValueLengthLimit = 1024 * 1024 * 4;
3030

3131
// Used for UTF8/ASCII (precalculated for fast path)
32+
// 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
3233
private static ReadOnlySpan<byte> UTF8EqualEncoded => new byte[] { (byte)'=' };
3334
private static ReadOnlySpan<byte> UTF8AndEncoded => new byte[] { (byte)'&' };
3435

src/Middleware/WebSockets/src/HandshakeHelpers.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ internal static class HandshakeHelpers
2424
};
2525

2626
// "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
27-
private static ReadOnlySpan<byte> _encodedWebSocketKey => new byte[]
27+
// 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
28+
private static ReadOnlySpan<byte> EncodedWebSocketKey => new byte[]
2829
{
2930
(byte)'2', (byte)'5', (byte)'8', (byte)'E', (byte)'A', (byte)'F', (byte)'A', (byte)'5', (byte)'-',
3031
(byte)'E', (byte)'9', (byte)'1', (byte)'4', (byte)'-', (byte)'4', (byte)'7', (byte)'D', (byte)'A',
@@ -115,7 +116,7 @@ public static string CreateResponseKey(string requestKey)
115116
// so this can be hardcoded to 60 bytes for the requestKey + static websocket string
116117
Span<byte> mergedBytes = stackalloc byte[60];
117118
Encoding.UTF8.GetBytes(requestKey, mergedBytes);
118-
_encodedWebSocketKey.CopyTo(mergedBytes.Slice(24));
119+
EncodedWebSocketKey.CopyTo(mergedBytes.Slice(24));
119120

120121
Span<byte> hashedBytes = stackalloc byte[20];
121122
var success = algorithm.TryComputeHash(mergedBytes, hashedBytes, out var written);

src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
using System.IO.Pipelines;
77
using System.Text;
88
using System.Runtime.CompilerServices;
9+
using System.Runtime.InteropServices;
910

1011
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
1112
{
1213
internal static class ChunkWriter
1314
{
14-
private static readonly byte[] _hex = Encoding.ASCII.GetBytes("0123456789abcdef");
15+
// 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
16+
private static ReadOnlySpan<byte> Hex => new byte[16] { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' };
1517

1618
public static int BeginChunkBytes(int dataCount, Span<byte> span)
1719
{
@@ -28,7 +30,7 @@ public static int BeginChunkBytes(int dataCount, Span<byte> span)
2830
count = (total >> 2) + 3;
2931

3032
var offset = 0;
31-
ref var startHex = ref _hex[0];
33+
ref var startHex = ref MemoryMarshal.GetReference(Hex);
3234

3335
for (shift = total; shift >= 0; shift -= 4)
3436
{

src/Servers/Kestrel/Core/src/Internal/Http/DateHeaderValueManager.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
1414
/// </summary>
1515
internal class DateHeaderValueManager : IHeartbeatHandler
1616
{
17-
private static readonly byte[] _datePreambleBytes = Encoding.ASCII.GetBytes("\r\nDate: ");
17+
// 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
18+
private static ReadOnlySpan<byte> DatePreambleBytes => new byte[8] { (byte)'\r', (byte)'\n', (byte)'D', (byte)'a', (byte)'t', (byte)'e', (byte)':', (byte)' ' };
1819

1920
private DateHeaderValues _dateValues;
2021

@@ -38,9 +39,9 @@ public void OnHeartbeat(DateTimeOffset now)
3839
private void SetDateValues(DateTimeOffset value)
3940
{
4041
var dateValue = HeaderUtilities.FormatDate(value);
41-
var dateBytes = new byte[_datePreambleBytes.Length + dateValue.Length];
42-
Buffer.BlockCopy(_datePreambleBytes, 0, dateBytes, 0, _datePreambleBytes.Length);
43-
Encoding.ASCII.GetBytes(dateValue, 0, dateValue.Length, dateBytes, _datePreambleBytes.Length);
42+
var dateBytes = new byte[DatePreambleBytes.Length + dateValue.Length];
43+
DatePreambleBytes.CopyTo(dateBytes);
44+
Encoding.ASCII.GetBytes(dateValue, dateBytes.AsSpan(DatePreambleBytes.Length));
4445

4546
var dateValues = new DateHeaderValues
4647
{

src/Servers/Kestrel/Core/src/Internal/Http/HttpResponseHeaders.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
1414
{
1515
internal sealed partial class HttpResponseHeaders : HttpHeaders
1616
{
17+
// 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
1718
private static ReadOnlySpan<byte> CrLf => new[] { (byte)'\r', (byte)'\n' };
1819
private static ReadOnlySpan<byte> ColonSpace => new[] { (byte)':', (byte)' ' };
1920

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
7+
{
8+
internal partial class Http2Connection
9+
{
10+
// 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
11+
12+
private static ReadOnlySpan<byte> ClientPrefaceBytes => new byte[24] { (byte)'P', (byte)'R', (byte)'I', (byte)' ', (byte)'*', (byte)' ', (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'2', (byte)'.', (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n', (byte)'S', (byte)'M', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' };
13+
private static ReadOnlySpan<byte> AuthorityBytes => new byte[10] { (byte)':', (byte)'a', (byte)'u', (byte)'t', (byte)'h', (byte)'o', (byte)'r', (byte)'i', (byte)'t', (byte)'y' };
14+
private static ReadOnlySpan<byte> MethodBytes => new byte[7] { (byte)':', (byte)'m', (byte)'e', (byte)'t', (byte)'h', (byte)'o', (byte)'d' };
15+
private static ReadOnlySpan<byte> PathBytes => new byte[5] { (byte)':', (byte)'p', (byte)'a', (byte)'t', (byte)'h' };
16+
private static ReadOnlySpan<byte> SchemeBytes => new byte[7] { (byte)':', (byte)'s', (byte)'c', (byte)'h', (byte)'e', (byte)'m', (byte)'e' };
17+
private static ReadOnlySpan<byte> StatusBytes => new byte[7] { (byte)':', (byte)'s', (byte)'t', (byte)'a', (byte)'t', (byte)'u', (byte)'s' };
18+
private static ReadOnlySpan<byte> ConnectionBytes => new byte[10] { (byte)'c', (byte)'o', (byte)'n', (byte)'n', (byte)'e', (byte)'c', (byte)'t', (byte)'i', (byte)'o', (byte)'n' };
19+
private static ReadOnlySpan<byte> TeBytes => new byte[2] { (byte)'t', (byte)'e' };
20+
private static ReadOnlySpan<byte> TrailersBytes => new byte[8] { (byte)'t', (byte)'r', (byte)'a', (byte)'i', (byte)'l', (byte)'e', (byte)'r', (byte)'s' };
21+
private static ReadOnlySpan<byte> ConnectBytes => new byte[7] { (byte)'C', (byte)'O', (byte)'N', (byte)'N', (byte)'E', (byte)'C', (byte)'T' };
22+
}
23+
}

src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,13 @@
2727

2828
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
2929
{
30-
internal class Http2Connection : IHttp2StreamLifetimeHandler, IHttpHeadersHandler, IRequestProcessor
30+
internal partial class Http2Connection : IHttp2StreamLifetimeHandler, IHttpHeadersHandler, IRequestProcessor
3131
{
32-
public static byte[] ClientPreface { get; } = Encoding.ASCII.GetBytes("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
32+
public static ReadOnlySpan<byte> ClientPreface => ClientPrefaceBytes;
3333

3434
private static readonly PseudoHeaderFields _mandatoryRequestPseudoHeaderFields =
3535
PseudoHeaderFields.Method | PseudoHeaderFields.Path | PseudoHeaderFields.Scheme;
3636

37-
private static readonly byte[] _authorityBytes = Encoding.ASCII.GetBytes(HeaderNames.Authority);
38-
private static readonly byte[] _methodBytes = Encoding.ASCII.GetBytes(HeaderNames.Method);
39-
private static readonly byte[] _pathBytes = Encoding.ASCII.GetBytes(HeaderNames.Path);
40-
private static readonly byte[] _schemeBytes = Encoding.ASCII.GetBytes(HeaderNames.Scheme);
41-
private static readonly byte[] _statusBytes = Encoding.ASCII.GetBytes(HeaderNames.Status);
42-
private static readonly byte[] _connectionBytes = Encoding.ASCII.GetBytes("connection");
43-
private static readonly byte[] _teBytes = Encoding.ASCII.GetBytes("te");
44-
private static readonly byte[] _trailersBytes = Encoding.ASCII.GetBytes("trailers");
45-
private static readonly byte[] _connectBytes = Encoding.ASCII.GetBytes("CONNECT");
46-
4737
private readonly HttpConnectionContext _context;
4838
private readonly Http2FrameWriter _frameWriter;
4939
private readonly Pipe _input;
@@ -1175,7 +1165,7 @@ implementations to these vulnerabilities.*/
11751165

11761166
if (headerField == PseudoHeaderFields.Method)
11771167
{
1178-
_isMethodConnect = value.SequenceEqual(_connectBytes);
1168+
_isMethodConnect = value.SequenceEqual(ConnectBytes);
11791169
}
11801170

11811171
_parsedPseudoHeaderFields |= headerField;
@@ -1217,23 +1207,23 @@ private bool IsPseudoHeaderField(ReadOnlySpan<byte> name, out PseudoHeaderFields
12171207
return false;
12181208
}
12191209

1220-
if (name.SequenceEqual(_pathBytes))
1210+
if (name.SequenceEqual(PathBytes))
12211211
{
12221212
headerField = PseudoHeaderFields.Path;
12231213
}
1224-
else if (name.SequenceEqual(_methodBytes))
1214+
else if (name.SequenceEqual(MethodBytes))
12251215
{
12261216
headerField = PseudoHeaderFields.Method;
12271217
}
1228-
else if (name.SequenceEqual(_schemeBytes))
1218+
else if (name.SequenceEqual(SchemeBytes))
12291219
{
12301220
headerField = PseudoHeaderFields.Scheme;
12311221
}
1232-
else if (name.SequenceEqual(_statusBytes))
1222+
else if (name.SequenceEqual(StatusBytes))
12331223
{
12341224
headerField = PseudoHeaderFields.Status;
12351225
}
1236-
else if (name.SequenceEqual(_authorityBytes))
1226+
else if (name.SequenceEqual(AuthorityBytes))
12371227
{
12381228
headerField = PseudoHeaderFields.Authority;
12391229
}
@@ -1247,7 +1237,7 @@ private bool IsPseudoHeaderField(ReadOnlySpan<byte> name, out PseudoHeaderFields
12471237

12481238
private static bool IsConnectionSpecificHeaderField(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
12491239
{
1250-
return name.SequenceEqual(_connectionBytes) || (name.SequenceEqual(_teBytes) && !value.SequenceEqual(_trailersBytes));
1240+
return name.SequenceEqual(ConnectionBytes) || (name.SequenceEqual(TeBytes) && !value.SequenceEqual(TrailersBytes));
12511241
}
12521242

12531243
private bool TryClose()

src/Servers/Kestrel/Core/src/Internal/Http2/Http2FrameWriter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
2222
internal class Http2FrameWriter
2323
{
2424
// Literal Header Field without Indexing - Indexed Name (Index 8 - :status)
25+
// 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
2526
private static ReadOnlySpan<byte> ContinueBytes => new byte[] { 0x08, 0x03, (byte)'1', (byte)'0', (byte)'0' };
2627

2728
private readonly object _writeLock = new object();

src/Servers/Kestrel/Kestrel/test/GeneratedCodeTests.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,46 @@ public class GeneratedCodeTests
1616
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2223", FlakyOn.Helix.All)]
1717
public void GeneratedCodeIsUpToDate()
1818
{
19-
var httpHeadersGeneratedPath = Path.Combine(AppContext.BaseDirectory,"shared", "GeneratedContent", "HttpHeaders.Generated.cs");
20-
var httpProtocolGeneratedPath = Path.Combine(AppContext.BaseDirectory,"shared", "GeneratedContent", "HttpProtocol.Generated.cs");
21-
var httpUtilitiesGeneratedPath = Path.Combine(AppContext.BaseDirectory,"shared", "GeneratedContent", "HttpUtilities.Generated.cs");
22-
var transportConnectionGeneratedPath = Path.Combine(AppContext.BaseDirectory,"shared", "GeneratedContent", "TransportConnection.Generated.cs");
19+
var httpHeadersGeneratedPath = Path.Combine(AppContext.BaseDirectory, "shared", "GeneratedContent", "HttpHeaders.Generated.cs");
20+
var httpProtocolGeneratedPath = Path.Combine(AppContext.BaseDirectory, "shared", "GeneratedContent", "HttpProtocol.Generated.cs");
21+
var httpUtilitiesGeneratedPath = Path.Combine(AppContext.BaseDirectory, "shared", "GeneratedContent", "HttpUtilities.Generated.cs");
22+
var http2ConnectionGeneratedPath = Path.Combine(AppContext.BaseDirectory, "shared", "GeneratedContent", "Http2Connection.Generated.cs");
23+
var transportConnectionGeneratedPath = Path.Combine(AppContext.BaseDirectory, "shared", "GeneratedContent", "TransportConnection.Generated.cs");
2324

2425
var testHttpHeadersGeneratedPath = Path.GetTempFileName();
2526
var testHttpProtocolGeneratedPath = Path.GetTempFileName();
2627
var testHttpUtilitiesGeneratedPath = Path.GetTempFileName();
28+
var testHttp2ConnectionGeneratedPath = Path.GetTempFileName();
2729
var testTransportConnectionGeneratedPath = Path.GetTempFileName();
2830

2931
try
3032
{
3133
var currentHttpHeadersGenerated = File.ReadAllText(httpHeadersGeneratedPath);
3234
var currentHttpProtocolGenerated = File.ReadAllText(httpProtocolGeneratedPath);
3335
var currentHttpUtilitiesGenerated = File.ReadAllText(httpUtilitiesGeneratedPath);
36+
var currentHttp2ConnectionGenerated = File.ReadAllText(http2ConnectionGeneratedPath);
3437
var currentTransportConnectionGenerated = File.ReadAllText(transportConnectionGeneratedPath);
3538

36-
CodeGenerator.Program.Run(testHttpHeadersGeneratedPath, testHttpProtocolGeneratedPath, testHttpUtilitiesGeneratedPath, testTransportConnectionGeneratedPath);
39+
CodeGenerator.Program.Run(testHttpHeadersGeneratedPath, testHttpProtocolGeneratedPath, testHttpUtilitiesGeneratedPath, testTransportConnectionGeneratedPath, testHttp2ConnectionGeneratedPath);
3740

3841
var testHttpHeadersGenerated = File.ReadAllText(testHttpHeadersGeneratedPath);
3942
var testHttpProtocolGenerated = File.ReadAllText(testHttpProtocolGeneratedPath);
4043
var testHttpUtilitiesGenerated = File.ReadAllText(testHttpUtilitiesGeneratedPath);
44+
var testHttp2ConnectionGenerated = File.ReadAllText(testHttp2ConnectionGeneratedPath);
4145
var testTransportConnectionGenerated = File.ReadAllText(testTransportConnectionGeneratedPath);
4246

4347
Assert.Equal(currentHttpHeadersGenerated, testHttpHeadersGenerated, ignoreLineEndingDifferences: true);
4448
Assert.Equal(currentHttpProtocolGenerated, testHttpProtocolGenerated, ignoreLineEndingDifferences: true);
4549
Assert.Equal(currentHttpUtilitiesGenerated, testHttpUtilitiesGenerated, ignoreLineEndingDifferences: true);
50+
Assert.Equal(currentHttp2ConnectionGenerated, testHttp2ConnectionGenerated, ignoreLineEndingDifferences: true);
4651
Assert.Equal(currentTransportConnectionGenerated, testTransportConnectionGenerated, ignoreLineEndingDifferences: true);
47-
4852
}
4953
finally
5054
{
5155
File.Delete(testHttpHeadersGeneratedPath);
5256
File.Delete(testHttpProtocolGeneratedPath);
5357
File.Delete(testHttpUtilitiesGeneratedPath);
58+
File.Delete(testHttp2ConnectionGeneratedPath);
5459
File.Delete(testTransportConnectionGeneratedPath);
5560
}
5661
}

src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<Content Include="$(KestrelRoot)Core\src\Internal\Http\HttpHeaders.Generated.cs" LinkBase="shared\GeneratedContent" CopyToOutputDirectory="PreserveNewest" />
1313
<Content Include="$(KestrelRoot)Core\src\Internal\Http\HttpProtocol.Generated.cs" LinkBase="shared\GeneratedContent" CopyToOutputDirectory="PreserveNewest" />
1414
<Content Include="$(KestrelRoot)Core\src\Internal\Infrastructure\HttpUtilities.Generated.cs" LinkBase="shared\GeneratedContent" CopyToOutputDirectory="PreserveNewest" />
15+
<Content Include="$(KestrelRoot)Core\src\Internal\Http2\Http2Connection.Generated.cs" LinkBase="shared\GeneratedContent" CopyToOutputDirectory="PreserveNewest" />
1516
<Content Include="$(KestrelSharedSourceRoot)\TransportConnection.Generated.cs" LinkBase="shared\GeneratedContent" CopyToOutputDirectory="PreserveNewest" />
1617
</ItemGroup>
1718

src/Servers/Kestrel/samples/http2cat/Http2Utilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ public static async Task FlushAsync(PipeWriter writableBuffer)
340340
await writableBuffer.FlushAsync().AsTask().DefaultTimeout();
341341
}
342342

343-
public Task SendPreambleAsync() => SendAsync(new ArraySegment<byte>(Http2Connection.ClientPreface));
343+
public Task SendPreambleAsync() => SendAsync(Http2Connection.ClientPreface);
344344

345345
public async Task SendSettingsAsync()
346346
{

src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TestBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ protected static async Task FlushAsync(PipeWriter writableBuffer)
688688
await writableBuffer.FlushAsync().AsTask().DefaultTimeout();
689689
}
690690

691-
protected Task SendPreambleAsync() => SendAsync(new ArraySegment<byte>(Http2Connection.ClientPreface));
691+
protected Task SendPreambleAsync() => SendAsync(Http2Connection.ClientPreface);
692692

693693
protected async Task SendSettingsAsync()
694694
{

src/Servers/Kestrel/tools/CodeGenerator/CodeGenerator.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
@@ -18,7 +18,7 @@
1818

1919
<PropertyGroup>
2020
<StartWorkingDirectory>$(MSBuildThisFileDirectory)..\..\</StartWorkingDirectory>
21-
<StartArguments>Core/src/Internal/Http/HttpHeaders.Generated.cs Core/src/Internal/Http/HttpProtocol.Generated.cs Core/src/Internal/Infrastructure/HttpUtilities.Generated.cs shared/TransportConnection.Generated.cs</StartArguments>
21+
<StartArguments>Core/src/Internal/Http/HttpHeaders.Generated.cs Core/src/Internal/Http/HttpProtocol.Generated.cs Core/src/Internal/Infrastructure/HttpUtilities.Generated.cs shared/TransportConnection.Generated.cs Core/src/Internal/Http2/Http2Connection.Generated.cs</StartArguments>
2222
</PropertyGroup>
2323

2424
</Project>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using Microsoft.Net.Http.Headers;
6+
7+
namespace CodeGenerator
8+
{
9+
public static class Http2Connection
10+
{
11+
public static string GenerateFile()
12+
{
13+
return ReadOnlySpanStaticDataGenerator.GenerateFile(
14+
namespaceName: "Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2",
15+
className: "Http2Connection",
16+
allProperties: GetStrings());
17+
}
18+
19+
private static IEnumerable<(string Name, string Value)> GetStrings()
20+
{
21+
yield return ("ClientPreface", "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
22+
yield return ("Authority", HeaderNames.Authority);
23+
yield return ("Method", HeaderNames.Method);
24+
yield return ("Path", HeaderNames.Path);
25+
yield return ("Scheme", HeaderNames.Scheme);
26+
yield return ("Status", HeaderNames.Status);
27+
yield return ("Connection", "connection");
28+
yield return ("Te", "te");
29+
yield return ("Trailers", "trailers");
30+
yield return ("Connect", "CONNECT");
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)