Ignore null valued headers #429

This commit is contained in:
John Luo 2015-12-08 16:16:07 -08:00
parent 3e2c090d7c
commit fd33475c05
4 changed files with 234 additions and 67 deletions

View File

@ -7827,11 +7827,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
if (((_bits & 1L) != 0)) if (((_bits & 1L) != 0))
{ {
foreach(var value in _CacheControl) foreach(var value in _CacheControl)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 0, 17); output.CopyFrom(_headerBytes, 0, 17);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 2L) != 0)) if (((_bits & 2L) != 0))
{ {
@ -7840,11 +7843,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
output.CopyFrom(_rawConnection, 0, _rawConnection.Length); output.CopyFrom(_rawConnection, 0, _rawConnection.Length);
} else } else
foreach(var value in _Connection) foreach(var value in _Connection)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 17, 14); output.CopyFrom(_headerBytes, 17, 14);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 4L) != 0)) if (((_bits & 4L) != 0))
{ {
@ -7853,38 +7859,50 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
output.CopyFrom(_rawDate, 0, _rawDate.Length); output.CopyFrom(_rawDate, 0, _rawDate.Length);
} else } else
foreach(var value in _Date) foreach(var value in _Date)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 31, 8); output.CopyFrom(_headerBytes, 31, 8);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 8L) != 0)) if (((_bits & 8L) != 0))
{ {
foreach(var value in _KeepAlive) foreach(var value in _KeepAlive)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 39, 14); output.CopyFrom(_headerBytes, 39, 14);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 16L) != 0)) if (((_bits & 16L) != 0))
{ {
foreach(var value in _Pragma) foreach(var value in _Pragma)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 53, 10); output.CopyFrom(_headerBytes, 53, 10);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 32L) != 0)) if (((_bits & 32L) != 0))
{ {
foreach(var value in _Trailer) foreach(var value in _Trailer)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 63, 11); output.CopyFrom(_headerBytes, 63, 11);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 64L) != 0)) if (((_bits & 64L) != 0))
{ {
@ -7893,47 +7911,62 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length); output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length);
} else } else
foreach(var value in _TransferEncoding) foreach(var value in _TransferEncoding)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 74, 21); output.CopyFrom(_headerBytes, 74, 21);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 128L) != 0)) if (((_bits & 128L) != 0))
{ {
foreach(var value in _Upgrade) foreach(var value in _Upgrade)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 95, 11); output.CopyFrom(_headerBytes, 95, 11);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 256L) != 0)) if (((_bits & 256L) != 0))
{ {
foreach(var value in _Via) foreach(var value in _Via)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 106, 7); output.CopyFrom(_headerBytes, 106, 7);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 512L) != 0)) if (((_bits & 512L) != 0))
{ {
foreach(var value in _Warning) foreach(var value in _Warning)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 113, 11); output.CopyFrom(_headerBytes, 113, 11);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 1024L) != 0)) if (((_bits & 1024L) != 0))
{ {
foreach(var value in _Allow) foreach(var value in _Allow)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 124, 9); output.CopyFrom(_headerBytes, 124, 9);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 2048L) != 0)) if (((_bits & 2048L) != 0))
{ {
@ -7942,137 +7975,182 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length); output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length);
} else } else
foreach(var value in _ContentLength) foreach(var value in _ContentLength)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 133, 18); output.CopyFrom(_headerBytes, 133, 18);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 4096L) != 0)) if (((_bits & 4096L) != 0))
{ {
foreach(var value in _ContentType) foreach(var value in _ContentType)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 151, 16); output.CopyFrom(_headerBytes, 151, 16);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 8192L) != 0)) if (((_bits & 8192L) != 0))
{ {
foreach(var value in _ContentEncoding) foreach(var value in _ContentEncoding)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 167, 20); output.CopyFrom(_headerBytes, 167, 20);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 16384L) != 0)) if (((_bits & 16384L) != 0))
{ {
foreach(var value in _ContentLanguage) foreach(var value in _ContentLanguage)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 187, 20); output.CopyFrom(_headerBytes, 187, 20);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 32768L) != 0)) if (((_bits & 32768L) != 0))
{ {
foreach(var value in _ContentLocation) foreach(var value in _ContentLocation)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 207, 20); output.CopyFrom(_headerBytes, 207, 20);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 65536L) != 0)) if (((_bits & 65536L) != 0))
{ {
foreach(var value in _ContentMD5) foreach(var value in _ContentMD5)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 227, 15); output.CopyFrom(_headerBytes, 227, 15);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 131072L) != 0)) if (((_bits & 131072L) != 0))
{ {
foreach(var value in _ContentRange) foreach(var value in _ContentRange)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 242, 17); output.CopyFrom(_headerBytes, 242, 17);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 262144L) != 0)) if (((_bits & 262144L) != 0))
{ {
foreach(var value in _Expires) foreach(var value in _Expires)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 259, 11); output.CopyFrom(_headerBytes, 259, 11);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 524288L) != 0)) if (((_bits & 524288L) != 0))
{ {
foreach(var value in _LastModified) foreach(var value in _LastModified)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 270, 17); output.CopyFrom(_headerBytes, 270, 17);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 1048576L) != 0)) if (((_bits & 1048576L) != 0))
{ {
foreach(var value in _AcceptRanges) foreach(var value in _AcceptRanges)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 287, 17); output.CopyFrom(_headerBytes, 287, 17);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 2097152L) != 0)) if (((_bits & 2097152L) != 0))
{ {
foreach(var value in _Age) foreach(var value in _Age)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 304, 7); output.CopyFrom(_headerBytes, 304, 7);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 4194304L) != 0)) if (((_bits & 4194304L) != 0))
{ {
foreach(var value in _ETag) foreach(var value in _ETag)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 311, 8); output.CopyFrom(_headerBytes, 311, 8);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 8388608L) != 0)) if (((_bits & 8388608L) != 0))
{ {
foreach(var value in _Location) foreach(var value in _Location)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 319, 12); output.CopyFrom(_headerBytes, 319, 12);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 16777216L) != 0)) if (((_bits & 16777216L) != 0))
{ {
foreach(var value in _ProxyAutheticate) foreach(var value in _ProxyAutheticate)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 331, 21); output.CopyFrom(_headerBytes, 331, 21);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 33554432L) != 0)) if (((_bits & 33554432L) != 0))
{ {
foreach(var value in _RetryAfter) foreach(var value in _RetryAfter)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 352, 15); output.CopyFrom(_headerBytes, 352, 15);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 67108864L) != 0)) if (((_bits & 67108864L) != 0))
{ {
@ -8081,38 +8159,50 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
output.CopyFrom(_rawServer, 0, _rawServer.Length); output.CopyFrom(_rawServer, 0, _rawServer.Length);
} else } else
foreach(var value in _Server) foreach(var value in _Server)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 367, 10); output.CopyFrom(_headerBytes, 367, 10);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 134217728L) != 0)) if (((_bits & 134217728L) != 0))
{ {
foreach(var value in _SetCookie) foreach(var value in _SetCookie)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 377, 14); output.CopyFrom(_headerBytes, 377, 14);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 268435456L) != 0)) if (((_bits & 268435456L) != 0))
{ {
foreach(var value in _Vary) foreach(var value in _Vary)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 391, 8); output.CopyFrom(_headerBytes, 391, 8);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
if (((_bits & 536870912L) != 0)) if (((_bits & 536870912L) != 0))
{ {
foreach(var value in _WWWAuthenticate) foreach(var value in _WWWAuthenticate)
{
if (value != null)
{ {
output.CopyFrom(_headerBytes, 399, 20); output.CopyFrom(_headerBytes, 399, 20);
output.CopyFromAscii(value); output.CopyFromAscii(value);
} }
} }
}
} }
public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value)

