Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit bc7e27f

Browse files
committed
Rework HeaderUtilities.Contains
1 parent 644ae1f commit bc7e27f

File tree

2 files changed

+79
-8
lines changed

2 files changed

+79
-8
lines changed

src/Microsoft.Net.Http.Headers/HeaderUtilities.cs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ internal static int GetNextNonEmptyOrWhitespaceIndex(
220220
/// <code>false</code>.
221221
/// </returns>
222222
// e.g. { "headerValue=10, targetHeaderValue=30" }
223-
public static bool TryParseTimeSpan(StringValues headerValues, string targetValue, out TimeSpan? value)
223+
public static bool TryParseSeconds(StringValues headerValues, string targetValue, out TimeSpan? value)
224224
{
225225
for (var i = 0; i < headerValues.Count; i++)
226226
{
@@ -258,12 +258,49 @@ public static bool TryParseTimeSpan(StringValues headerValues, string targetValu
258258
/// </returns>
259259
public static bool Contains(StringValues headerValues, string targetValue)
260260
{
261+
if (StringValues.IsNullOrEmpty(headerValues) || string.IsNullOrEmpty(targetValue))
262+
{
263+
return false;
264+
}
265+
266+
261267
for (var i = 0; i < headerValues.Count; i++)
262268
{
263-
var index = headerValues[i].IndexOf(targetValue, StringComparison.OrdinalIgnoreCase);
264-
if (index != -1)
269+
var current = 0;
270+
271+
// Trim leading white space
272+
current += HttpRuleParser.GetWhitespaceLength(headerValues[i], current);
273+
274+
while (current < headerValues[i].Length)
265275
{
266-
return true;
276+
var tokenLength = HttpRuleParser.GetTokenLength(headerValues[i], current);
277+
if (tokenLength == targetValue.Length
278+
&& string.Compare(headerValues[i], current, targetValue, 0, tokenLength, StringComparison.OrdinalIgnoreCase) == 0)
279+
{
280+
// Token matches target value
281+
return true;
282+
}
283+
else
284+
{
285+
// Skip until the next potential name
286+
current += tokenLength;
287+
current += HttpRuleParser.GetWhitespaceLength(headerValues[i], current);
288+
289+
// Skip the value if present
290+
if (current < headerValues[i].Length && headerValues[i][current] == '=')
291+
{
292+
current++; // skip '='
293+
current += NameValueHeaderValue.GetValueLength(headerValues[i], current);
294+
current += HttpRuleParser.GetWhitespaceLength(headerValues[i], current);
295+
}
296+
297+
// Skip the delimiter
298+
if (current < headerValues[i].Length && headerValues[i][current] == ',')
299+
{
300+
current++; // skip ','
301+
current += HttpRuleParser.GetWhitespaceLength(headerValues[i], current);
302+
}
303+
}
267304
}
268305
}
269306

test/Microsoft.Net.Http.Headers.Tests/HeaderUtilitiesTest.cs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ public static TheoryData<DateTimeOffset, bool> TestValues
5252
[InlineData("header1 =45, header2=80", "header1", 45)]
5353
[InlineData("header1= 89 , header2=22", "header1", 89)]
5454
[InlineData("header1= 89 , header2= 42", "header2", 42)]
55-
public void TryParseTimeSpan_Succeeds(string headerValues, string targetValue, int expectedValue)
55+
public void TryParseSeconds_Succeeds(string headerValues, string targetValue, int expectedValue)
5656
{
5757
TimeSpan? value;
58-
Assert.True(HeaderUtilities.TryParseTimeSpan(new StringValues(headerValues), targetValue, out value));
58+
Assert.True(HeaderUtilities.TryParseSeconds(new StringValues(headerValues), targetValue, out value));
5959
Assert.Equal(TimeSpan.FromSeconds(expectedValue), value);
6060
}
6161

@@ -66,10 +66,44 @@ public void TryParseTimeSpan_Succeeds(string headerValues, string targetValue, i
6666
[InlineData("h=10", "header")]
6767
[InlineData("", "")]
6868
[InlineData(null, null)]
69-
public void TryParseTimeSpan_Fails(string headerValues, string targetValue)
69+
public void TryParseSeconds_Fails(string headerValues, string targetValue)
7070
{
7171
TimeSpan? value;
72-
Assert.False(HeaderUtilities.TryParseTimeSpan(new StringValues(headerValues), targetValue, out value));
72+
Assert.False(HeaderUtilities.TryParseSeconds(new StringValues(headerValues), targetValue, out value));
73+
}
74+
75+
[Theory]
76+
[InlineData("h", "h", true)]
77+
[InlineData("h=", "h", true)]
78+
[InlineData("h=1", "h", true)]
79+
[InlineData("H", "h", true)]
80+
[InlineData("H=", "h", true)]
81+
[InlineData("H=1", "h", true)]
82+
[InlineData("h", "H", true)]
83+
[InlineData("h=", "H", true)]
84+
[InlineData("h=1", "H", true)]
85+
[InlineData("header1, header=10", "header1", true)]
86+
[InlineData("header1=, header=10", "header1", true)]
87+
[InlineData("header1=3, header=10", "header1", true)]
88+
[InlineData("header1 , header=80", "header1", true)]
89+
[InlineData("header1 =45, header=80", "header1", true)]
90+
[InlineData("header1= 89 , header=22", "header1", true)]
91+
[InlineData("header1=3, header", "header", true)]
92+
[InlineData("header1=3, header=", "header", true)]
93+
[InlineData("header1=3, header=10", "header", true)]
94+
[InlineData("header1= 89 , header= 42", "header", true)]
95+
[InlineData("header1= 89 , header = 42", "header", true)]
96+
[InlineData(null, null, false)]
97+
[InlineData(null, "", false)]
98+
[InlineData("", null, false)]
99+
[InlineData("", "", false)]
100+
[InlineData("h=10", "header", false)]
101+
[InlineData("header1", "header", false)]
102+
[InlineData("h=header", "header", false)]
103+
[InlineData("header1, header2=80", "header", false)]
104+
public void Contains_MatchesExactValue(string headerValues, string targetValue, bool contains)
105+
{
106+
Assert.Equal(contains, HeaderUtilities.Contains(new StringValues(headerValues), targetValue));
73107
}
74108

75109
[Theory]

0 commit comments

Comments
 (0)