Skip to content

Commit 1f6fc66

Browse files
authored
Reduce the size of some Http header values (#83640)
* Reduce the size of some Http header values * PR feedback
1 parent 850a320 commit 1f6fc66

8 files changed

+292
-508
lines changed

src/libraries/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderValue.cs

Lines changed: 163 additions & 197 deletions
Large diffs are not rendered by default.

src/libraries/System.Net.Http/src/System/Net/Http/Headers/ContentRangeHeaderValue.cs

Lines changed: 27 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@
33

44
using System.Diagnostics;
55
using System.Diagnostics.CodeAnalysis;
6-
using System.Globalization;
7-
using System.IO;
86
using System.Text;
97

108
namespace System.Net.Http.Headers
119
{
1210
public class ContentRangeHeaderValue : ICloneable
1311
{
1412
private string _unit = null!;
15-
private long? _from;
16-
private long? _to;
17-
private long? _length;
13+
private long _from;
14+
private long _to;
15+
private long _length;
1816

1917
public string Unit
2018
{
@@ -26,30 +24,15 @@ public string Unit
2624
}
2725
}
2826

29-
public long? From
30-
{
31-
get { return _from; }
32-
}
27+
public long? From => HasRange ? _from : null;
3328

34-
public long? To
35-
{
36-
get { return _to; }
37-
}
29+
public long? To => HasRange ? _to : null;
3830

39-
public long? Length
40-
{
41-
get { return _length; }
42-
}
31+
public long? Length => HasLength ? _length : null;
4332

44-
public bool HasLength // e.g. "Content-Range: bytes 12-34/*"
45-
{
46-
get { return _length != null; }
47-
}
33+
public bool HasLength => _length >= 0; // e.g. "Content-Range: bytes 12-34/*"
4834

49-
public bool HasRange // e.g. "Content-Range: bytes */1234"
50-
{
51-
get { return _from != null; }
52-
}
35+
public bool HasRange => _from >= 0; // e.g. "Content-Range: bytes */1234"
5336

5437
public ContentRangeHeaderValue(long from, long to, long length)
5538
{
@@ -75,6 +58,7 @@ public ContentRangeHeaderValue(long length)
7558

7659
_length = length;
7760
_unit = HeaderUtilities.BytesUnit;
61+
_from = -1;
7862
}
7963

8064
public ContentRangeHeaderValue(long from, long to)
@@ -88,10 +72,13 @@ public ContentRangeHeaderValue(long from, long to)
8872
_from = from;
8973
_to = to;
9074
_unit = HeaderUtilities.BytesUnit;
75+
_length = -1;
9176
}
9277

9378
private ContentRangeHeaderValue()
9479
{
80+
_from = -1;
81+
_length = -1;
9582
}
9683

9784
private ContentRangeHeaderValue(ContentRangeHeaderValue source)
@@ -104,35 +91,19 @@ private ContentRangeHeaderValue(ContentRangeHeaderValue source)
10491
_unit = source._unit;
10592
}
10693

107-
public override bool Equals([NotNullWhen(true)] object? obj)
108-
{
109-
ContentRangeHeaderValue? other = obj as ContentRangeHeaderValue;
110-
111-
if (other == null)
112-
{
113-
return false;
114-
}
115-
116-
return ((_from == other._from) && (_to == other._to) && (_length == other._length) &&
117-
string.Equals(_unit, other._unit, StringComparison.OrdinalIgnoreCase));
118-
}
119-
120-
public override int GetHashCode()
121-
{
122-
int result = StringComparer.OrdinalIgnoreCase.GetHashCode(_unit);
123-
124-
if (HasRange)
125-
{
126-
result = result ^ _from.GetHashCode() ^ _to.GetHashCode();
127-
}
128-
129-
if (HasLength)
130-
{
131-
result ^= _length.GetHashCode();
132-
}
94+
public override bool Equals([NotNullWhen(true)] object? obj) =>
95+
obj is ContentRangeHeaderValue other &&
96+
_from == other._from &&
97+
_to == other._to &&
98+
_length == other._length &&
99+
string.Equals(_unit, other._unit, StringComparison.OrdinalIgnoreCase);
133100

134-
return result;
135-
}
101+
public override int GetHashCode() =>
102+
HashCode.Combine(
103+
StringComparer.OrdinalIgnoreCase.GetHashCode(_unit),
104+
_from,
105+
_to,
106+
_length);
136107

