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

Commit ce7dd83

Browse files
committed
Ignore null valued headers #158
1 parent f33ce78 commit ce7dd83

File tree

2 files changed

+79
-24
lines changed

2 files changed

+79
-24
lines changed

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

+27-23
Original file line numberDiff line numberDiff line change
@@ -573,21 +573,16 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
573573
int numKnownMultiHeaders = 0;
574574
foreach (var headerPair in Headers)
575575
{
576-
if (headerPair.Value.Count == 0)
577-
{
578-
// TODO: Have the collection exclude empty headers.
579-
continue;
580-
}
581576
// See if this is an unknown header
582577
lookup = HttpApi.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerPair.Key);
583578

584579
// Http.Sys doesn't let us send the Connection: Upgrade header as a Known header.
585580
if (lookup == -1 ||
586581
(isOpaqueUpgrade && lookup == (int)HttpApi.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderConnection))
587582
{
588-
numUnknownHeaders += headerPair.Value.Count;
583+
numUnknownHeaders += headerPair.Value.Where(s => s != null).Count();
589584
}
590-
else if (headerPair.Value.Count > 1)
585+
else if (headerPair.Value.Where(s => !string.IsNullOrEmpty(s)).Count() > 1)
591586
{
592587
numKnownMultiHeaders++;
593588
}
@@ -600,11 +595,11 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
600595
{
601596
foreach (var headerPair in Headers)
602597
{
603-
if (headerPair.Value.Count == 0)
598+
if (headerPair.Value.Where(s => s != null).Count() == 0)
604599
{
605-
// TODO: Have the collection exclude empty headers.
606600
continue;
607601
}
602+
608603
headerName = headerPair.Key;
609604
StringValues headerValues = headerPair.Value;
610605
lookup = HttpApi.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerName);
@@ -623,6 +618,13 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
623618

624619
for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++)
625620
{
621+
headerValue = headerValues[headerValueIndex];
622+
623+
if (headerValue == null)
624+
{
625+
continue;
626+
}
627+
626628
// Add Name
627629
bytes = new byte[HeaderEncoding.GetByteCount(headerName)];
628630
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].NameLength = (ushort)bytes.Length;
@@ -632,7 +634,6 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
632634
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].pName = (sbyte*)gcHandle.AddrOfPinnedObject();
633635

634636
// Add Value
635-
headerValue = headerValues[headerValueIndex];
636637
bytes = new byte[HeaderEncoding.GetByteCount(headerValue)];
637638
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].RawValueLength = (ushort)bytes.Length;
638639
HeaderEncoding.GetBytes(headerValue, 0, bytes.Length, bytes, 0);
@@ -642,20 +643,17 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
642643
_nativeResponse.Response_V1.Headers.UnknownHeaderCount++;
643644
}
644645
}
645-
else if (headerPair.Value.Count == 1)
646+
else if (headerPair.Value.Where(s => !string.IsNullOrEmpty(s)).Count() == 1)
646647
{
647648
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-
}
649+
bytes = new byte[HeaderEncoding.GetByteCount(headerValue)];
650+
pKnownHeaders[lookup].RawValueLength = (ushort)bytes.Length;
651+
HeaderEncoding.GetBytes(headerValue, 0, bytes.Length, bytes, 0);
652+
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
653+
pinnedHeaders.Add(gcHandle);
654+
pKnownHeaders[lookup].pRawValue = (sbyte*)gcHandle.AddrOfPinnedObject();
657655
}
658-
else
656+
else if(headerPair.Value.Where(s => !string.IsNullOrEmpty(s)).Count() > 1)
659657
{
660658
if (knownHeaderInfo == null)
661659
{
@@ -673,15 +671,21 @@ private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
673671
header.HeaderId = (HttpApi.HTTP_RESPONSE_HEADER_ID.Enum)lookup;
674672
header.Flags = HttpApi.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // TODO: The docs say this is for www-auth only.
675673

676-
HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApi.HTTP_KNOWN_HEADER[headerValues.Count];
674+
HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApi.HTTP_KNOWN_HEADER[headerValues.Where(s => s != null).Count()];
677675
gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned);
678676
pinnedHeaders.Add(gcHandle);
679677
header.KnownHeaders = (HttpApi.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject();
680678

681679
for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++)
682680
{
683-
// Add Value
684681
headerValue = headerValues[headerValueIndex];
682+
683+
if (string.IsNullOrEmpty(headerValue))
684+
{
685+
continue;
686+
}
687+
688+
// Add Valuegit
685689
bytes = new byte[HeaderEncoding.GetByteCount(headerValue)];
686690
nativeHeaderValues[header.KnownHeaderCount].RawValueLength = (ushort)bytes.Length;
687691
HeaderEncoding.GetBytes(headerValue, 0, bytes.Length, bytes, 0);

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

+52-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,57 @@ public async Task Headers_FlushAsyncSendsHeaders_Success()
259259
}
260260
}
261261

262+
[Theory, MemberData(nameof(NullHeaderData))]
263+
public async Task Headers_IgnoreNullHeaders(string headerName, StringValues headerValue, string 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 == null)
278+
{
279+
Assert.False(headers.Contains(headerName));
280+
}
281+
else
282+
{
283+
Assert.True(headers.Contains(headerName));
284+
Assert.Equal(headers.GetValues(headerName).Single(), expectedValue);
285+
}
286+
}
287+
}
288+
289+
public static TheoryData<string, StringValues, string> NullHeaderData
290+
{
291+
get
292+
{
293+
var dataset = new TheoryData<string, StringValues, string>();
294+
295+
// Unknown headers
296+
dataset.Add("NullString", (string)null, null);
297+
dataset.Add("EmptyString", "", "");
298+
dataset.Add("NullStringArray", new string[] { null }, null);
299+
dataset.Add("EmptyStringArray", new string[] { "" }, "");
300+
dataset.Add("MixedStringArray", new string[] { null, "" }, "");
301+
// Known headers
302+
dataset.Add("Location", (string)null, null);
303+
dataset.Add("Location", "", null);
304+
dataset.Add("Location", new string[] { null }, null);
305+
dataset.Add("Location", new string[] { "" }, null);
306+
dataset.Add("Location", new string[] { null, "" }, null);
307+
dataset.Add("Location", new string[] { null, "", "" }, null);
308+
309+
return dataset;
310+
}
311+
}
312+
262313
private async Task<HttpResponseMessage> SendRequestAsync(string uri)
263314
{
264315
using (HttpClient client = new HttpClient())

0 commit comments

Comments
 (0)