diff --git a/src/Microsoft.AspNet.Server.WebListener/FeatureContext.cs b/src/Microsoft.AspNet.Server.WebListener/FeatureContext.cs index 2ba8740c6f..f40812631f 100644 --- a/src/Microsoft.AspNet.Server.WebListener/FeatureContext.cs +++ b/src/Microsoft.AspNet.Server.WebListener/FeatureContext.cs @@ -26,6 +26,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Http.Features; using Microsoft.AspNet.Http.Features.Authentication; +using Microsoft.Framework.Primitives; using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Server; using Microsoft.Net.WebSockets; @@ -53,7 +54,7 @@ namespace Microsoft.AspNet.Server.WebListener private bool _enableResponseCaching; private Stream _requestBody; - private IDictionary _requestHeaders; + private IDictionary _requestHeaders; private string _scheme; private string _httpMethod; private string _httpProtocolVersion; @@ -71,7 +72,7 @@ namespace Microsoft.AspNet.Server.WebListener private IAuthenticationHandler _authHandler; private CancellationToken? _disconnectToken; private Stream _responseStream; - private IDictionary _responseHeaders; + private IDictionary _responseHeaders; internal FeatureContext(RequestContext requestContext, bool enableResponseCaching) { @@ -115,7 +116,7 @@ namespace Microsoft.AspNet.Server.WebListener set { _requestBody = value; } } - IDictionary IHttpRequestFeature.Headers + IDictionary IHttpRequestFeature.Headers { get { @@ -348,7 +349,7 @@ namespace Microsoft.AspNet.Server.WebListener set { _responseStream = value; } } - IDictionary IHttpResponseFeature.Headers + IDictionary IHttpResponseFeature.Headers { get { diff --git a/src/Microsoft.Net.Http.Server/AuthenticationManager.cs b/src/Microsoft.Net.Http.Server/AuthenticationManager.cs index 76377dd63c..321851995f 100644 --- a/src/Microsoft.Net.Http.Server/AuthenticationManager.cs +++ b/src/Microsoft.Net.Http.Server/AuthenticationManager.cs @@ -27,6 +27,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Security.Claims; using System.Security.Principal; +using Microsoft.Framework.Primitives; namespace Microsoft.Net.Http.Server { @@ -147,7 +148,8 @@ namespace Microsoft.Net.Http.Server if (challenges.Count > 0) { - context.Response.Headers.AppendValues(HttpKnownHeaderNames.WWWAuthenticate, challenges.ToArray()); + context.Response.Headers[HttpKnownHeaderNames.WWWAuthenticate] + = StringValues.Concat(context.Response.Headers[HttpKnownHeaderNames.WWWAuthenticate], challenges.ToArray()); } } diff --git a/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs b/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs index 2b2c05b6a3..c4464119a8 100644 --- a/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs +++ b/src/Microsoft.Net.Http.Server/NativeInterop/UnsafeNativeMethods.cs @@ -25,6 +25,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using Microsoft.Framework.Primitives; namespace Microsoft.Net.Http.Server { @@ -1048,7 +1049,7 @@ namespace Microsoft.Net.Http.Server // Server API - internal static void GetUnknownHeaders(IDictionary unknownHeaders, byte[] memoryBlob, IntPtr originalAddress) + internal static void GetUnknownHeaders(IDictionary unknownHeaders, byte[] memoryBlob, IntPtr originalAddress) { // Return value. fixed (byte* pMemoryBlob = memoryBlob) @@ -1079,7 +1080,7 @@ namespace Microsoft.Net.Http.Server } // Note that Http.Sys currently collapses all headers of the same name to a single coma seperated string, // so we can just call Set. - unknownHeaders[headerName] = new[] { headerValue }; + unknownHeaders[headerName] = headerValue; } pUnknownHeader++; } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderCollection.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderCollection.cs index 87ee134733..2190b3dd2f 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderCollection.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderCollection.cs @@ -4,44 +4,49 @@ using System; using System.Collections; using System.Collections.Generic; +using Microsoft.Framework.Primitives; namespace Microsoft.Net.Http.Server { - public class HeaderCollection : IDictionary + public class HeaderCollection : IDictionary { public HeaderCollection() - : this(new Dictionary(4, StringComparer.OrdinalIgnoreCase)) + : this(new Dictionary(4, StringComparer.OrdinalIgnoreCase)) { } - public HeaderCollection(IDictionary store) + public HeaderCollection(IDictionary store) { Store = store; } - private IDictionary Store { get; set; } + private IDictionary Store { get; set; } // Readonly after the response has been started. public bool IsReadOnly { get; internal set; } - public string this[string key] + public StringValues this[string key] { - get { return Get(key); } + get + { + StringValues values; + return TryGetValue(key, out values) ? values : StringValues.Empty; + } set { ThrowIfReadOnly(); - if (string.IsNullOrEmpty(value)) + if (StringValues.IsNullOrEmpty(value)) { Remove(key); } else { - Set(key, value); + Store[key] = value; } } } - string[] IDictionary.this[string key] + StringValues IDictionary.this[string key] { get { return Store[key]; } set @@ -61,18 +66,18 @@ namespace Microsoft.Net.Http.Server get { return Store.Keys; } } - public ICollection Values + public ICollection Values { get { return Store.Values; } } - public void Add(KeyValuePair item) + public void Add(KeyValuePair item) { ThrowIfReadOnly(); Store.Add(item); } - public void Add(string key, string[] value) + public void Add(string key, StringValues value) { ThrowIfReadOnly(); Store.Add(key, value); @@ -81,35 +86,9 @@ namespace Microsoft.Net.Http.Server public void Append(string key, string value) { ThrowIfReadOnly(); - string[] values; - if (Store.TryGetValue(key, out values)) - { - var newValues = new string[values.Length + 1]; - Array.Copy(values, newValues, values.Length); - newValues[values.Length] = value; - Store[key] = newValues; - } - else - { - Set(key, value); - } - } - - public void AppendValues(string key, params string[] values) - { - ThrowIfReadOnly(); - string[] oldValues; - if (Store.TryGetValue(key, out oldValues)) - { - var newValues = new string[oldValues.Length + values.Length]; - Array.Copy(oldValues, newValues, oldValues.Length); - Array.Copy(values, 0, newValues, oldValues.Length, values.Length); - Store[key] = newValues; - } - else - { - SetValues(key, values); - } + StringValues values; + Store.TryGetValue(key, out values); + Store[key] = StringValues.Concat(values, value); } public void Clear() @@ -118,7 +97,7 @@ namespace Microsoft.Net.Http.Server Store.Clear(); } - public bool Contains(KeyValuePair item) + public bool Contains(KeyValuePair item) { return Store.Contains(item); } @@ -128,29 +107,19 @@ namespace Microsoft.Net.Http.Server return Store.ContainsKey(key); } - public void CopyTo(KeyValuePair[] array, int arrayIndex) + public void CopyTo(KeyValuePair[] array, int arrayIndex) { Store.CopyTo(array, arrayIndex); } - public string Get(string key) - { - string[] values; - if (Store.TryGetValue(key, out values)) - { - return string.Join(", ", values); - } - return null; - } - - public IEnumerator> GetEnumerator() + public IEnumerator> GetEnumerator() { return Store.GetEnumerator(); } public IEnumerable GetValues(string key) { - string[] values; + StringValues values; if (Store.TryGetValue(key, out values)) { return HeaderParser.SplitValues(values); @@ -158,7 +127,7 @@ namespace Microsoft.Net.Http.Server return HeaderParser.Empty; } - public bool Remove(KeyValuePair item) + public bool Remove(KeyValuePair item) { ThrowIfReadOnly(); return Store.Remove(item); @@ -170,19 +139,7 @@ namespace Microsoft.Net.Http.Server return Store.Remove(key); } - public void Set(string key, string value) - { - ThrowIfReadOnly(); - Store[key] = new[] { value }; - } - - public void SetValues(string key, params string[] values) - { - ThrowIfReadOnly(); - Store[key] = values; - } - - public bool TryGetValue(string key, out string[] value) + public bool TryGetValue(string key, out StringValues value) { return Store.TryGetValue(key, out value); } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderParser.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderParser.cs index ebc77b8203..d4694415d6 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderParser.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/HeaderParser.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.Framework.Primitives; namespace Microsoft.Net.Http.Server { @@ -11,7 +12,7 @@ namespace Microsoft.Net.Http.Server internal static IEnumerable Empty = new string[0]; // Split on commas, except in quotes - internal static IEnumerable SplitValues(string[] values) + internal static IEnumerable SplitValues(StringValues values) { foreach (var value in values) { diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs index 146f0cf81e..2043da2957 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/Request.cs @@ -231,16 +231,16 @@ namespace Microsoft.Net.Http.Server { if (_contentBoundaryType == BoundaryType.None) { - string transferEncoding = Headers.Get(HttpKnownHeaderNames.TransferEncoding) ?? string.Empty; - if (string.Equals("chunked", transferEncoding.Trim(), StringComparison.OrdinalIgnoreCase)) + string transferEncoding = Headers[HttpKnownHeaderNames.TransferEncoding]; + if (string.Equals("chunked", transferEncoding?.Trim(), StringComparison.OrdinalIgnoreCase)) { _contentBoundaryType = BoundaryType.Chunked; } else { - string length = Headers.Get(HttpKnownHeaderNames.ContentLength) ?? string.Empty; + string length = Headers[HttpKnownHeaderNames.ContentLength]; long value; - if (long.TryParse(length.Trim(), NumberStyles.None, + if (length != null && long.TryParse(length.Trim(), NumberStyles.None, CultureInfo.InvariantCulture.NumberFormat, out value)) { _contentBoundaryType = BoundaryType.ContentLength; @@ -422,7 +422,7 @@ namespace Microsoft.Net.Http.Server { get { - return Headers.Get(HttpKnownHeaderNames.ContentType); + return Headers[HttpKnownHeaderNames.ContentType]; } } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs index 757cb4e7de..905fe8db18 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestContext.cs @@ -194,8 +194,8 @@ namespace Microsoft.Net.Http.Server } // Connection: Upgrade (some odd clients send Upgrade,KeepAlive) - string connection = Request.Headers[HttpKnownHeaderNames.Connection] ?? string.Empty; - if (connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0) + string connection = Request.Headers[HttpKnownHeaderNames.Connection]; + if (connection == null || connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0) { return false; } @@ -244,8 +244,8 @@ namespace Microsoft.Net.Http.Server } // Connection: Upgrade (some odd clients send Upgrade,KeepAlive) - string connection = Request.Headers[HttpKnownHeaderNames.Connection] ?? string.Empty; - if (connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0) + string connection = Request.Headers[HttpKnownHeaderNames.Connection]; + if (connection == null || connection.IndexOf(HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase) < 0) { throw new InvalidOperationException("The Connection header is invalid: " + connection); } @@ -345,9 +345,9 @@ namespace Microsoft.Net.Http.Server string secWebSocketKey = Request.Headers[HttpKnownHeaderNames.SecWebSocketKey]; string secWebSocketAccept = WebSocketHelpers.GetSecWebSocketAcceptString(secWebSocketKey); - Response.Headers.AppendValues(HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade); - Response.Headers.AppendValues(HttpKnownHeaderNames.Upgrade, WebSocketHelpers.WebSocketUpgradeToken); - Response.Headers.AppendValues(HttpKnownHeaderNames.SecWebSocketAccept, secWebSocketAccept); + Response.Headers.Append(HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade); + Response.Headers.Append(HttpKnownHeaderNames.Upgrade, WebSocketHelpers.WebSocketUpgradeToken); + Response.Headers.Append(HttpKnownHeaderNames.SecWebSocketAccept, secWebSocketAccept); Stream opaqueStream = await UpgradeAsync(); diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.cs index 66019a500e..1326e7204d 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.cs @@ -29,6 +29,7 @@ using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.Framework.Primitives; namespace Microsoft.Net.Http.Server { @@ -36,52 +37,52 @@ namespace Microsoft.Net.Http.Server internal partial class RequestHeaders { // Tracks if individual fields have been read from native or set directly. - // Once read or set, their presence in the collection is marked by if their string[] is null or not. + // Once read or set, their presence in the collection is marked by if their StringValues is null or not. private UInt32 _flag0, _flag1; - private string[] _Accept; - private string[] _AcceptCharset; - private string[] _AcceptEncoding; - private string[] _AcceptLanguage; - private string[] _Allow; - private string[] _Authorization; - private string[] _CacheControl; - private string[] _Connection; - private string[] _ContentEncoding; - private string[] _ContentLanguage; - private string[] _ContentLength; - private string[] _ContentLocation; - private string[] _ContentMd5; - private string[] _ContentRange; - private string[] _ContentType; - private string[] _Cookie; - private string[] _Date; - private string[] _Expect; - private string[] _Expires; - private string[] _From; - private string[] _Host; - private string[] _IfMatch; - private string[] _IfModifiedSince; - private string[] _IfNoneMatch; - private string[] _IfRange; - private string[] _IfUnmodifiedSince; - private string[] _KeepAlive; - private string[] _LastModified; - private string[] _MaxForwards; - private string[] _Pragma; - private string[] _ProxyAuthorization; - private string[] _Range; - private string[] _Referer; - private string[] _Te; - private string[] _Trailer; - private string[] _TransferEncoding; - private string[] _Translate; - private string[] _Upgrade; - private string[] _UserAgent; - private string[] _Via; - private string[] _Warning; + private StringValues _Accept; + private StringValues _AcceptCharset; + private StringValues _AcceptEncoding; + private StringValues _AcceptLanguage; + private StringValues _Allow; + private StringValues _Authorization; + private StringValues _CacheControl; + private StringValues _Connection; + private StringValues _ContentEncoding; + private StringValues _ContentLanguage; + private StringValues _ContentLength; + private StringValues _ContentLocation; + private StringValues _ContentMd5; + private StringValues _ContentRange; + private StringValues _ContentType; + private StringValues _Cookie; + private StringValues _Date; + private StringValues _Expect; + private StringValues _Expires; + private StringValues _From; + private StringValues _Host; + private StringValues _IfMatch; + private StringValues _IfModifiedSince; + private StringValues _IfNoneMatch; + private StringValues _IfRange; + private StringValues _IfUnmodifiedSince; + private StringValues _KeepAlive; + private StringValues _LastModified; + private StringValues _MaxForwards; + private StringValues _Pragma; + private StringValues _ProxyAuthorization; + private StringValues _Range; + private StringValues _Referer; + private StringValues _Te; + private StringValues _Trailer; + private StringValues _TransferEncoding; + private StringValues _Translate; + private StringValues _Upgrade; + private StringValues _UserAgent; + private StringValues _Via; + private StringValues _Warning; - internal string[] Accept + internal StringValues Accept { get { @@ -90,7 +91,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Accept); if (nativeValue != null) { - _Accept = new string[] { nativeValue }; + _Accept = nativeValue; } _flag0 |= 0x1u; } @@ -103,7 +104,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] AcceptCharset + internal StringValues AcceptCharset { get { @@ -112,7 +113,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.AcceptCharset); if (nativeValue != null) { - _AcceptCharset = new string[] { nativeValue }; + _AcceptCharset = nativeValue; } _flag0 |= 0x2u; } @@ -125,7 +126,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] AcceptEncoding + internal StringValues AcceptEncoding { get { @@ -134,7 +135,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.AcceptEncoding); if (nativeValue != null) { - _AcceptEncoding = new string[] { nativeValue }; + _AcceptEncoding = nativeValue; } _flag0 |= 0x4u; } @@ -147,7 +148,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] AcceptLanguage + internal StringValues AcceptLanguage { get { @@ -156,7 +157,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.AcceptLanguage); if (nativeValue != null) { - _AcceptLanguage = new string[] { nativeValue }; + _AcceptLanguage = nativeValue; } _flag0 |= 0x8u; } @@ -169,7 +170,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Allow + internal StringValues Allow { get { @@ -178,7 +179,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Allow); if (nativeValue != null) { - _Allow = new string[] { nativeValue }; + _Allow = nativeValue; } _flag0 |= 0x10u; } @@ -191,7 +192,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Authorization + internal StringValues Authorization { get { @@ -200,7 +201,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Authorization); if (nativeValue != null) { - _Authorization = new string[] { nativeValue }; + _Authorization = nativeValue; } _flag0 |= 0x20u; } @@ -213,7 +214,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] CacheControl + internal StringValues CacheControl { get { @@ -222,7 +223,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.CacheControl); if (nativeValue != null) { - _CacheControl = new string[] { nativeValue }; + _CacheControl = nativeValue; } _flag0 |= 0x40u; } @@ -235,7 +236,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Connection + internal StringValues Connection { get { @@ -244,7 +245,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Connection); if (nativeValue != null) { - _Connection = new string[] { nativeValue }; + _Connection = nativeValue; } _flag0 |= 0x80u; } @@ -257,7 +258,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ContentEncoding + internal StringValues ContentEncoding { get { @@ -266,7 +267,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ContentEncoding); if (nativeValue != null) { - _ContentEncoding = new string[] { nativeValue }; + _ContentEncoding = nativeValue; } _flag0 |= 0x100u; } @@ -279,7 +280,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ContentLanguage + internal StringValues ContentLanguage { get { @@ -288,7 +289,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ContentLanguage); if (nativeValue != null) { - _ContentLanguage = new string[] { nativeValue }; + _ContentLanguage = nativeValue; } _flag0 |= 0x200u; } @@ -301,7 +302,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ContentLength + internal StringValues ContentLength { get { @@ -310,7 +311,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ContentLength); if (nativeValue != null) { - _ContentLength = new string[] { nativeValue }; + _ContentLength = nativeValue; } _flag0 |= 0x400u; } @@ -323,7 +324,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ContentLocation + internal StringValues ContentLocation { get { @@ -332,7 +333,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ContentLocation); if (nativeValue != null) { - _ContentLocation = new string[] { nativeValue }; + _ContentLocation = nativeValue; } _flag0 |= 0x800u; } @@ -345,7 +346,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ContentMd5 + internal StringValues ContentMd5 { get { @@ -354,7 +355,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ContentMd5); if (nativeValue != null) { - _ContentMd5 = new string[] { nativeValue }; + _ContentMd5 = nativeValue; } _flag0 |= 0x1000u; } @@ -367,7 +368,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ContentRange + internal StringValues ContentRange { get { @@ -376,7 +377,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ContentRange); if (nativeValue != null) { - _ContentRange = new string[] { nativeValue }; + _ContentRange = nativeValue; } _flag0 |= 0x2000u; } @@ -389,7 +390,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ContentType + internal StringValues ContentType { get { @@ -398,7 +399,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ContentType); if (nativeValue != null) { - _ContentType = new string[] { nativeValue }; + _ContentType = nativeValue; } _flag0 |= 0x4000u; } @@ -411,7 +412,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Cookie + internal StringValues Cookie { get { @@ -420,7 +421,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Cookie); if (nativeValue != null) { - _Cookie = new string[] { nativeValue }; + _Cookie = nativeValue; } _flag0 |= 0x8000u; } @@ -433,7 +434,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Date + internal StringValues Date { get { @@ -442,7 +443,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Date); if (nativeValue != null) { - _Date = new string[] { nativeValue }; + _Date = nativeValue; } _flag0 |= 0x10000u; } @@ -455,7 +456,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Expect + internal StringValues Expect { get { @@ -464,7 +465,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Expect); if (nativeValue != null) { - _Expect = new string[] { nativeValue }; + _Expect = nativeValue; } _flag0 |= 0x20000u; } @@ -477,7 +478,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Expires + internal StringValues Expires { get { @@ -486,7 +487,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Expires); if (nativeValue != null) { - _Expires = new string[] { nativeValue }; + _Expires = nativeValue; } _flag0 |= 0x40000u; } @@ -499,7 +500,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] From + internal StringValues From { get { @@ -508,7 +509,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.From); if (nativeValue != null) { - _From = new string[] { nativeValue }; + _From = nativeValue; } _flag0 |= 0x80000u; } @@ -521,7 +522,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Host + internal StringValues Host { get { @@ -530,7 +531,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Host); if (nativeValue != null) { - _Host = new string[] { nativeValue }; + _Host = nativeValue; } _flag0 |= 0x100000u; } @@ -543,7 +544,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] IfMatch + internal StringValues IfMatch { get { @@ -552,7 +553,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.IfMatch); if (nativeValue != null) { - _IfMatch = new string[] { nativeValue }; + _IfMatch = nativeValue; } _flag0 |= 0x200000u; } @@ -565,7 +566,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] IfModifiedSince + internal StringValues IfModifiedSince { get { @@ -574,7 +575,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.IfModifiedSince); if (nativeValue != null) { - _IfModifiedSince = new string[] { nativeValue }; + _IfModifiedSince = nativeValue; } _flag0 |= 0x400000u; } @@ -587,7 +588,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] IfNoneMatch + internal StringValues IfNoneMatch { get { @@ -596,7 +597,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.IfNoneMatch); if (nativeValue != null) { - _IfNoneMatch = new string[] { nativeValue }; + _IfNoneMatch = nativeValue; } _flag0 |= 0x800000u; } @@ -609,7 +610,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] IfRange + internal StringValues IfRange { get { @@ -618,7 +619,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.IfRange); if (nativeValue != null) { - _IfRange = new string[] { nativeValue }; + _IfRange = nativeValue; } _flag0 |= 0x1000000u; } @@ -631,7 +632,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] IfUnmodifiedSince + internal StringValues IfUnmodifiedSince { get { @@ -640,7 +641,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.IfUnmodifiedSince); if (nativeValue != null) { - _IfUnmodifiedSince = new string[] { nativeValue }; + _IfUnmodifiedSince = nativeValue; } _flag0 |= 0x2000000u; } @@ -653,7 +654,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] KeepAlive + internal StringValues KeepAlive { get { @@ -662,7 +663,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.KeepAlive); if (nativeValue != null) { - _KeepAlive = new string[] { nativeValue }; + _KeepAlive = nativeValue; } _flag0 |= 0x4000000u; } @@ -675,7 +676,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] LastModified + internal StringValues LastModified { get { @@ -684,7 +685,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.LastModified); if (nativeValue != null) { - _LastModified = new string[] { nativeValue }; + _LastModified = nativeValue; } _flag0 |= 0x8000000u; } @@ -697,7 +698,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] MaxForwards + internal StringValues MaxForwards { get { @@ -706,7 +707,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.MaxForwards); if (nativeValue != null) { - _MaxForwards = new string[] { nativeValue }; + _MaxForwards = nativeValue; } _flag0 |= 0x10000000u; } @@ -719,7 +720,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Pragma + internal StringValues Pragma { get { @@ -728,7 +729,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Pragma); if (nativeValue != null) { - _Pragma = new string[] { nativeValue }; + _Pragma = nativeValue; } _flag0 |= 0x20000000u; } @@ -741,7 +742,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] ProxyAuthorization + internal StringValues ProxyAuthorization { get { @@ -750,7 +751,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.ProxyAuthorization); if (nativeValue != null) { - _ProxyAuthorization = new string[] { nativeValue }; + _ProxyAuthorization = nativeValue; } _flag0 |= 0x40000000u; } @@ -763,7 +764,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Range + internal StringValues Range { get { @@ -772,7 +773,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Range); if (nativeValue != null) { - _Range = new string[] { nativeValue }; + _Range = nativeValue; } _flag0 |= 0x80000000u; } @@ -785,7 +786,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Referer + internal StringValues Referer { get { @@ -794,7 +795,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Referer); if (nativeValue != null) { - _Referer = new string[] { nativeValue }; + _Referer = nativeValue; } _flag1 |= 0x1u; } @@ -807,7 +808,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Te + internal StringValues Te { get { @@ -816,7 +817,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Te); if (nativeValue != null) { - _Te = new string[] { nativeValue }; + _Te = nativeValue; } _flag1 |= 0x2u; } @@ -829,7 +830,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Trailer + internal StringValues Trailer { get { @@ -838,7 +839,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Trailer); if (nativeValue != null) { - _Trailer = new string[] { nativeValue }; + _Trailer = nativeValue; } _flag1 |= 0x4u; } @@ -851,7 +852,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] TransferEncoding + internal StringValues TransferEncoding { get { @@ -860,7 +861,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.TransferEncoding); if (nativeValue != null) { - _TransferEncoding = new string[] { nativeValue }; + _TransferEncoding = nativeValue; } _flag1 |= 0x8u; } @@ -873,7 +874,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Translate + internal StringValues Translate { get { @@ -882,7 +883,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Translate); if (nativeValue != null) { - _Translate = new string[] { nativeValue }; + _Translate = nativeValue; } _flag1 |= 0x10u; } @@ -895,7 +896,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Upgrade + internal StringValues Upgrade { get { @@ -904,7 +905,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Upgrade); if (nativeValue != null) { - _Upgrade = new string[] { nativeValue }; + _Upgrade = nativeValue; } _flag1 |= 0x20u; } @@ -917,7 +918,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] UserAgent + internal StringValues UserAgent { get { @@ -926,7 +927,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.UserAgent); if (nativeValue != null) { - _UserAgent = new string[] { nativeValue }; + _UserAgent = nativeValue; } _flag1 |= 0x40u; } @@ -939,7 +940,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Via + internal StringValues Via { get { @@ -948,7 +949,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Via); if (nativeValue != null) { - _Via = new string[] { nativeValue }; + _Via = nativeValue; } _flag1 |= 0x80u; } @@ -961,7 +962,7 @@ namespace Microsoft.Net.Http.Server } } - internal string[] Warning + internal StringValues Warning { get { @@ -970,7 +971,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(HttpSysRequestHeader.Warning); if (nativeValue != null) { - _Warning = new string[] { nativeValue }; + _Warning = nativeValue; } _flag1 |= 0x100u; } @@ -1189,7 +1190,7 @@ namespace Microsoft.Net.Http.Server return false; } - private bool PropertiesTryGetValue(string key, out string[] value) + private bool PropertiesTryGetValue(string key, out StringValues value) { switch (key.Length) { @@ -1433,11 +1434,11 @@ namespace Microsoft.Net.Http.Server } break; } - value = null; + value = StringValues.Empty; return false; } - private bool PropertiesTrySetValue(string key, string[] value) + private bool PropertiesTrySetValue(string key, StringValues value) { switch (key.Length) { @@ -1734,7 +1735,7 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Te", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x2u) != 0); - Te = null; + Te = StringValues.Empty; return wasSet; } break; @@ -1743,7 +1744,7 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Via", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x80u) != 0); - Via = null; + Via = StringValues.Empty; return wasSet; } break; @@ -1752,21 +1753,21 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Date", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x10000u) != 0); - Date = null; + Date = StringValues.Empty; return wasSet; } if (_From != null && string.Equals(key, "From", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x80000u) != 0); - From = null; + From = StringValues.Empty; return wasSet; } if (_Host != null && string.Equals(key, "Host", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x100000u) != 0); - Host = null; + Host = StringValues.Empty; return wasSet; } break; @@ -1775,14 +1776,14 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Allow", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x10u) != 0); - Allow = null; + Allow = StringValues.Empty; return wasSet; } if (_Range != null && string.Equals(key, "Range", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x80000000u) != 0); - Range = null; + Range = StringValues.Empty; return wasSet; } break; @@ -1791,28 +1792,28 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Accept", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x1u) != 0); - Accept = null; + Accept = StringValues.Empty; return wasSet; } if (_Cookie != null && string.Equals(key, "Cookie", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x8000u) != 0); - Cookie = null; + Cookie = StringValues.Empty; return wasSet; } if (_Expect != null && string.Equals(key, "Expect", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x20000u) != 0); - Expect = null; + Expect = StringValues.Empty; return wasSet; } if (_Pragma != null && string.Equals(key, "Pragma", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x20000000u) != 0); - Pragma = null; + Pragma = StringValues.Empty; return wasSet; } break; @@ -1821,35 +1822,35 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Expires", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x40000u) != 0); - Expires = null; + Expires = StringValues.Empty; return wasSet; } if (_Referer != null && string.Equals(key, "Referer", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x1u) != 0); - Referer = null; + Referer = StringValues.Empty; return wasSet; } if (_Trailer != null && string.Equals(key, "Trailer", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x4u) != 0); - Trailer = null; + Trailer = StringValues.Empty; return wasSet; } if (_Upgrade != null && string.Equals(key, "Upgrade", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x20u) != 0); - Upgrade = null; + Upgrade = StringValues.Empty; return wasSet; } if (_Warning != null && string.Equals(key, "Warning", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x100u) != 0); - Warning = null; + Warning = StringValues.Empty; return wasSet; } break; @@ -1858,14 +1859,14 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "If-Match", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x200000u) != 0); - IfMatch = null; + IfMatch = StringValues.Empty; return wasSet; } if (_IfRange != null && string.Equals(key, "If-Range", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x1000000u) != 0); - IfRange = null; + IfRange = StringValues.Empty; return wasSet; } break; @@ -1874,7 +1875,7 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Translate", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x10u) != 0); - Translate = null; + Translate = StringValues.Empty; return wasSet; } break; @@ -1883,21 +1884,21 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Connection", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x80u) != 0); - Connection = null; + Connection = StringValues.Empty; return wasSet; } if (_KeepAlive != null && string.Equals(key, "Keep-Alive", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x4000000u) != 0); - KeepAlive = null; + KeepAlive = StringValues.Empty; return wasSet; } if (_UserAgent != null && string.Equals(key, "User-Agent", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x40u) != 0); - UserAgent = null; + UserAgent = StringValues.Empty; return wasSet; } break; @@ -1906,7 +1907,7 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Content-Md5", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x1000u) != 0); - ContentMd5 = null; + ContentMd5 = StringValues.Empty; return wasSet; } break; @@ -1915,14 +1916,14 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Content-Type", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x4000u) != 0); - ContentType = null; + ContentType = StringValues.Empty; return wasSet; } if (_MaxForwards != null && string.Equals(key, "Max-Forwards", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x10000000u) != 0); - MaxForwards = null; + MaxForwards = StringValues.Empty; return wasSet; } break; @@ -1931,35 +1932,35 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Authorization", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x20u) != 0); - Authorization = null; + Authorization = StringValues.Empty; return wasSet; } if (_CacheControl != null && string.Equals(key, "Cache-Control", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x40u) != 0); - CacheControl = null; + CacheControl = StringValues.Empty; return wasSet; } if (_ContentRange != null && string.Equals(key, "Content-Range", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x2000u) != 0); - ContentRange = null; + ContentRange = StringValues.Empty; return wasSet; } if (_IfNoneMatch != null && string.Equals(key, "If-None-Match", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x800000u) != 0); - IfNoneMatch = null; + IfNoneMatch = StringValues.Empty; return wasSet; } if (_LastModified != null && string.Equals(key, "Last-Modified", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x8000000u) != 0); - LastModified = null; + LastModified = StringValues.Empty; return wasSet; } break; @@ -1968,14 +1969,14 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Accept-Charset", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x2u) != 0); - AcceptCharset = null; + AcceptCharset = StringValues.Empty; return wasSet; } if (_ContentLength != null && string.Equals(key, "Content-Length", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x400u) != 0); - ContentLength = null; + ContentLength = StringValues.Empty; return wasSet; } break; @@ -1984,14 +1985,14 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Accept-Encoding", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x4u) != 0); - AcceptEncoding = null; + AcceptEncoding = StringValues.Empty; return wasSet; } if (_AcceptLanguage != null && string.Equals(key, "Accept-Language", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x8u) != 0); - AcceptLanguage = null; + AcceptLanguage = StringValues.Empty; return wasSet; } break; @@ -2000,21 +2001,21 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "Content-Encoding", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x100u) != 0); - ContentEncoding = null; + ContentEncoding = StringValues.Empty; return wasSet; } if (_ContentLanguage != null && string.Equals(key, "Content-Language", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x200u) != 0); - ContentLanguage = null; + ContentLanguage = StringValues.Empty; return wasSet; } if (_ContentLocation != null && string.Equals(key, "Content-Location", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x800u) != 0); - ContentLocation = null; + ContentLocation = StringValues.Empty; return wasSet; } break; @@ -2023,14 +2024,14 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "If-Modified-Since", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x400000u) != 0); - IfModifiedSince = null; + IfModifiedSince = StringValues.Empty; return wasSet; } if (_TransferEncoding != null && string.Equals(key, "Transfer-Encoding", StringComparison.Ordinal)) { bool wasSet = ((_flag1 & 0x8u) != 0); - TransferEncoding = null; + TransferEncoding = StringValues.Empty; return wasSet; } break; @@ -2039,14 +2040,14 @@ namespace Microsoft.Net.Http.Server && string.Equals(key, "If-Unmodified-Since", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x2000000u) != 0); - IfUnmodifiedSince = null; + IfUnmodifiedSince = StringValues.Empty; return wasSet; } if (_ProxyAuthorization != null && string.Equals(key, "Proxy-Authorization", StringComparison.Ordinal)) { bool wasSet = ((_flag0 & 0x40000000u) != 0); - ProxyAuthorization = null; + ProxyAuthorization = StringValues.Empty; return wasSet; } break; @@ -2222,7 +2223,7 @@ namespace Microsoft.Net.Http.Server } } - private IEnumerable PropertiesValues() + private IEnumerable PropertiesValues() { if (Accept != null) { @@ -2390,171 +2391,171 @@ namespace Microsoft.Net.Http.Server } } - private IEnumerable> PropertiesEnumerable() + private IEnumerable> PropertiesEnumerable() { if (Accept != null) { - yield return new KeyValuePair("Accept", Accept); + yield return new KeyValuePair("Accept", Accept); } if (AcceptCharset != null) { - yield return new KeyValuePair("Accept-Charset", AcceptCharset); + yield return new KeyValuePair("Accept-Charset", AcceptCharset); } if (AcceptEncoding != null) { - yield return new KeyValuePair("Accept-Encoding", AcceptEncoding); + yield return new KeyValuePair("Accept-Encoding", AcceptEncoding); } if (AcceptLanguage != null) { - yield return new KeyValuePair("Accept-Language", AcceptLanguage); + yield return new KeyValuePair("Accept-Language", AcceptLanguage); } if (Allow != null) { - yield return new KeyValuePair("Allow", Allow); + yield return new KeyValuePair("Allow", Allow); } if (Authorization != null) { - yield return new KeyValuePair("Authorization", Authorization); + yield return new KeyValuePair("Authorization", Authorization); } if (CacheControl != null) { - yield return new KeyValuePair("Cache-Control", CacheControl); + yield return new KeyValuePair("Cache-Control", CacheControl); } if (Connection != null) { - yield return new KeyValuePair("Connection", Connection); + yield return new KeyValuePair("Connection", Connection); } if (ContentEncoding != null) { - yield return new KeyValuePair("Content-Encoding", ContentEncoding); + yield return new KeyValuePair("Content-Encoding", ContentEncoding); } if (ContentLanguage != null) { - yield return new KeyValuePair("Content-Language", ContentLanguage); + yield return new KeyValuePair("Content-Language", ContentLanguage); } if (ContentLength != null) { - yield return new KeyValuePair("Content-Length", ContentLength); + yield return new KeyValuePair("Content-Length", ContentLength); } if (ContentLocation != null) { - yield return new KeyValuePair("Content-Location", ContentLocation); + yield return new KeyValuePair("Content-Location", ContentLocation); } if (ContentMd5 != null) { - yield return new KeyValuePair("Content-Md5", ContentMd5); + yield return new KeyValuePair("Content-Md5", ContentMd5); } if (ContentRange != null) { - yield return new KeyValuePair("Content-Range", ContentRange); + yield return new KeyValuePair("Content-Range", ContentRange); } if (ContentType != null) { - yield return new KeyValuePair("Content-Type", ContentType); + yield return new KeyValuePair("Content-Type", ContentType); } if (Cookie != null) { - yield return new KeyValuePair("Cookie", Cookie); + yield return new KeyValuePair("Cookie", Cookie); } if (Date != null) { - yield return new KeyValuePair("Date", Date); + yield return new KeyValuePair("Date", Date); } if (Expect != null) { - yield return new KeyValuePair("Expect", Expect); + yield return new KeyValuePair("Expect", Expect); } if (Expires != null) { - yield return new KeyValuePair("Expires", Expires); + yield return new KeyValuePair("Expires", Expires); } if (From != null) { - yield return new KeyValuePair("From", From); + yield return new KeyValuePair("From", From); } if (Host != null) { - yield return new KeyValuePair("Host", Host); + yield return new KeyValuePair("Host", Host); } if (IfMatch != null) { - yield return new KeyValuePair("If-Match", IfMatch); + yield return new KeyValuePair("If-Match", IfMatch); } if (IfModifiedSince != null) { - yield return new KeyValuePair("If-Modified-Since", IfModifiedSince); + yield return new KeyValuePair("If-Modified-Since", IfModifiedSince); } if (IfNoneMatch != null) { - yield return new KeyValuePair("If-None-Match", IfNoneMatch); + yield return new KeyValuePair("If-None-Match", IfNoneMatch); } if (IfRange != null) { - yield return new KeyValuePair("If-Range", IfRange); + yield return new KeyValuePair("If-Range", IfRange); } if (IfUnmodifiedSince != null) { - yield return new KeyValuePair("If-Unmodified-Since", IfUnmodifiedSince); + yield return new KeyValuePair("If-Unmodified-Since", IfUnmodifiedSince); } if (KeepAlive != null) { - yield return new KeyValuePair("Keep-Alive", KeepAlive); + yield return new KeyValuePair("Keep-Alive", KeepAlive); } if (LastModified != null) { - yield return new KeyValuePair("Last-Modified", LastModified); + yield return new KeyValuePair("Last-Modified", LastModified); } if (MaxForwards != null) { - yield return new KeyValuePair("Max-Forwards", MaxForwards); + yield return new KeyValuePair("Max-Forwards", MaxForwards); } if (Pragma != null) { - yield return new KeyValuePair("Pragma", Pragma); + yield return new KeyValuePair("Pragma", Pragma); } if (ProxyAuthorization != null) { - yield return new KeyValuePair("Proxy-Authorization", ProxyAuthorization); + yield return new KeyValuePair("Proxy-Authorization", ProxyAuthorization); } if (Range != null) { - yield return new KeyValuePair("Range", Range); + yield return new KeyValuePair("Range", Range); } if (Referer != null) { - yield return new KeyValuePair("Referer", Referer); + yield return new KeyValuePair("Referer", Referer); } if (Te != null) { - yield return new KeyValuePair("Te", Te); + yield return new KeyValuePair("Te", Te); } if (Trailer != null) { - yield return new KeyValuePair("Trailer", Trailer); + yield return new KeyValuePair("Trailer", Trailer); } if (TransferEncoding != null) { - yield return new KeyValuePair("Transfer-Encoding", TransferEncoding); + yield return new KeyValuePair("Transfer-Encoding", TransferEncoding); } if (Translate != null) { - yield return new KeyValuePair("Translate", Translate); + yield return new KeyValuePair("Translate", Translate); } if (Upgrade != null) { - yield return new KeyValuePair("Upgrade", Upgrade); + yield return new KeyValuePair("Upgrade", Upgrade); } if (UserAgent != null) { - yield return new KeyValuePair("User-Agent", UserAgent); + yield return new KeyValuePair("User-Agent", UserAgent); } if (Via != null) { - yield return new KeyValuePair("Via", Via); + yield return new KeyValuePair("Via", Via); } if (Warning != null) { - yield return new KeyValuePair("Warning", Warning); + yield return new KeyValuePair("Warning", Warning); } } } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.tt b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.tt index 931380b1fd..a029f29b02 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.tt +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.Generated.tt @@ -68,6 +68,7 @@ using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.Framework.Primitives; namespace Microsoft.Net.Http.Server { @@ -75,15 +76,15 @@ namespace Microsoft.Net.Http.Server internal partial class RequestHeaders { // Tracks if individual fields have been read from native or set directly. - // Once read or set, their presence in the collection is marked by if their string[] is null or not. + // Once read or set, their presence in the collection is marked by if their StringValues is null or not. private UInt32 _flag0, _flag1; <# foreach(var prop in props) { #> - private string[] _<#=prop.Name#>; + private StringValues _<#=prop.Name#>; <# } #> <# foreach(var prop in props) { #> - internal string[] <#=prop.Name#> + internal StringValues <#=prop.Name#> { get { @@ -92,7 +93,7 @@ namespace Microsoft.Net.Http.Server string nativeValue = GetKnownHeader(<#=prop.ID#>); if (nativeValue != null) { - _<#=prop.Name#> = new string[] { nativeValue }; + _<#=prop.Name#> = nativeValue; } <#=MarkRead(prop.Index)#>; } @@ -124,7 +125,7 @@ namespace Microsoft.Net.Http.Server return false; } - private bool PropertiesTryGetValue(string key, out string[] value) + private bool PropertiesTryGetValue(string key, out StringValues value) { switch (key.Length) { @@ -144,7 +145,7 @@ namespace Microsoft.Net.Http.Server return false; } - private bool PropertiesTrySetValue(string key, string[] value) + private bool PropertiesTrySetValue(string key, StringValues value) { switch (key.Length) { @@ -195,7 +196,7 @@ namespace Microsoft.Net.Http.Server <# } #> } - private IEnumerable PropertiesValues() + private IEnumerable PropertiesValues() { <# foreach(var prop in props) { #> if (<#=prop.Name#> != null) @@ -205,12 +206,12 @@ namespace Microsoft.Net.Http.Server <# } #> } - private IEnumerable> PropertiesEnumerable() + private IEnumerable> PropertiesEnumerable() { <# foreach(var prop in props) { #> if (<#=prop.Name#> != null) { - yield return new KeyValuePair("<#=prop.Key#>", <#=prop.Name#>); + yield return new KeyValuePair("<#=prop.Key#>", <#=prop.Name#>); } <# } #> } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs index 95e754870a..cc00e29da1 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/RequestHeaders.cs @@ -39,12 +39,13 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; +using Microsoft.Framework.Primitives; namespace Microsoft.Net.Http.Server { - internal partial class RequestHeaders : IDictionary + internal partial class RequestHeaders : IDictionary { - private IDictionary _extra; + private IDictionary _extra; private NativeRequestContext _requestMemoryBlob; internal RequestHeaders(NativeRequestContext requestMemoryBlob) @@ -52,13 +53,13 @@ namespace Microsoft.Net.Http.Server _requestMemoryBlob = requestMemoryBlob; } - private IDictionary Extra + private IDictionary Extra { get { if (_extra == null) { - var newDict = new Dictionary(StringComparer.OrdinalIgnoreCase); + var newDict = new Dictionary(StringComparer.OrdinalIgnoreCase); GetUnknownHeaders(newDict); Interlocked.CompareExchange(ref _extra, newDict, null); } @@ -66,11 +67,11 @@ namespace Microsoft.Net.Http.Server } } - string[] IDictionary.this[string key] + StringValues IDictionary.this[string key] { get { - string[] value; + StringValues value; return PropertiesTryGetValue(key, out value) ? value : Extra[key]; } set @@ -88,13 +89,13 @@ namespace Microsoft.Net.Http.Server _requestMemoryBlob.OriginalBlobAddress, (int)header); } - private void GetUnknownHeaders(IDictionary extra) + private void GetUnknownHeaders(IDictionary extra) { UnsafeNclNativeMethods.HttpApi.GetUnknownHeaders(extra, _requestMemoryBlob.RequestBuffer, _requestMemoryBlob.OriginalBlobAddress); } - void IDictionary.Add(string key, string[] value) + void IDictionary.Add(string key, StringValues value) { if (!PropertiesTrySetValue(key, value)) { @@ -112,7 +113,7 @@ namespace Microsoft.Net.Http.Server get { return PropertiesKeys().Concat(Extra.Keys).ToArray(); } } - ICollection IDictionary.Values + ICollection IDictionary.Values { get { return PropertiesValues().Concat(Extra.Values).ToArray(); } } @@ -130,17 +131,17 @@ namespace Microsoft.Net.Http.Server return PropertiesTryRemove(key) || Extra.Remove(key); } - public bool TryGetValue(string key, out string[] value) + public bool TryGetValue(string key, out StringValues value) { return PropertiesTryGetValue(key, out value) || Extra.TryGetValue(key, out value); } - void ICollection>.Add(KeyValuePair item) + void ICollection>.Add(KeyValuePair item) { ((IDictionary)this).Add(item.Key, item.Value); } - void ICollection>.Clear() + void ICollection>.Clear() { foreach (var key in PropertiesKeys()) { @@ -149,36 +150,36 @@ namespace Microsoft.Net.Http.Server Extra.Clear(); } - bool ICollection>.Contains(KeyValuePair item) + bool ICollection>.Contains(KeyValuePair item) { object value; return ((IDictionary)this).TryGetValue(item.Key, out value) && Object.Equals(value, item.Value); } - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { PropertiesEnumerable().Concat(Extra).ToArray().CopyTo(array, arrayIndex); } - bool ICollection>.IsReadOnly + bool ICollection>.IsReadOnly { get { return false; } } - bool ICollection>.Remove(KeyValuePair item) + bool ICollection>.Remove(KeyValuePair item) { - return ((IDictionary)this).Contains(item) && - ((IDictionary)this).Remove(item.Key); + return ((IDictionary)this).Contains(item) && + ((IDictionary)this).Remove(item.Key); } - IEnumerator> IEnumerable>.GetEnumerator() + IEnumerator> IEnumerable>.GetEnumerator() { return PropertiesEnumerable().Concat(Extra).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return ((IDictionary)this).GetEnumerator(); + return ((IDictionary)this).GetEnumerator(); } } } diff --git a/src/Microsoft.Net.Http.Server/RequestProcessing/Response.cs b/src/Microsoft.Net.Http.Server/RequestProcessing/Response.cs index 487aa46cdc..8648b3bce5 100644 --- a/src/Microsoft.Net.Http.Server/RequestProcessing/Response.cs +++ b/src/Microsoft.Net.Http.Server/RequestProcessing/Response.cs @@ -33,14 +33,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Framework.Logging; +using Microsoft.Framework.Primitives; using static Microsoft.Net.Http.Server.UnsafeNclNativeMethods; namespace Microsoft.Net.Http.Server { public sealed unsafe class Response { - private static readonly string[] ZeroContentLength = new[] { Constants.Zero }; - private ResponseState _responseState; private HeaderCollection _headers; private string _reasonPhrase; @@ -200,7 +199,7 @@ namespace Microsoft.Net.Http.Server { get { - string contentLengthString = Headers.Get(HttpKnownHeaderNames.ContentLength); + string contentLengthString = Headers[HttpKnownHeaderNames.ContentLength]; long contentLength; if (!string.IsNullOrWhiteSpace(contentLengthString)) { @@ -232,7 +231,7 @@ namespace Microsoft.Net.Http.Server if (value.Value == 0) { - ((IDictionary)Headers)[HttpKnownHeaderNames.ContentLength] = ZeroContentLength; + Headers[HttpKnownHeaderNames.ContentLength] = Constants.Zero; } else { @@ -246,7 +245,7 @@ namespace Microsoft.Net.Http.Server { get { - return Headers.Get(HttpKnownHeaderNames.ContentType); + return Headers[HttpKnownHeaderNames.ContentType]; } set { @@ -467,14 +466,14 @@ namespace Microsoft.Net.Http.Server // Gather everything from the request that affects the response: var requestVersion = Request.ProtocolVersion; - var requestConnectionString = Request.Headers.Get(HttpKnownHeaderNames.Connection); + var requestConnectionString = Request.Headers[HttpKnownHeaderNames.Connection]; var isHeadRequest = Request.IsHeadMethod; var requestCloseSet = Matches(Constants.Close, requestConnectionString); // Gather everything the app may have set on the response: // Http.Sys does not allow us to specify the response protocol version, assume this is a HTTP/1.1 response when making decisions. - var responseConnectionString = Headers.Get(HttpKnownHeaderNames.Connection); - var transferEncodingString = Headers.Get(HttpKnownHeaderNames.TransferEncoding); + var responseConnectionString = Headers[HttpKnownHeaderNames.Connection]; + var transferEncodingString = Headers[HttpKnownHeaderNames.TransferEncoding]; var responseContentLength = ContentLength; var responseCloseSet = Matches(Constants.Close, responseConnectionString); var responseChunkedSet = Matches(Constants.Chunked, transferEncodingString); @@ -572,9 +571,9 @@ namespace Microsoft.Net.Http.Server int numUnknownHeaders = 0; int numKnownMultiHeaders = 0; - foreach (KeyValuePair headerPair in Headers) + foreach (var headerPair in Headers) { - if (headerPair.Value.Length == 0) + if (headerPair.Value.Count == 0) { // TODO: Have the collection exclude empty headers. continue; @@ -586,9 +585,9 @@ namespace Microsoft.Net.Http.Server if (lookup == -1 || (isOpaqueUpgrade && lookup == (int)HttpApi.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderConnection)) { - numUnknownHeaders += headerPair.Value.Length; + numUnknownHeaders += headerPair.Value.Count; } - else if (headerPair.Value.Length > 1) + else if (headerPair.Value.Count > 1) { numKnownMultiHeaders++; } @@ -599,15 +598,15 @@ namespace Microsoft.Net.Http.Server { fixed (HttpApi.HTTP_KNOWN_HEADER* pKnownHeaders = &_nativeResponse.Response_V1.Headers.KnownHeaders) { - foreach (KeyValuePair headerPair in Headers) + foreach (var headerPair in Headers) { - if (headerPair.Value.Length == 0) + if (headerPair.Value.Count == 0) { // TODO: Have the collection exclude empty headers. continue; } headerName = headerPair.Key; - string[] headerValues = headerPair.Value; + StringValues headerValues = headerPair.Value; lookup = HttpApi.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerName); // Http.Sys doesn't let us send the Connection: Upgrade header as a Known header. @@ -622,7 +621,7 @@ namespace Microsoft.Net.Http.Server _nativeResponse.Response_V1.Headers.pUnknownHeaders = (HttpApi.HTTP_UNKNOWN_HEADER*)gcHandle.AddrOfPinnedObject(); } - for (int headerValueIndex = 0; headerValueIndex < headerValues.Length; headerValueIndex++) + for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++) { // Add Name bytes = new byte[HeaderEncoding.GetByteCount(headerName)]; @@ -643,7 +642,7 @@ namespace Microsoft.Net.Http.Server _nativeResponse.Response_V1.Headers.UnknownHeaderCount++; } } - else if (headerPair.Value.Length == 1) + else if (headerPair.Value.Count == 1) { headerValue = headerValues[0]; if (headerValue != null) @@ -674,12 +673,12 @@ namespace Microsoft.Net.Http.Server header.HeaderId = (HttpApi.HTTP_RESPONSE_HEADER_ID.Enum)lookup; header.Flags = HttpApi.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // TODO: The docs say this is for www-auth only. - HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApi.HTTP_KNOWN_HEADER[headerValues.Length]; + HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApi.HTTP_KNOWN_HEADER[headerValues.Count]; gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); header.KnownHeaders = (HttpApi.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject(); - for (int headerValueIndex = 0; headerValueIndex < headerValues.Length; headerValueIndex++) + for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++) { // Add Value headerValue = headerValues[headerValueIndex]; diff --git a/src/Microsoft.Net.Http.Server/project.json b/src/Microsoft.Net.Http.Server/project.json index 8356811d61..ac42adf57d 100644 --- a/src/Microsoft.Net.Http.Server/project.json +++ b/src/Microsoft.Net.Http.Server/project.json @@ -3,6 +3,7 @@ "description": "Implementation of WebListener, a successor to HttpListener. It is used in the WebListener server package.", "dependencies": { "Microsoft.Framework.Logging.Abstractions": "1.0.0-*", + "Microsoft.Framework.Primitives": "1.0.0-*", "Microsoft.Net.WebSockets": "1.0.0-*" }, "compilationOptions": { diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs index fcf661891f..c8e1302986 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs @@ -22,6 +22,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Http.Features; using Microsoft.AspNet.Http.Internal; +using Microsoft.Framework.Primitives; using Xunit; namespace Microsoft.AspNet.Server.WebListener @@ -38,8 +39,8 @@ namespace Microsoft.AspNet.Server.WebListener // NOTE: The System.Net client only sends the Connection: keep-alive header on the first connection per service-point. // Assert.Equal(2, requestHeaders.Count); // Assert.Equal("Keep-Alive", requestHeaders.Get("Connection")); - Assert.NotNull(requestHeaders.Get("Host")); - Assert.Equal(null, requestHeaders.Get("Accept")); + Assert.False(StringValues.IsNullOrEmpty(requestHeaders["Host"])); + Assert.True(StringValues.IsNullOrEmpty(requestHeaders["Accept"])); return Task.FromResult(0); })) { @@ -56,13 +57,13 @@ namespace Microsoft.AspNet.Server.WebListener { var requestHeaders = new DefaultHttpContext((IFeatureCollection)env).Request.Headers; Assert.Equal(4, requestHeaders.Count); - Assert.NotNull(requestHeaders.Get("Host")); - Assert.Equal("close", requestHeaders.Get("Connection")); + Assert.False(StringValues.IsNullOrEmpty(requestHeaders["Host"])); + Assert.Equal("close", requestHeaders["Connection"]); // Apparently Http.Sys squashes request headers together. - Assert.Equal(1, requestHeaders.GetValues("Custom-Header").Count); - Assert.Equal("custom1, and custom2, custom3", requestHeaders.Get("Custom-Header")); - Assert.Equal(1, requestHeaders.GetValues("Spacer-Header").Count); - Assert.Equal("spacervalue, spacervalue", requestHeaders.Get("Spacer-Header")); + Assert.Equal(1, requestHeaders["Custom-Header"].Count); + Assert.Equal("custom1, and custom2, custom3", requestHeaders["Custom-Header"]); + Assert.Equal(1, requestHeaders["Spacer-Header"].Count); + Assert.Equal("spacervalue, spacervalue", requestHeaders["Spacer-Header"]); return Task.FromResult(0); })) { diff --git a/test/Microsoft.Net.Http.Server.FunctionalTests/RequestHeaderTests.cs b/test/Microsoft.Net.Http.Server.FunctionalTests/RequestHeaderTests.cs index 73eb3d152e..dd47057415 100644 --- a/test/Microsoft.Net.Http.Server.FunctionalTests/RequestHeaderTests.cs +++ b/test/Microsoft.Net.Http.Server.FunctionalTests/RequestHeaderTests.cs @@ -6,6 +6,7 @@ using System.Net.Http; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; +using Microsoft.Framework.Primitives; using Xunit; namespace Microsoft.Net.Http.Server @@ -26,10 +27,10 @@ namespace Microsoft.Net.Http.Server // Assert.Equal(2, requestHeaders.Count); // Assert.Equal("Keep-Alive", requestHeaders.Get("Connection")); Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]); - string[] values; + StringValues values; Assert.False(requestHeaders.TryGetValue("Accept", out values)); Assert.False(requestHeaders.ContainsKey("Accept")); - Assert.Null(requestHeaders["Accept"]); + Assert.True(StringValues.IsNullOrEmpty(requestHeaders["Accept"])); context.Dispose(); string response = await responseTask; diff --git a/test/Microsoft.Net.Http.Server.FunctionalTests/ResponseHeaderTests.cs b/test/Microsoft.Net.Http.Server.FunctionalTests/ResponseHeaderTests.cs index 2f6648aaf3..46c471c607 100644 --- a/test/Microsoft.Net.Http.Server.FunctionalTests/ResponseHeaderTests.cs +++ b/test/Microsoft.Net.Http.Server.FunctionalTests/ResponseHeaderTests.cs @@ -207,7 +207,7 @@ namespace Microsoft.Net.Http.Server var context = await server.GetContextAsync(); var responseHeaders = context.Response.Headers; - responseHeaders.SetValues("WWW-Authenticate", "custom1, and custom2", "custom3"); + responseHeaders["WWW-Authenticate"] = new[] { "custom1, and custom2", "custom3" }; context.Dispose(); // HttpClient would merge the headers no matter what @@ -232,7 +232,7 @@ namespace Microsoft.Net.Http.Server var context = await server.GetContextAsync(); var responseHeaders = context.Response.Headers; - responseHeaders.SetValues("Custom-Header1", "custom1, and custom2", "custom3"); + responseHeaders["Custom-Header1"] = new[] { "custom1, and custom2", "custom3" }; context.Dispose(); // HttpClient would merge the headers no matter what @@ -346,8 +346,8 @@ namespace Microsoft.Net.Http.Server var context = await server.GetContextAsync(); var responseHeaders = context.Response.Headers; - responseHeaders.SetValues("Custom1", "value1a", "value1b"); - responseHeaders.SetValues("Custom2", "value2a, value2b"); + responseHeaders["Custom1"] = new[] { "value1a", "value1b" }; + responseHeaders["Custom2"] = "value2a, value2b"; var body = context.Response.Body; Assert.False(context.Response.HasStarted); body.Flush(); @@ -382,8 +382,8 @@ namespace Microsoft.Net.Http.Server var context = await server.GetContextAsync(); var responseHeaders = context.Response.Headers; - responseHeaders.SetValues("Custom1", "value1a", "value1b"); - responseHeaders.SetValues("Custom2", "value2a, value2b"); + responseHeaders["Custom1"] = new[] { "value1a", "value1b" }; + responseHeaders["Custom2"] = "value2a, value2b"; var body = context.Response.Body; Assert.False(context.Response.HasStarted); await body.FlushAsync();