View File

@ -38,6 +38,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
foreach (var kv in MaybeUnknown) foreach (var kv in MaybeUnknown)
{ {
foreach (var value in kv.Value) foreach (var value in kv.Value)
{
if (value != null)
{ {
output.CopyFrom(_CrLf, 0, 2); output.CopyFrom(_CrLf, 0, 2);
output.CopyFromAscii(kv.Key); output.CopyFromAscii(kv.Key);
@ -47,6 +49,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
} }
} }
} }
}
public partial struct Enumerator : IEnumerator<KeyValuePair<string, StringValues>> public partial struct Enumerator : IEnumerator<KeyValuePair<string, StringValues>>
{ {

View File

@ -2,12 +2,15 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Testing.xunit; using Microsoft.AspNet.Testing.xunit;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.Kestrel.FunctionalTests namespace Microsoft.AspNet.Server.Kestrel.FunctionalTests
@ -70,5 +73,73 @@ namespace Microsoft.AspNet.Server.Kestrel.FunctionalTests
} }
} }
} }
[ConditionalTheory, MemberData(nameof(NullHeaderData))]
[FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Test hangs after execution on mono.")]
public async Task IgnoreNullHeaderValues(string headerName, StringValues headerValue, string expectedValue)
{
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
{ "server.urls", "http://localhost:8793/" }
})
.Build();
var hostBuilder = new WebHostBuilder(config)
.UseServerFactory("Microsoft.AspNet.Server.Kestrel")
.UseStartup(app =>
{
app.Run(async context =>
{
context.Response.Headers.Add(headerName, headerValue);
await context.Response.WriteAsync("");
});
});
using (var app = hostBuilder.Build().Start())
{
using (var client = new HttpClient())
{
var response = await client.GetAsync("http://localhost:8793/");
response.EnsureSuccessStatusCode();
var headers = response.Headers;
if (expectedValue == null)
{
Assert.False(headers.Contains(headerName));
}
else
{
Assert.True(headers.Contains(headerName));
Assert.Equal(headers.GetValues(headerName).Single(), expectedValue);
}
}
}
}
public static TheoryData<string, StringValues, string> NullHeaderData
{
get
{
var dataset = new TheoryData<string, StringValues, string>();
// Unknown headers
dataset.Add("NullString", (string)null, null);
dataset.Add("EmptyString", "", "");
dataset.Add("NullStringArray", new string[] { null }, null);
dataset.Add("EmptyStringArray", new string[] { "" }, "");
dataset.Add("MixedStringArray", new string[] { null, "" }, "");
// Known headers
dataset.Add("Location", (string)null, null);
dataset.Add("Location", "", "");
dataset.Add("Location", new string[] { null }, null);
dataset.Add("Location", new string[] { "" }, "");
dataset.Add("Location", new string[] { null, "" }, "");
return dataset;
}
}
} }
} }

View File

@ -390,11 +390,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
output.CopyFrom(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length); output.CopyFrom(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length);
}} else ")} }} else ")}
foreach(var value in _{header.Identifier}) foreach(var value in _{header.Identifier})
{{
if (value != null)
{{ {{
output.CopyFrom(_headerBytes, {header.BytesOffset}, {header.BytesCount}); output.CopyFrom(_headerBytes, {header.BytesOffset}, {header.BytesCount});
output.CopyFromAscii(value); output.CopyFromAscii(value);
}} }}
}} }}
}}
")} ")}
}}" : "")} }}" : "")}
public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value)