137108
public override string ToString()
138109
{
@@ -142,10 +113,9 @@ public override string ToString()
142113

143114
if (HasRange)
144115
{
145-
sb.AppendSpanFormattable(_from!.Value);
116+
sb.AppendSpanFormattable(_from);
146117
sb.Append('-');
147-
Debug.Assert(_to.HasValue);
148-
sb.AppendSpanFormattable(_to.Value);
118+
sb.AppendSpanFormattable(_to);
149119
}
150120
else
151121
{
@@ -155,7 +125,7 @@ public override string ToString()
155125
sb.Append('/');
156126
if (HasLength)
157127
{
158-
sb.AppendSpanFormattable(_length!.Value);
128+
sb.AppendSpanFormattable(_length);
159129
}
160130
else
161131
{

src/libraries/System.Net.Http/src/System/Net/Http/Headers/RangeConditionHeaderValue.cs

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,13 @@ namespace System.Net.Http.Headers
88
{
99
public class RangeConditionHeaderValue : ICloneable
1010
{
11-
private readonly DateTimeOffset? _date;
11+
// Exactly one of date and entityTag will be set.
12+
private readonly DateTimeOffset _date;
1213
private readonly EntityTagHeaderValue? _entityTag;
1314

14-
public DateTimeOffset? Date
15-
{
16-
get { return _date; }
17-
}
15+
public DateTimeOffset? Date => _entityTag is null ? _date : null;
1816

19-
public EntityTagHeaderValue? EntityTag
20-
{
21-
get { return _entityTag; }
22-
}
17+
public EntityTagHeaderValue? EntityTag => _entityTag;
2318

2419
public RangeConditionHeaderValue(DateTimeOffset date)
2520
{
@@ -46,45 +41,14 @@ private RangeConditionHeaderValue(RangeConditionHeaderValue source)
4641
_date = source._date;
4742
}
4843

49-
public override string ToString()
50-
{
51-
if (_entityTag == null)
52-
{
53-
Debug.Assert(_date != null);
54-
return _date.GetValueOrDefault().ToString("r");
55-
}
56-
57-
return _entityTag.ToString();
58-
}
44+
public override string ToString() => _entityTag?.ToString() ?? _date.ToString("r");
5945

60-
public override bool Equals([NotNullWhen(true)] object? obj)
61-
{
62-
RangeConditionHeaderValue? other = obj as RangeConditionHeaderValue;
46+
public override bool Equals([NotNullWhen(true)] object? obj) =>
47+
obj is RangeConditionHeaderValue other &&
48+
(_entityTag is null ? other._entityTag is null : _entityTag.Equals(other._entityTag)) &&
49+
_date == other._date;
6350

64-
if (other == null)
65-
{
66-
return false;
67-
}
68-
69-
if (_entityTag == null)
70-
{
71-
Debug.Assert(_date != null);
72-
return (other._date != null) && (_date.Value == other._date.Value);
73-
}
74-
75-
return _entityTag.Equals(other._entityTag);
76-
}
77-
78-
public override int GetHashCode()
79-
{
80-
if (_entityTag == null)
81-
{
82-
Debug.Assert(_date != null);
83-
return _date.Value.GetHashCode();
84-
}
85-
86-
return _entityTag.GetHashCode();
87-
}
51+
public override int GetHashCode() => _entityTag?.GetHashCode() ?? _date.GetHashCode();
8852

8953
public static RangeConditionHeaderValue Parse(string input)
9054
{

src/libraries/System.Net.Http/src/System/Net/Http/Headers/RangeItemHeaderValue.cs

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,13 @@ namespace System.Net.Http.Headers
1010
{
1111
public class RangeItemHeaderValue : ICloneable
1212
{
13-
private readonly long? _from;
14-
private readonly long? _to;
13+
// Set to -1 if not set.
14+
private readonly long _from;
15+
private readonly long _to;
1516

16-
public long? From
17-
{
18-
get { return _from; }
19-
}
17+
public long? From => _from >= 0 ? _from : null;
2018

21-
public long? To
22-
{
23-
get { return _to; }
24-
}
19+
public long? To => _to >= 0 ? _to : null;
2520

2621
public RangeItemHeaderValue(long? from, long? to)
2722
{
@@ -42,8 +37,8 @@ public RangeItemHeaderValue(long? from, long? to)
4237
ArgumentOutOfRangeException.ThrowIfGreaterThan(from.GetValueOrDefault(), to.GetValueOrDefault(), nameof(from));
4338
}
4439

45-
_from = from;
46-
_to = to;
40+
_from = from ?? -1;
41+
_to = to ?? -1;
4742
}
4843

4944
internal RangeItemHeaderValue(RangeItemHeaderValue source)
@@ -58,43 +53,26 @@ public override string ToString()
5853
{
5954
Span<char> stackBuffer = stackalloc char[128];
6055

61-
if (!_from.HasValue)
56+
if (_from < 0)
6257
{
63-
Debug.Assert(_to != null);
64-
return string.Create(CultureInfo.InvariantCulture, stackBuffer, $"-{_to.Value}");
58+
return string.Create(CultureInfo.InvariantCulture, stackBuffer, $"-{_to}");
6559
}
6660

67-
if (!_to.HasValue)
61+
if (_to < 0)
6862
{
69-
return string.Create(CultureInfo.InvariantCulture, stackBuffer, $"{_from.Value}-"); ;
63+
return string.Create(CultureInfo.InvariantCulture, stackBuffer, $"{_from}-"); ;
7064
}
7165

72-
return string.Create(CultureInfo.InvariantCulture, stackBuffer, $"{_from.Value}-{_to.Value}");
66+
return string.Create(CultureInfo.InvariantCulture, stackBuffer, $"{_from}-{_to}");
7367
}
7468

75-
public override bool Equals([NotNullWhen(true)] object? obj)
76-
{
77-
RangeItemHeaderValue? other = obj as RangeItemHeaderValue;
69+
public override bool Equals([NotNullWhen(true)] object? obj) =>
70+
obj is RangeItemHeaderValue other &&
71+
_from == other._from &&
72+
_to == other._to;
7873

79-
if (other == null)
80-
{
81-
return false;
82-
}
83-
return ((_from == other._from) && (_to == other._to));
84-
}
85-
86-
public override int GetHashCode()
87-
{
88-
if (!_from.HasValue)
89-
{
90-
return _to.GetHashCode();
91-
}
92-
else if (!_to.HasValue)
93-
{
94-
return _from.GetHashCode();
95-
}
96-
return _from.GetHashCode() ^ _to.GetHashCode();
97-
}
74+
public override int GetHashCode() =>
75+
HashCode.Combine(_from, _to);
9876

9977
// Returns the length of a range list. E.g. "1-2, 3-4, 5-6" adds 3 ranges to 'rangeCollection'. Note that empty
10078
// list segments are allowed, e.g. ",1-2, , 3-4,,".
@@ -118,10 +96,9 @@ internal static int GetRangeItemListLength(string? input, int startIndex,
11896
return 0;
11997
}
12098

121-
RangeItemHeaderValue? range;
12299
while (true)
123100
{
124-
int rangeLength = GetRangeItemLength(input, current, out range);
101+
int rangeLength = GetRangeItemLength(input, current, out RangeItemHeaderValue? range);
125102

126103
if (rangeLength == 0)
127104
{
@@ -227,8 +204,7 @@ internal static int GetRangeItemLength(string? input, int startIndex, out RangeI
227204
return 0;
228205
}
229206

230-
parsedValue = new RangeItemHeaderValue((fromLength == 0 ? (long?)null : (long?)from),
231-
(toLength == 0 ? (long?)null : (long?)to));
207+
parsedValue = new RangeItemHeaderValue((fromLength == 0 ? null : from), (toLength == 0 ? null : to));
232208
return current - startIndex;
233209
}
234210

0 commit comments

Comments
 (0)