#426 Move IHeaderDictionary to Features to reduce wrapping.
This commit is contained in:
parent
8ecb147332
commit
3741d38691
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents request and response headers
|
||||
/// </summary>
|
||||
public interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, StringValues>
|
||||
{
|
||||
// This property is duplicated to resolve an ambiguity between IReadableStringCollection and IDictionary<string, StringValues>
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns>The stored value, or StringValues.Empty if the key is not present.</returns>
|
||||
new StringValues this[string key] { get; set; }
|
||||
|
||||
// This property is duplicated to resolve an ambiguity between IReadableStringCollection.Count and IDictionary<string, StringValues>.Count
|
||||
/// <summary>
|
||||
/// Gets the number of elements contained in the collection.
|
||||
/// </summary>
|
||||
new int Count { get; }
|
||||
|
||||
// This property is duplicated to resolve an ambiguity between IReadableStringCollection.Keys and IDictionary<string, StringValues>.Keys
|
||||
/// <summary>
|
||||
/// Gets a collection containing the keys.
|
||||
/// </summary>
|
||||
new ICollection<string> Keys { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents request and response headers
|
||||
/// </summary>
|
||||
public interface IHeaderDictionary : IDictionary<string, StringValues>
|
||||
{
|
||||
/// <summary>
|
||||
/// IHeaderDictionary has a different indexer contract than IDictionary, where it will return StringValues.Empty for missing entries.
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns>The stored value, or StringValues.Empty if the key is not present.</returns>
|
||||
new StringValues this[string key] { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features
|
||||
{
|
||||
|
|
@ -15,7 +13,7 @@ namespace Microsoft.AspNet.Http.Features
|
|||
string PathBase { get; set; }
|
||||
string Path { get; set; }
|
||||
string QueryString { get; set; }
|
||||
IDictionary<string, StringValues> Headers { get; set; }
|
||||
IHeaderDictionary Headers { get; set; }
|
||||
Stream Body { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features
|
||||
{
|
||||
|
|
@ -13,7 +11,7 @@ namespace Microsoft.AspNet.Http.Features
|
|||
{
|
||||
int StatusCode { get; set; }
|
||||
string ReasonPhrase { get; set; }
|
||||
IDictionary<string, StringValues> Headers { get; set; }
|
||||
IHeaderDictionary Headers { get; set; }
|
||||
Stream Body { get; set; }
|
||||
bool HasStarted { get; }
|
||||
void OnStarting(Func<object, Task> callback, object state);
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
|
||||
public override IHeaderDictionary Headers
|
||||
{
|
||||
get { return new HeaderDictionary(HttpRequestFeature.Headers); }
|
||||
get { return HttpRequestFeature.Headers; }
|
||||
}
|
||||
|
||||
public override IReadableStringCollection Cookies
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
|
||||
public override IHeaderDictionary Headers
|
||||
{
|
||||
get { return new HeaderDictionary(HttpResponseFeature.Headers); }
|
||||
get { return HttpResponseFeature.Headers; }
|
||||
}
|
||||
|
||||
public override Stream Body
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features.Internal
|
||||
{
|
||||
|
|
@ -12,7 +10,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
|||
{
|
||||
public HttpRequestFeature()
|
||||
{
|
||||
Headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
|
||||
Headers = new HeaderDictionary();
|
||||
Body = Stream.Null;
|
||||
Protocol = string.Empty;
|
||||
Scheme = string.Empty;
|
||||
|
|
@ -28,7 +26,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
|||
public string PathBase { get; set; }
|
||||
public string Path { get; set; }
|
||||
public string QueryString { get; set; }
|
||||
public IDictionary<string, StringValues> Headers { get; set; }
|
||||
public IHeaderDictionary Headers { get; set; }
|
||||
public Stream Body { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features.Internal
|
||||
{
|
||||
|
|
@ -14,7 +13,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
|||
public HttpResponseFeature()
|
||||
{
|
||||
StatusCode = 200;
|
||||
Headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
|
||||
Headers = new HeaderDictionary();
|
||||
Body = Stream.Null;
|
||||
}
|
||||
|
||||
|
|
@ -22,7 +21,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
|||
|
||||
public string ReasonPhrase { get; set; }
|
||||
|
||||
public IDictionary<string, StringValues> Headers { get; set; }
|
||||
public IHeaderDictionary Headers { get; set; }
|
||||
|
||||
public Stream Body { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNet.Owin
|
||||
{
|
||||
internal class DictionaryStringArrayWrapper : IDictionary<string, string[]>
|
||||
{
|
||||
public DictionaryStringArrayWrapper(IDictionary<string, StringValues> inner)
|
||||
public DictionaryStringArrayWrapper(IHeaderDictionary inner)
|
||||
{
|
||||
Inner = inner;
|
||||
}
|
||||
|
||||
public readonly IDictionary<string, StringValues> Inner;
|
||||
public readonly IHeaderDictionary Inner;
|
||||
|
||||
private KeyValuePair<string, StringValues> Convert(KeyValuePair<string, string[]> item) => new KeyValuePair<string, StringValues>(item.Key, item.Value);
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ namespace Microsoft.AspNet.Owin
|
|||
|
||||
string[] IDictionary<string, string[]>.this[string key]
|
||||
{
|
||||
get { return Inner[key]; }
|
||||
get { return ((IDictionary<string, StringValues>)Inner)[key]; }
|
||||
set { Inner[key] = value; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNet.Owin
|
||||
{
|
||||
internal class DictionaryStringValuesWrapper : IDictionary<string, StringValues>
|
||||
internal class DictionaryStringValuesWrapper : IHeaderDictionary
|
||||
{
|
||||
public DictionaryStringValuesWrapper(IDictionary<string, string[]> inner)
|
||||
{
|
||||
|
|
@ -25,6 +26,16 @@ namespace Microsoft.AspNet.Owin
|
|||
|
||||
private string[] Convert(StringValues item) => item;
|
||||
|
||||
StringValues IHeaderDictionary.this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
string[] values;
|
||||
return Inner.TryGetValue(key, out values) ? values : null;
|
||||
}
|
||||
set { Inner[key] = value; }
|
||||
}
|
||||
|
||||
StringValues IDictionary<string, StringValues>.this[string key]
|
||||
{
|
||||
get { return Inner[key]; }
|
||||
|
|
|
|||
|
|
@ -56,13 +56,13 @@ namespace Microsoft.AspNet.Owin
|
|||
{ OwinConstants.RequestPath, new FeatureMap<IHttpRequestFeature>(feature => feature.Path, () => string.Empty, (feature, value) => feature.Path = Convert.ToString(value)) },
|
||||
{ OwinConstants.RequestQueryString, new FeatureMap<IHttpRequestFeature>(feature => Utilities.RemoveQuestionMark(feature.QueryString), () => string.Empty,
|
||||
(feature, value) => feature.QueryString = Utilities.AddQuestionMark(Convert.ToString(value))) },
|
||||
{ OwinConstants.RequestHeaders, new FeatureMap<IHttpRequestFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeDictionaryStringValues((IDictionary<string, string[]>)value)) },
|
||||
{ OwinConstants.RequestHeaders, new FeatureMap<IHttpRequestFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary<string, string[]>)value)) },
|
||||
{ OwinConstants.RequestBody, new FeatureMap<IHttpRequestFeature>(feature => feature.Body, () => Stream.Null, (feature, value) => feature.Body = (Stream)value) },
|
||||
{ OwinConstants.RequestUser, new FeatureMap<IHttpAuthenticationFeature>(feature => feature.User, () => null, (feature, value) => feature.User = (ClaimsPrincipal)value) },
|
||||
|
||||
{ OwinConstants.ResponseStatusCode, new FeatureMap<IHttpResponseFeature>(feature => feature.StatusCode, () => 200, (feature, value) => feature.StatusCode = Convert.ToInt32(value)) },
|
||||
{ OwinConstants.ResponseReasonPhrase, new FeatureMap<IHttpResponseFeature>(feature => feature.ReasonPhrase, (feature, value) => feature.ReasonPhrase = Convert.ToString(value)) },
|
||||
{ OwinConstants.ResponseHeaders, new FeatureMap<IHttpResponseFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeDictionaryStringValues((IDictionary<string, string[]>)value)) },
|
||||
{ OwinConstants.ResponseHeaders, new FeatureMap<IHttpResponseFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary<string, string[]>)value)) },
|
||||
{ OwinConstants.ResponseBody, new FeatureMap<IHttpResponseFeature>(feature => feature.Body, () => Stream.Null, (feature, value) => feature.Body = (Stream)value) },
|
||||
{ OwinConstants.CommonKeys.OnSendingHeaders, new FeatureMap<IHttpResponseFeature>(
|
||||
feature => new Action<Action<object>, object>((cb, state) => {
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ namespace Microsoft.AspNet.Owin
|
|||
set { Prop(OwinConstants.RequestQueryString, Utilities.RemoveQuestionMark(value)); }
|
||||
}
|
||||
|
||||
IDictionary<string, StringValues> IHttpRequestFeature.Headers
|
||||
IHeaderDictionary IHttpRequestFeature.Headers
|
||||
{
|
||||
get { return Utilities.MakeDictionaryStringValues(Prop<IDictionary<string, string[]>>(OwinConstants.RequestHeaders)); }
|
||||
get { return Utilities.MakeHeaderDictionary(Prop<IDictionary<string, string[]>>(OwinConstants.RequestHeaders)); }
|
||||
set { Prop(OwinConstants.RequestHeaders, Utilities.MakeDictionaryStringArray(value)); }
|
||||
}
|
||||
|
||||
|
|
@ -136,9 +136,9 @@ namespace Microsoft.AspNet.Owin
|
|||
set { Prop(OwinConstants.ResponseReasonPhrase, value); }
|
||||
}
|
||||
|
||||
IDictionary<string, StringValues> IHttpResponseFeature.Headers
|
||||
IHeaderDictionary IHttpResponseFeature.Headers
|
||||
{
|
||||
get { return Utilities.MakeDictionaryStringValues(Prop<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders)); }
|
||||
get { return Utilities.MakeHeaderDictionary(Prop<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders)); }
|
||||
set { Prop(OwinConstants.ResponseHeaders, Utilities.MakeDictionaryStringArray(value)); }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Owin
|
|||
return new ClaimsPrincipal(principal);
|
||||
}
|
||||
|
||||
internal static IDictionary<string, StringValues> MakeDictionaryStringValues(IDictionary<string, string[]> dictionary)
|
||||
internal static IHeaderDictionary MakeHeaderDictionary(IDictionary<string, string[]> dictionary)
|
||||
{
|
||||
var wrapper = dictionary as DictionaryStringArrayWrapper;
|
||||
if (wrapper != null)
|
||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNet.Owin
|
|||
return new DictionaryStringValuesWrapper(dictionary);
|
||||
}
|
||||
|
||||
internal static IDictionary<string, string[]> MakeDictionaryStringArray(IDictionary<string, StringValues> dictionary)
|
||||
internal static IDictionary<string, string[]> MakeDictionaryStringArray(IHeaderDictionary dictionary)
|
||||
{
|
||||
var wrapper = dictionary as DictionaryStringValuesWrapper;
|
||||
if (wrapper != null)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Http.Extensions
|
|||
|
||||
public bool HasStarted { get { return true; } }
|
||||
|
||||
public IDictionary<string, StringValues> Headers { get; set; }
|
||||
public IHeaderDictionary Headers { get; set; }
|
||||
|
||||
public string ReasonPhrase { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
// Arrange
|
||||
const string expected = "localhost:9001";
|
||||
|
||||
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase)
|
||||
var headers = new HeaderDictionary()
|
||||
{
|
||||
{ "Host", expected },
|
||||
};
|
||||
|
|
@ -85,7 +85,7 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
// Arrange
|
||||
const string expected = "löcalhöst";
|
||||
|
||||
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase)
|
||||
var headers = new HeaderDictionary()
|
||||
{
|
||||
{ "Host", "xn--lcalhst-90ae" },
|
||||
};
|
||||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
// Arrange
|
||||
const string expected = "xn--lcalhst-90ae";
|
||||
|
||||
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
|
||||
var headers = new HeaderDictionary();
|
||||
|
||||
var request = CreateRequest(headers);
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
Assert.Equal(new[] { "name2=value2" }, cookieHeaders);
|
||||
}
|
||||
|
||||
private static HttpRequest CreateRequest(IDictionary<string, StringValues> headers)
|
||||
private static HttpRequest CreateRequest(IHeaderDictionary headers)
|
||||
{
|
||||
var context = new DefaultHttpContext();
|
||||
context.Features.Get<IHttpRequestFeature>().Headers = headers;
|
||||
|
|
@ -217,7 +217,7 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
|
||||
private static HttpRequest GetRequestWithHeader(string headerName, string headerValue)
|
||||
{
|
||||
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
|
||||
var headers = new HeaderDictionary();
|
||||
if (headerValue != null)
|
||||
{
|
||||
headers.Add(headerName, headerValue);
|
||||
|
|
|
|||
Loading…
Reference in New Issue