Allow Content-Length 0 for Websocket-Connection (#2217)

This commit is contained in:
Steffen Forkmann 2018-01-10 00:01:09 +01:00 committed by Chris Ross
parent 7fde08d6fb
commit 9a8dd6ef12
2 changed files with 36 additions and 14 deletions

View File

@ -230,6 +230,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
keepAlive = (connectionOptions & ConnectionOptions.KeepAlive) == ConnectionOptions.KeepAlive;
}
if (upgrade)
{
if (headers.HeaderTransferEncoding.Count > 0 || (headers.ContentLength.HasValue && headers.ContentLength.Value != 0))
{
context.ThrowRequestRejected(RequestRejectionReason.UpgradeRequestCannotHavePayload);
}
return new ForUpgrade(context);
}
var transferEncoding = headers.HeaderTransferEncoding;
if (transferEncoding.Count > 0)
{
@ -246,11 +256,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
context.ThrowRequestRejected(RequestRejectionReason.FinalTransferCodingNotChunked, transferEncoding.ToString());
}
if (upgrade)
{
context.ThrowRequestRejected(RequestRejectionReason.UpgradeRequestCannotHavePayload);
}
return new ForChunkedEncoding(keepAlive, context);
}
@ -262,10 +267,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
return keepAlive ? MessageBody.ZeroContentLengthKeepAlive : MessageBody.ZeroContentLengthClose;
}
else if (upgrade)
{
context.ThrowRequestRejected(RequestRejectionReason.UpgradeRequestCannotHavePayload);
}
return new ForContentLength(keepAlive, contentLength, context);
}
@ -282,11 +283,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
}
}
if (upgrade)
{
return new ForUpgrade(context);
}
return keepAlive ? MessageBody.ZeroContentLengthKeepAlive : MessageBody.ZeroContentLengthClose;
}

View File

@ -503,6 +503,32 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
}
[Fact]
public async Task UpgradeConnectionAcceptsContentLengthZero()
{
// https://tools.ietf.org/html/rfc7230#section-3.3.2
// "A user agent SHOULD NOT send a Content-Length header field when the request message does not contain
// a payload body and the method semantics do not anticipate such a body."
// ==> it can actually send that header
var headerConnection = "Upgrade, Keep-Alive";
using (var input = new TestInput())
{
var body = Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders { HeaderConnection = headerConnection, ContentLength = 0 }, input.Http1Connection);
var stream = new HttpRequestStream(Mock.Of<IHttpBodyControlFeature>());
stream.StartAcceptingReads(body);
input.Add("Hello");
var buffer = new byte[1024];
Assert.Equal(5, await stream.ReadAsync(buffer, 0, buffer.Length));
AssertASCII("Hello", new ArraySegment<byte>(buffer, 0, 5));
input.Fin();
await body.StopAsync();
}
}
[Fact]
public async Task PumpAsyncDoesNotReturnAfterCancelingInput()
{