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

Commit 3741d38

Browse files
committed
#426 Move IHeaderDictionary to Features to reduce wrapping.
1 parent 8ecb147 commit 3741d38

File tree

15 files changed

+61
-69
lines changed

15 files changed

+61
-69
lines changed

Diff for: src/Microsoft.AspNet.Http.Abstractions/IHeaderDictionary.cs

-34
This file was deleted.
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using Microsoft.Extensions.Primitives;
6+
7+
namespace Microsoft.AspNet.Http
8+
{
9+
/// <summary>
10+
/// Represents request and response headers
11+
/// </summary>
12+
public interface IHeaderDictionary : IDictionary<string, StringValues>
13+
{
14+
/// <summary>
15+
/// IHeaderDictionary has a different indexer contract than IDictionary, where it will return StringValues.Empty for missing entries.
16+
/// </summary>
17+
/// <param name="key"></param>
18+
/// <returns>The stored value, or StringValues.Empty if the key is not present.</returns>
19+
new StringValues this[string key] { get; set; }
20+
}
21+
}

Diff for: src/Microsoft.AspNet.Http.Features/IHttpRequestFeature.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System.Collections.Generic;
54
using System.IO;
6-
using Microsoft.Extensions.Primitives;
75

86
namespace Microsoft.AspNet.Http.Features
97
{
@@ -15,7 +13,7 @@ public interface IHttpRequestFeature
1513
string PathBase { get; set; }
1614
string Path { get; set; }
1715
string QueryString { get; set; }
18-
IDictionary<string, StringValues> Headers { get; set; }
16+
IHeaderDictionary Headers { get; set; }
1917
Stream Body { get; set; }
2018
}
2119
}

Diff for: src/Microsoft.AspNet.Http.Features/IHttpResponseFeature.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.IO;
76
using System.Threading.Tasks;
8-
using Microsoft.Extensions.Primitives;
97

108
namespace Microsoft.AspNet.Http.Features
119
{
1210
public interface IHttpResponseFeature
1311
{
1412
int StatusCode { get; set; }
1513
string ReasonPhrase { get; set; }
16-
IDictionary<string, StringValues> Headers { get; set; }
14+
IHeaderDictionary Headers { get; set; }
1715
Stream Body { get; set; }
1816
bool HasStarted { get; }
1917
void OnStarting(Func<object, Task> callback, object state);

Diff for: src/Microsoft.AspNet.Http/DefaultHttpRequest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public override string Protocol
123123

124124
public override IHeaderDictionary Headers
125125
{
126-
get { return new HeaderDictionary(HttpRequestFeature.Headers); }
126+
get { return HttpRequestFeature.Headers; }
127127
}
128128

129129
public override IReadableStringCollection Cookies

Diff for: src/Microsoft.AspNet.Http/DefaultHttpResponse.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public override int StatusCode
4343

4444
public override IHeaderDictionary Headers
4545
{
46-
get { return new HeaderDictionary(HttpResponseFeature.Headers); }
46+
get { return HttpResponseFeature.Headers; }
4747
}
4848

4949
public override Stream Body

Diff for: src/Microsoft.AspNet.Http/Features/HttpRequestFeature.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
5-
using System.Collections.Generic;
64
using System.IO;
7-
using Microsoft.Extensions.Primitives;
5+
using Microsoft.AspNet.Http.Internal;
86

97
namespace Microsoft.AspNet.Http.Features.Internal
108
{
119
public class HttpRequestFeature : IHttpRequestFeature
1210
{
1311
public HttpRequestFeature()
1412
{
15-
Headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
13+
Headers = new HeaderDictionary();
1614
Body = Stream.Null;
1715
Protocol = string.Empty;
1816
Scheme = string.Empty;
@@ -28,7 +26,7 @@ public HttpRequestFeature()
2826
public string PathBase { get; set; }
2927
public string Path { get; set; }
3028
public string QueryString { get; set; }
31-
public IDictionary<string, StringValues> Headers { get; set; }
29+
public IHeaderDictionary Headers { get; set; }
3230
public Stream Body { get; set; }
3331
}
3432
}

Diff for: src/Microsoft.AspNet.Http/Features/HttpResponseFeature.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.IO;
76
using System.Threading.Tasks;
8-
using Microsoft.Extensions.Primitives;
7+
using Microsoft.AspNet.Http.Internal;
98

109
namespace Microsoft.AspNet.Http.Features.Internal
1110
{
@@ -14,15 +13,15 @@ public class HttpResponseFeature : IHttpResponseFeature
1413
public HttpResponseFeature()
1514
{
1615
StatusCode = 200;
17-
Headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
16+
Headers = new HeaderDictionary();
1817
Body = Stream.Null;
1918
}
2019

2120
public int StatusCode { get; set; }
2221

2322
public string ReasonPhrase { get; set; }
2423

25-
public IDictionary<string, StringValues> Headers { get; set; }
24+
public IHeaderDictionary Headers { get; set; }
2625

2726
public Stream Body { get; set; }
2827

Diff for: src/Microsoft.AspNet.Owin/DictionaryStringArrayWrapper.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@
44
using System.Collections;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using Microsoft.AspNet.Http;
78
using Microsoft.Extensions.Primitives;
89

910
namespace Microsoft.AspNet.Owin
1011
{
1112
internal class DictionaryStringArrayWrapper : IDictionary<string, string[]>
1213
{
13-
public DictionaryStringArrayWrapper(IDictionary<string, StringValues> inner)
14+
public DictionaryStringArrayWrapper(IHeaderDictionary inner)
1415
{
1516
Inner = inner;
1617
}
1718

18-
public readonly IDictionary<string, StringValues> Inner;
19+
public readonly IHeaderDictionary Inner;
1920

2021
private KeyValuePair<string, StringValues> Convert(KeyValuePair<string, string[]> item) => new KeyValuePair<string, StringValues>(item.Key, item.Value);
2122

@@ -27,7 +28,7 @@ public DictionaryStringArrayWrapper(IDictionary<string, StringValues> inner)
2728

2829
string[] IDictionary<string, string[]>.this[string key]
2930
{
30-
get { return Inner[key]; }
31+
get { return ((IDictionary<string, StringValues>)Inner)[key]; }
3132
set { Inner[key] = value; }
3233
}
3334

Diff for: src/Microsoft.AspNet.Owin/DictionaryStringValuesWrapper.cs

+12-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
using System.Collections;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using Microsoft.AspNet.Http;
78
using Microsoft.Extensions.Primitives;
89

910
namespace Microsoft.AspNet.Owin
1011
{
11-
internal class DictionaryStringValuesWrapper : IDictionary<string, StringValues>
12+
internal class DictionaryStringValuesWrapper : IHeaderDictionary
1213
{
1314
public DictionaryStringValuesWrapper(IDictionary<string, string[]> inner)
1415
{
@@ -25,6 +26,16 @@ public DictionaryStringValuesWrapper(IDictionary<string, string[]> inner)
2526

2627
private string[] Convert(StringValues item) => item;
2728

29+
StringValues IHeaderDictionary.this[string key]
30+
{
31+
get
32+
{
33+
string[] values;
34+
return Inner.TryGetValue(key, out values) ? values : null;
35+
}
36+
set { Inner[key] = value; }
37+
}
38+
2839
StringValues IDictionary<string, StringValues>.this[string key]
2940
{
3041
get { return Inner[key]; }

Diff for: src/Microsoft.AspNet.Owin/OwinEnvironment.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ public OwinEnvironment(HttpContext context)
5656
{ OwinConstants.RequestPath, new FeatureMap<IHttpRequestFeature>(feature => feature.Path, () => string.Empty, (feature, value) => feature.Path = Convert.ToString(value)) },
5757
{ OwinConstants.RequestQueryString, new FeatureMap<IHttpRequestFeature>(feature => Utilities.RemoveQuestionMark(feature.QueryString), () => string.Empty,
5858
(feature, value) => feature.QueryString = Utilities.AddQuestionMark(Convert.ToString(value))) },
59-
{ OwinConstants.RequestHeaders, new FeatureMap<IHttpRequestFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeDictionaryStringValues((IDictionary<string, string[]>)value)) },
59+
{ OwinConstants.RequestHeaders, new FeatureMap<IHttpRequestFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary<string, string[]>)value)) },
6060
{ OwinConstants.RequestBody, new FeatureMap<IHttpRequestFeature>(feature => feature.Body, () => Stream.Null, (feature, value) => feature.Body = (Stream)value) },
6161
{ OwinConstants.RequestUser, new FeatureMap<IHttpAuthenticationFeature>(feature => feature.User, () => null, (feature, value) => feature.User = (ClaimsPrincipal)value) },
6262

6363
{ OwinConstants.ResponseStatusCode, new FeatureMap<IHttpResponseFeature>(feature => feature.StatusCode, () => 200, (feature, value) => feature.StatusCode = Convert.ToInt32(value)) },
6464
{ OwinConstants.ResponseReasonPhrase, new FeatureMap<IHttpResponseFeature>(feature => feature.ReasonPhrase, (feature, value) => feature.ReasonPhrase = Convert.ToString(value)) },
65-
{ OwinConstants.ResponseHeaders, new FeatureMap<IHttpResponseFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeDictionaryStringValues((IDictionary<string, string[]>)value)) },
65+
{ OwinConstants.ResponseHeaders, new FeatureMap<IHttpResponseFeature>(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary<string, string[]>)value)) },
6666
{ OwinConstants.ResponseBody, new FeatureMap<IHttpResponseFeature>(feature => feature.Body, () => Stream.Null, (feature, value) => feature.Body = (Stream)value) },
6767
{ OwinConstants.CommonKeys.OnSendingHeaders, new FeatureMap<IHttpResponseFeature>(
6868
feature => new Action<Action<object>, object>((cb, state) => {

Diff for: src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ string IHttpRequestFeature.QueryString
106106
set { Prop(OwinConstants.RequestQueryString, Utilities.RemoveQuestionMark(value)); }
107107
}
108108

109-
IDictionary<string, StringValues> IHttpRequestFeature.Headers
109+
IHeaderDictionary IHttpRequestFeature.Headers
110110
{
111-
get { return Utilities.MakeDictionaryStringValues(Prop<IDictionary<string, string[]>>(OwinConstants.RequestHeaders)); }
111+
get { return Utilities.MakeHeaderDictionary(Prop<IDictionary<string, string[]>>(OwinConstants.RequestHeaders)); }
112112
set { Prop(OwinConstants.RequestHeaders, Utilities.MakeDictionaryStringArray(value)); }
113113
}
114114

@@ -136,9 +136,9 @@ string IHttpResponseFeature.ReasonPhrase
136136
set { Prop(OwinConstants.ResponseReasonPhrase, value); }
137137
}
138138

139-
IDictionary<string, StringValues> IHttpResponseFeature.Headers
139+
IHeaderDictionary IHttpResponseFeature.Headers
140140
{
141-
get { return Utilities.MakeDictionaryStringValues(Prop<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders)); }
141+
get { return Utilities.MakeHeaderDictionary(Prop<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders)); }
142142
set { Prop(OwinConstants.ResponseHeaders, Utilities.MakeDictionaryStringArray(value)); }
143143
}
144144

Diff for: src/Microsoft.AspNet.Owin/Utilities.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ internal static ClaimsPrincipal MakeClaimsPrincipal(IPrincipal principal)
4646
return new ClaimsPrincipal(principal);
4747
}
4848

49-
internal static IDictionary<string, StringValues> MakeDictionaryStringValues(IDictionary<string, string[]> dictionary)
49+
internal static IHeaderDictionary MakeHeaderDictionary(IDictionary<string, string[]> dictionary)
5050
{
5151
var wrapper = dictionary as DictionaryStringArrayWrapper;
5252
if (wrapper != null)
@@ -56,7 +56,7 @@ internal static IDictionary<string, StringValues> MakeDictionaryStringValues(IDi
5656
return new DictionaryStringValuesWrapper(dictionary);
5757
}
5858

59-
internal static IDictionary<string, string[]> MakeDictionaryStringArray(IDictionary<string, StringValues> dictionary)
59+
internal static IDictionary<string, string[]> MakeDictionaryStringArray(IHeaderDictionary dictionary)
6060
{
6161
var wrapper = dictionary as DictionaryStringValuesWrapper;
6262
if (wrapper != null)

Diff for: test/Microsoft.AspNet.Http.Extensions.Tests/ResponseExtensionTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ private class StartedResponseFeature : IHttpResponseFeature
4444

4545
public bool HasStarted { get { return true; } }
4646

47-
public IDictionary<string, StringValues> Headers { get; set; }
47+
public IHeaderDictionary Headers { get; set; }
4848

4949
public string ReasonPhrase { get; set; }
5050

Diff for: test/Microsoft.AspNet.Http.Tests/DefaultHttpRequestTests.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public void Host_GetsHostFromHeaders()
6565
// Arrange
6666
const string expected = "localhost:9001";
6767

68-
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase)
68+
var headers = new HeaderDictionary()
6969
{
7070
{ "Host", expected },
7171
};
@@ -85,7 +85,7 @@ public void Host_DecodesPunyCode()
8585
// Arrange
8686
const string expected = "löcalhöst";
8787

88-
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase)
88+
var headers = new HeaderDictionary()
8989
{
9090
{ "Host", "xn--lcalhst-90ae" },
9191
};
@@ -105,7 +105,7 @@ public void Host_EncodesPunyCode()
105105
// Arrange
106106
const string expected = "xn--lcalhst-90ae";
107107

108-
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
108+
var headers = new HeaderDictionary();
109109

110110
var request = CreateRequest(headers);
111111

@@ -188,7 +188,7 @@ public void Cookies_GetAndSet()
188188
Assert.Equal(new[] { "name2=value2" }, cookieHeaders);
189189
}
190190

191-
private static HttpRequest CreateRequest(IDictionary<string, StringValues> headers)
191+
private static HttpRequest CreateRequest(IHeaderDictionary headers)
192192
{
193193
var context = new DefaultHttpContext();
194194
context.Features.Get<IHttpRequestFeature>().Headers = headers;
@@ -217,7 +217,7 @@ private static HttpRequest GetRequestWithAcceptCharsetHeader(string acceptCharse
217217

218218
private static HttpRequest GetRequestWithHeader(string headerName, string headerValue)
219219
{
220-
var headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase);
220+
var headers = new HeaderDictionary();
221221
if (headerValue != null)
222222
{
223223
headers.Add(headerName, headerValue);

0 commit comments

Comments
 (0)