Skip to content

Commit 574b2d4

Browse files
Refactor writing QPACK status (#62069)
Co-authored-by: JamesNK <JamesNK@users.noreply.github.com>
1 parent 15649df commit 574b2d4

File tree

3 files changed

+52
-48
lines changed

3 files changed

+52
-48
lines changed

src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/H2StaticTable.Http2.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ internal static partial class H2StaticTable
1111

1212
public static ref readonly HeaderField Get(int index) => ref s_staticDecoderTable[index];
1313

14-
public static int GetStatusIndex(int status) =>
15-
status switch
14+
public static bool TryGetStatusIndex(int status, out int index)
15+
{
16+
index = status switch
1617
{
1718
200 => 8,
1819
204 => 9,
@@ -21,9 +22,12 @@ public static int GetStatusIndex(int status) =>
2122
400 => 12,
2223
404 => 13,
2324
500 => 14,
24-
_ => throw new ArgumentOutOfRangeException(nameof(status))
25+
_ => -1
2526
};
2627

28+
return index != -1;
29+
}
30+
2731
private static readonly HeaderField[] s_staticDecoderTable = new HeaderField[]
2832
{
2933
CreateHeaderField(":authority", ""),

src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/HPackEncoder.cs

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,36 +44,31 @@ public static bool EncodeIndexedHeaderField(int index, Span<byte> destination, o
4444
public static bool EncodeStatusHeader(int statusCode, Span<byte> destination, out int bytesWritten)
4545
{
4646
// Bytes written depend on whether the status code value maps directly to an index
47-
switch (statusCode)
47+
if (H2StaticTable.TryGetStatusIndex(statusCode, out var index))
4848
{
49-
case 200:
50-
case 204:
51-
case 206:
52-
case 304:
53-
case 400:
54-
case 404:
55-
case 500:
56-
// Status codes which exist in the HTTP/2 StaticTable.
57-
return EncodeIndexedHeaderField(H2StaticTable.GetStatusIndex(statusCode), destination, out bytesWritten);
58-
default:
59-
// If the status code doesn't have a static index then we need to include the full value.
60-
// Write a status index and then the number bytes as a string literal.
61-
if (!EncodeLiteralHeaderFieldWithoutIndexing(H2StaticTable.Status200, destination, out var nameLength))
62-
{
63-
bytesWritten = 0;
64-
return false;
65-
}
49+
// Status codes which exist in the HTTP/2 StaticTable.
50+
return EncodeIndexedHeaderField(index, destination, out bytesWritten);
51+
}
52+
else
53+
{
54+
// If the status code doesn't have a static index then we need to include the full value.
55+
// Write a status index and then the number bytes as a string literal.
56+
if (!EncodeLiteralHeaderFieldWithoutIndexing(H2StaticTable.Status200, destination, out var nameLength))
57+
{
58+
bytesWritten = 0;
59+
return false;
60+
}
6661

67-
var statusBytes = StatusCodes.ToStatusBytes(statusCode);
62+
var statusBytes = StatusCodes.ToStatusBytes(statusCode);
6863

69-
if (!EncodeStringLiteral(statusBytes, destination.Slice(nameLength), out var valueLength))
70-
{
71-
bytesWritten = 0;
72-
return false;
73-
}
64+
if (!EncodeStringLiteral(statusBytes, destination.Slice(nameLength), out var valueLength))
65+
{
66+
bytesWritten = 0;
67+
return false;
68+
}
7469

75-
bytesWritten = nameLength + valueLength;
76-
return true;
70+
bytesWritten = nameLength + valueLength;
71+
return true;
7772
}
7873
}
7974

src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,6 @@ namespace System.Net.Http.QPack
88
{
99
internal static partial class H3StaticTable
1010
{
11-
private static readonly Dictionary<int, int> s_statusIndex = new Dictionary<int, int>
12-
{
13-
[103] = 24,
14-
[200] = 25,
15-
[304] = 26,
16-
[404] = 27,
17-
[503] = 28,
18-
[100] = 63,
19-
[204] = 64,
20-
[206] = 65,
21-
[302] = 66,
22-
[400] = 67,
23-
[403] = 68,
24-
[421] = 69,
25-
[425] = 70,
26-
[500] = 71,
27-
};
28-
2911
private static readonly Dictionary<HttpMethod, int> s_methodIndex = new Dictionary<HttpMethod, int>
3012
{
3113
// TODO connect is internal to system.net.http
@@ -37,10 +19,33 @@ internal static partial class H3StaticTable
3719
[HttpMethod.Put] = 21,
3820
};
3921

22+
public static bool TryGetStatusIndex(int status, out int index)
23+
{
24+
index = status switch
25+
{
26+
103 => 24,
27+
200 => 25,
28+
304 => 26,
29+
404 => 27,
30+
503 => 28,
31+
100 => 63,
32+
204 => 64,
33+
206 => 65,
34+
302 => 66,
35+
400 => 67,
36+
403 => 68,
37+
421 => 69,
38+
425 => 70,
39+
500 => 71,
40+
_ => -1
41+
};
42+
43+
return index != -1;
44+
}
45+
4046
public static int Count => s_staticTable.Length;
4147

4248
// TODO: just use Dictionary directly to avoid interface dispatch.
43-
public static IReadOnlyDictionary<int, int> StatusIndex => s_statusIndex;
4449
public static IReadOnlyDictionary<HttpMethod, int> MethodIndex => s_methodIndex;
4550

4651
public static HeaderField GetHeaderFieldAt(int index) => s_staticTable[index];

0 commit comments

Comments
 (0)