Properly handle headers with empty values
This commit is contained in:
parent
52f4fa91e3
commit
094b8efbf8
|
|
@ -157,7 +157,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!terminated && !_requestProcessingStopping && !TakeMessageHeaders(SocketInput))
|
while (!terminated && !_requestProcessingStopping && !TakeMessageHeaders(SocketInput, _requestHeaders))
|
||||||
{
|
{
|
||||||
terminated = SocketInput.RemoteIntakeFin;
|
terminated = SocketInput.RemoteIntakeFin;
|
||||||
if (!terminated)
|
if (!terminated)
|
||||||
|
|
@ -654,7 +654,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
return Encoding.UTF8.GetString(range.Array, range.Offset + startIndex, endIndex - startIndex);
|
return Encoding.UTF8.GetString(range.Array, range.Offset + startIndex, endIndex - startIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TakeMessageHeaders(SocketInput input)
|
public static bool TakeMessageHeaders(SocketInput input, FrameRequestHeaders requestHeaders)
|
||||||
{
|
{
|
||||||
var scan = input.ConsumingStart();
|
var scan = input.ConsumingStart();
|
||||||
var consumed = scan;
|
var consumed = scan;
|
||||||
|
|
@ -692,6 +692,22 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
chSecond == '\r' ||
|
chSecond == '\r' ||
|
||||||
chSecond == '\n')
|
chSecond == '\n')
|
||||||
{
|
{
|
||||||
|
if (chSecond == '\r')
|
||||||
|
{
|
||||||
|
var scanAhead = scan;
|
||||||
|
var chAhead = scanAhead.Take();
|
||||||
|
if (chAhead == '\n')
|
||||||
|
{
|
||||||
|
chAhead = scanAhead.Take();
|
||||||
|
// If the "\r\n" isn't part of "linear whitespace",
|
||||||
|
// then this header has no value.
|
||||||
|
if (chAhead != ' ' && chAhead != '\t')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
beginValue = scan;
|
beginValue = scan;
|
||||||
chSecond = scan.Take();
|
chSecond = scan.Take();
|
||||||
}
|
}
|
||||||
|
|
@ -729,9 +745,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = beginName.GetArraySegment(endName);
|
var name = beginName.GetArraySegment(endName);
|
||||||
#if DEBUG
|
|
||||||
var nameString = beginName.GetString(endName);
|
|
||||||
#endif
|
|
||||||
var value = beginValue.GetString(endValue);
|
var value = beginValue.GetString(endValue);
|
||||||
if (wrapping)
|
if (wrapping)
|
||||||
{
|
{
|
||||||
|
|
@ -739,7 +752,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = scan;
|
consumed = scan;
|
||||||
_requestHeaders.Append(name.Array, name.Offset, name.Count, value);
|
requestHeaders.Append(name.Array, name.Offset, name.Count, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNet.Server.Kestrel.Http;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||||
|
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.KestrelTests
|
namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
|
|
@ -34,5 +36,34 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
|
|
||||||
Assert.Equal(Encoding.ASCII.GetBytes(expected), beginChunkBytes.ToArray());
|
Assert.Equal(Encoding.ASCII.GetBytes(expected), beginChunkBytes.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("Cookie: \r\n\r\n", 1)]
|
||||||
|
[InlineData("Cookie:\r\n\r\n", 1)]
|
||||||
|
[InlineData("Cookie:\r\n value\r\n\r\n", 1)]
|
||||||
|
[InlineData("Cookie\r\n", 0)]
|
||||||
|
[InlineData("Cookie: \r\nConnection: close\r\n\r\n", 2)]
|
||||||
|
[InlineData("Connection: close\r\nCookie: \r\n\r\n", 2)]
|
||||||
|
[InlineData("Connection: close\r\nCookie \r\n", 1)]
|
||||||
|
[InlineData("Connection:\r\n \r\nCookie \r\n", 1)]
|
||||||
|
public void EmptyHeaderValuesCanBeParsed(string rawHeaders, int numHeaders)
|
||||||
|
{
|
||||||
|
var socketInput = new SocketInput(new MemoryPool2());
|
||||||
|
var headerCollection = new FrameRequestHeaders();
|
||||||
|
|
||||||
|
var headerArray = Encoding.ASCII.GetBytes(rawHeaders);
|
||||||
|
var inputBuffer = socketInput.IncomingStart(headerArray.Length);
|
||||||
|
Buffer.BlockCopy(headerArray, 0, inputBuffer.Data.Array, inputBuffer.Data.Offset, headerArray.Length);
|
||||||
|
socketInput.IncomingComplete(headerArray.Length, null);
|
||||||
|
|
||||||
|
var success = Frame.TakeMessageHeaders(socketInput, headerCollection);
|
||||||
|
|
||||||
|
Assert.True(success);
|
||||||
|
Assert.Equal(numHeaders, headerCollection.Count());
|
||||||
|
|
||||||
|
// Assert TakeMessageHeaders consumed all the input
|
||||||
|
var scan = socketInput.ConsumingStart();
|
||||||
|
Assert.True(scan.IsEnd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue