Skip to content
This repository was archived by the owner on Mar 19, 2019. It is now read-only.

Commit 3b42433

Browse files
committed
Handle null valued headers #158
1 parent 94dd583 commit 3b42433

File tree

2 files changed

+62
-15
lines changed

2 files changed

+62
-15
lines changed

src/Microsoft.Net.Http.Server/RequestProcessing/Response.cs

+9-14
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,6 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
575575
{
576576
if (headerPair.Value.Count == 0)
577577
{
578-
// TODO: Have the collection exclude empty headers.
579578
continue;
580579
}
581580
// See if this is an unknown header
@@ -602,7 +601,6 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
602601
{
603602
if (headerPair.Value.Count == 0)
604603
{
605-
// TODO: Have the collection exclude empty headers.
606604
continue;
607605
}
608606
headerName = headerPair.Key;
@@ -632,7 +630,7 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
632630
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].pName = (sbyte*)gcHandle.AddrOfPinnedObject();
633631

634632
// Add Value
635-
headerValue = headerValues[headerValueIndex];
633+
headerValue = headerValues[headerValueIndex] ?? string.Empty;
636634
bytes = new byte[HeaderEncoding.GetByteCount(headerValue)];
637635
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].RawValueLength = (ushort)bytes.Length;
638636
HeaderEncoding.GetBytes(headerValue, 0, bytes.Length, bytes, 0);
@@ -644,16 +642,13 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
644642
}
645643
else if (headerPair.Value.Count == 1)
646644
{
647-
headerValue = headerValues[0];
648-
if (headerValue != null)
649-
{
650-
bytes = new byte[HeaderEncoding.GetByteCount(headerValue)];
651-
pKnownHeaders[lookup].RawValueLength = (ushort)bytes.Length;
652-
HeaderEncoding.GetBytes(headerValue, 0, bytes.Length, bytes, 0);
653-
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
654-
pinnedHeaders.Add(gcHandle);
655-
pKnownHeaders[lookup].pRawValue = (sbyte*)gcHandle.AddrOfPinnedObject();
656-
}
645+
headerValue = headerValues[0] ?? string.Empty;
646+
bytes = new byte[HeaderEncoding.GetByteCount(headerValue)];
647+
pKnownHeaders[lookup].RawValueLength = (ushort)bytes.Length;
648+
HeaderEncoding.GetBytes(headerValue, 0, bytes.Length, bytes, 0);
649+
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
650+
pinnedHeaders.Add(gcHandle);
651+
pKnownHeaders[lookup].pRawValue = (sbyte*)gcHandle.AddrOfPinnedObject();
657652
}
658653
else
659654
{
@@ -681,7 +676,7 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
681676
for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++)
682677
{
683678
// Add Value
684-
headerValue = headerValues[headerValueIndex];
679+
headerValue = headerValues[headerValueIndex] ?? string.Empty;
685680
bytes = new byte[HeaderEncoding.GetByteCount(headerValue)];
686681
nativeHeaderValues[header.KnownHeaderCount].RawValueLength = (ushort)bytes.Length;
687682
HeaderEncoding.GetBytes(headerValue, 0, bytes.Length, bytes, 0);

test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseHeaderTests.cs

+53-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
using System.Text;
2424
using System.Threading.Tasks;
2525
using Microsoft.AspNet.Http.Features;
26-
using Microsoft.AspNet.Http.Internal;
26+
using Microsoft.Extensions.Primitives;
2727
using Xunit;
2828

2929
namespace Microsoft.AspNet.Server.WebListener
@@ -259,6 +259,58 @@ public async Task Headers_FlushAsyncSendsHeaders_Success()
259259
}
260260
}
261261

262+
[Theory, MemberData(nameof(NullHeaderData))]
263+
public async Task Headers_IgnoreNullHeaders(string headerName, StringValues headerValue, StringValues expectedValue)
264+
{
265+
string address;
266+
using (Utilities.CreateHttpServer(out address, httpContext =>
267+
{
268+
var responseHeaders = httpContext.Response.Headers;
269+
responseHeaders.Add(headerName, headerValue);
270+
return Task.FromResult(0);
271+
}))
272+
{
273+
HttpResponseMessage response = await SendRequestAsync(address);
274+
response.EnsureSuccessStatusCode();
275+
var headers = response.Headers;
276+
277+
if (expectedValue.Count == 0)
278+
{
279+
Assert.False(headers.Contains(headerName));
280+
}
281+
else
282+
{
283+
Assert.True(headers.Contains(headerName));
284+
Assert.Equal(headers.GetValues(headerName), expectedValue);
285+
}
286+
}
287+
}
288+
289+
public static TheoryData<string, StringValues, StringValues> NullHeaderData
290+
{
291+
get
292+
{
293+
var dataset = new TheoryData<string, StringValues, StringValues>();
294+
295+
// Unknown headers
296+
dataset.Add("NullString", (string)null, (string)null);
297+
dataset.Add("EmptyString", "", "");
298+
dataset.Add("NullStringArray", new string[] { null }, "");
299+
dataset.Add("EmptyStringArray", new string[] { "" }, "");
300+
dataset.Add("MixedStringArray", new string[] { null, "" }, new string[] { "", "" });
301+
// Known headers
302+
dataset.Add("Location", (string)null, (string)null);
303+
dataset.Add("Location", "", (string)null);
304+
dataset.Add("Location", new string[] { null }, (string)null);
305+
dataset.Add("Location", new string[] { "" }, (string)null);
306+
dataset.Add("Location", new string[] { "a" }, "a");
307+
dataset.Add("Location", new string[] { null, "" }, (string)null);
308+
dataset.Add("Location", new string[] { null, "", "a", "b" }, new string[] { "a", "b" });
309+
310+
return dataset;
311+
}
312+
}
313+
262314
private async Task<HttpResponseMessage> SendRequestAsync(string uri)
263315
{
264316
using (HttpClient client = new HttpClient())

0 commit comments

Comments
 (0)