-
Notifications
You must be signed in to change notification settings - Fork 191
HeaderUtilities enhancements #738
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -98,7 +98,7 @@ public int? Port | |
{ | ||
return null; | ||
} | ||
|
||
return p; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,18 +11,18 @@ namespace Microsoft.Net.Http.Headers | |
{ | ||
public class CacheControlHeaderValue | ||
{ | ||
private const string MaxAgeString = "max-age"; | ||
private const string MaxStaleString = "max-stale"; | ||
private const string MinFreshString = "min-fresh"; | ||
private const string MustRevalidateString = "must-revalidate"; | ||
private const string NoCacheString = "no-cache"; | ||
private const string NoStoreString = "no-store"; | ||
private const string NoTransformString = "no-transform"; | ||
private const string OnlyIfCachedString = "only-if-cached"; | ||
private const string PrivateString = "private"; | ||
private const string ProxyRevalidateString = "proxy-revalidate"; | ||
private const string PublicString = "public"; | ||
private const string SharedMaxAgeString = "s-maxage"; | ||
public static readonly string PublicString = "public"; | ||
public static readonly string PrivateString = "private"; | ||
public static readonly string MaxAgeString = "max-age"; | ||
public static readonly string SharedMaxAgeString = "s-maxage"; | ||
public static readonly string NoCacheString = "no-cache"; | ||
public static readonly string NoStoreString = "no-store"; | ||
public static readonly string MaxStaleString = "max-stale"; | ||
public static readonly string MinFreshString = "min-fresh"; | ||
public static readonly string NoTransformString = "no-transform"; | ||
public static readonly string OnlyIfCachedString = "only-if-cached"; | ||
public static readonly string MustRevalidateString = "must-revalidate"; | ||
public static readonly string ProxyRevalidateString = "proxy-revalidate"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have we learned nothing from #712!? I actually prefer const as you can see if you read the PR comments, but we should be consistent and use static readonly instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently we were using these values in a switch statement and they need to be const for that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if David will be OK with this because of the switch statement. Like I said, I'm fine with consts given we don't mess up the values, but I would like consistency. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Modified the switch statement. These strings are now public static readonly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👎 This regressed the code readability and maintainability. These constants aren't worth it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also avoiding a ToLower() which is required since switch on strings are case-sensitive. I'm seeing a one percent performance increase in ResponseCaching with it. Also it's code within a private method, so I'm not too concerned about its readability. |
||
|
||
// The Cache-Control header is special: It is a header supporting a list of values, but we represent the list | ||
// as _one_ instance of CacheControlHeaderValue. I.e we set 'SupportsMultipleValues' to 'true' since it is | ||
|
@@ -394,63 +394,120 @@ private static bool TrySetCacheControlValues( | |
CacheControlHeaderValue cc, | ||
List<NameValueHeaderValue> nameValueList) | ||
{ | ||
foreach (NameValueHeaderValue nameValue in nameValueList) | ||
for (var i = 0; i < nameValueList.Count; i++) | ||
{ | ||
var nameValue = nameValueList[i]; | ||
var name = nameValue.Name; | ||
var success = true; | ||
string name = nameValue.Name.ToLowerInvariant(); | ||
|
||
switch (name) | ||
switch (name.Length) | ||
{ | ||
case NoCacheString: | ||
success = TrySetOptionalTokenList(nameValue, ref cc._noCache, ref cc._noCacheHeaders); | ||
break; | ||
|
||
case NoStoreString: | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._noStore); | ||
break; | ||
|
||
case MaxAgeString: | ||
success = TrySetTimeSpan(nameValue, ref cc._maxAge); | ||
break; | ||
|
||
case MaxStaleString: | ||
success = ((nameValue.Value == null) || TrySetTimeSpan(nameValue, ref cc._maxStaleLimit)); | ||
if (success) | ||
case 6: | ||
if (string.Equals(PublicString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
cc._maxStale = true; | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._public); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
case MinFreshString: | ||
success = TrySetTimeSpan(nameValue, ref cc._minFresh); | ||
break; | ||
|
||
case NoTransformString: | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._noTransform); | ||
case 7: | ||
if (string.Equals(MaxAgeString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTimeSpan(nameValue, ref cc._maxAge); | ||
} | ||
else if(string.Equals(PrivateString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetOptionalTokenList(nameValue, ref cc._private, ref cc._privateHeaders); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
case OnlyIfCachedString: | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._onlyIfCached); | ||
case 8: | ||
if (string.Equals(NoCacheString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetOptionalTokenList(nameValue, ref cc._noCache, ref cc._noCacheHeaders); | ||
} | ||
else if (string.Equals(NoStoreString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._noStore); | ||
} | ||
else if (string.Equals(SharedMaxAgeString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTimeSpan(nameValue, ref cc._sharedMaxAge); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
case PublicString: | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._public); | ||
case 9: | ||
if (string.Equals(MaxStaleString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = ((nameValue.Value == null) || TrySetTimeSpan(nameValue, ref cc._maxStaleLimit)); | ||
if (success) | ||
{ | ||
cc._maxStale = true; | ||
} | ||
} | ||
else if (string.Equals(MinFreshString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTimeSpan(nameValue, ref cc._minFresh); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
case PrivateString: | ||
success = TrySetOptionalTokenList(nameValue, ref cc._private, ref cc._privateHeaders); | ||
case 12: | ||
if (string.Equals(NoTransformString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._noTransform); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
case MustRevalidateString: | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._mustRevalidate); | ||
case 14: | ||
if (string.Equals(OnlyIfCachedString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._onlyIfCached); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
case ProxyRevalidateString: | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._proxyRevalidate); | ||
case 15: | ||
if (string.Equals(MustRevalidateString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._mustRevalidate); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
case SharedMaxAgeString: | ||
success = TrySetTimeSpan(nameValue, ref cc._sharedMaxAge); | ||
case 16: | ||
if (string.Equals(ProxyRevalidateString, name, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
success = TrySetTokenOnlyValue(nameValue, ref cc._proxyRevalidate); | ||
} | ||
else | ||
{ | ||
goto default; | ||
} | ||
break; | ||
|
||
default: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do SetContentLength while we're at it, but I don't know if we have any optimized code for this yet. Kestrel has one but it's for hex.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modified the
FormatInt64
implementation.As a reference, formatting
long num = 1234567890;
to"1234567890"
for 30000000 iterations:Old: 2027ms using
num.ToString(CultureInfo.InvariantCulture)
New: 1023ms using
FormatInt64(num)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/cc @KrzysztofCwalina