Merge pull request #722 from aspnet/release/2.1

Merge Release/2.1 into dev
This commit is contained in:
Pavel Krymets 2018-03-22 16:50:11 -07:00 committed by GitHub
commit 2f44ab1744
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 62 deletions

View File

@ -17,25 +17,11 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
/// <summary> /// <summary>
/// Reads data from the Input pipe to the user. /// Reads data from the Input pipe to the user.
/// </summary> /// </summary>
/// <param name="buffer"></param> /// <param name="memory"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) internal async Task<int> ReadAsync(Memory<byte> memory, CancellationToken cancellationToken)
{ {
// Start a task which will continuously call ReadFromIISAsync and WriteToIISAsync
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (count == 0)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
var memory = new Memory<byte>(buffer, offset, count);
StartProcessingRequestAndResponseBody(); StartProcessingRequestAndResponseBody();
while (true) while (true)
@ -46,7 +32,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
{ {
if (!readableBuffer.IsEmpty) if (!readableBuffer.IsEmpty)
{ {
var actual = Math.Min(readableBuffer.Length, count); var actual = Math.Min(readableBuffer.Length, memory.Length);
readableBuffer = readableBuffer.Slice(0, actual); readableBuffer = readableBuffer.Slice(0, actual);
readableBuffer.CopyTo(memory.Span); readableBuffer.CopyTo(memory.Span);
return (int)actual; return (int)actual;
@ -69,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
/// <param name="memory"></param> /// <param name="memory"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public Task WriteAsync(ReadOnlyMemory<byte> memory, CancellationToken cancellationToken = default(CancellationToken)) internal Task WriteAsync(ReadOnlyMemory<byte> memory, CancellationToken cancellationToken = default(CancellationToken))
{ {
// Want to keep exceptions consistent, // Want to keep exceptions consistent,
@ -90,7 +76,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
/// </summary> /// </summary>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken)) internal Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken))
{ {
if (!_hasResponseStarted) if (!_hasResponseStarted)
{ {

View File

@ -223,7 +223,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
_reasonPhrase = value; _reasonPhrase = value;
} }
} }
internal IISHttpServer Server internal IISHttpServer Server
{ {
get { return _server; } get { return _server; }
@ -333,10 +333,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
{ {
// Verifies we have sent the statuscode before writing a header // Verifies we have sent the statuscode before writing a header
var reasonPhrase = string.IsNullOrEmpty(ReasonPhrase) ? ReasonPhrases.GetReasonPhrase(StatusCode) : ReasonPhrase; var reasonPhrase = string.IsNullOrEmpty(ReasonPhrase) ? ReasonPhrases.GetReasonPhrase(StatusCode) : ReasonPhrase;
// This copies data into the underlying buffer // This copies data into the underlying buffer
NativeMethods.http_set_response_status_code(_pInProcessHandler, (ushort)StatusCode, reasonPhrase); NativeMethods.http_set_response_status_code(_pInProcessHandler, (ushort)StatusCode, reasonPhrase);
HttpResponseHeaders.IsReadOnly = true; HttpResponseHeaders.IsReadOnly = true;
foreach (var headerPair in HttpResponseHeaders) foreach (var headerPair in HttpResponseHeaders)
{ {

View File

@ -39,7 +39,9 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
public override unsafe Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) public override unsafe Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
return _httpContext.ReadAsync(buffer, offset, count, cancellationToken); var memory = new Memory<byte>(buffer, offset, count);
return _httpContext.ReadAsync(memory, cancellationToken);
} }
public override long Seek(long offset, SeekOrigin origin) public override long Seek(long offset, SeekOrigin origin)

View File

@ -54,11 +54,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
public override unsafe Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) public override unsafe Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
return _httpContext.WriteAsync(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken); return _httpContext.WriteAsync(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken);
} }

View File

@ -26,13 +26,11 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
} }
[ConditionalTheory] [ConditionalTheory]
[InlineData("/NullBuffer")]
[InlineData("/InvalidOffsetSmall")] [InlineData("/InvalidOffsetSmall")]
[InlineData("/InvalidOffsetLarge")] [InlineData("/InvalidOffsetLarge")]
[InlineData("/InvalidCountSmall")] [InlineData("/InvalidCountSmall")]
[InlineData("/InvalidCountLarge")] [InlineData("/InvalidCountLarge")]
[InlineData("/InvalidCountWithOffset")] [InlineData("/InvalidCountWithOffset")]
[InlineData("/InvalidCountZeroRead")]
public async Task TestInvalidReadOperations(string operation) public async Task TestInvalidReadOperations(string operation)
{ {
var result = await _fixture.Client.GetStringAsync($"/TestInvalidReadOperations{operation}"); var result = await _fixture.Client.GetStringAsync($"/TestInvalidReadOperations{operation}");
@ -41,6 +39,23 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[ConditionalTheory] [ConditionalTheory]
[InlineData("/NullBuffer")] [InlineData("/NullBuffer")]
[InlineData("/InvalidCountZeroRead")]
public async Task TestValidReadOperations(string operation)
{
var result = await _fixture.Client.GetStringAsync($"/TestValidReadOperations{operation}");
Assert.Equal("Success", result);
}
[ConditionalTheory]
[InlineData("/NullBufferPost")]
[InlineData("/InvalidCountZeroReadPost")]
public async Task TestValidReadOperationsPost(string operation)
{
var result = await _fixture.Client.PostAsync($"/TestValidReadOperations{operation}", new StringContent("hello"));
Assert.Equal("Success", await result.Content.ReadAsStringAsync());
}
[ConditionalTheory]
[InlineData("/InvalidOffsetSmall")] [InlineData("/InvalidOffsetSmall")]
[InlineData("/InvalidOffsetLarge")] [InlineData("/InvalidOffsetLarge")]
[InlineData("/InvalidCountSmall")] [InlineData("/InvalidCountSmall")]
@ -51,5 +66,19 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
var result = await _fixture.Client.GetStringAsync($"/TestInvalidWriteOperations{operation}"); var result = await _fixture.Client.GetStringAsync($"/TestInvalidWriteOperations{operation}");
Assert.Equal("Success", result); Assert.Equal("Success", result);
} }
[ConditionalFact]
public async Task TestValidWriteOperations()
{
var result = await _fixture.Client.GetStringAsync($"/TestValidWriteOperations/NullBuffer");
Assert.Equal("Success", result);
}
[ConditionalFact]
public async Task TestValidWriteOperationsPost()
{
var result = await _fixture.Client.PostAsync($"/TestValidWriteOperations/NullBufferPost", new StringContent("hello"));
Assert.Equal("Success", await result.Content.ReadAsStringAsync());
}
} }
} }

View File

@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal("1", headerValues.First()); Assert.Equal("1", headerValues.First());
Assert.Equal("2", headerValues.Last()); Assert.Equal("2", headerValues.Last());
} }
[ConditionalFact] [ConditionalFact]
public async Task ErrorCodeIsSetForExceptionDuringRequest() public async Task ErrorCodeIsSetForExceptionDuringRequest()
{ {

View File

@ -470,10 +470,6 @@ namespace IISTestSite
{ {
await context.Request.Body.ReadAsync(null, 0, 0); await context.Request.Body.ReadAsync(null, 0, 0);
} }
catch (ArgumentNullException)
{
success = true;
}
catch (Exception) catch (Exception)
{ {
success = true; success = true;
@ -534,42 +530,46 @@ namespace IISTestSite
success = true; success = true;
} }
} }
else if (context.Request.Path.StartsWithSegments("/InvalidCountZeroRead"))
{
try
{
await context.Request.Body.ReadAsync(new byte[1], 0, 0);
}
catch (ArgumentOutOfRangeException)
{
success = true;
}
catch (Exception)
{
success = true;
}
}
await context.Response.WriteAsync(success ? "Success" : "Failure"); await context.Response.WriteAsync(success ? "Success" : "Failure");
}); });
} }
private void TestValidReadOperations(IApplicationBuilder app)
{
app.Run(async context =>
{
var count = -1;
if (context.Request.Path.StartsWithSegments("/NullBuffer"))
{
count = await context.Request.Body.ReadAsync(null, 0, 0);
}
else if (context.Request.Path.StartsWithSegments("/NullBufferPost"))
{
count = await context.Request.Body.ReadAsync(null, 0, 0);
}
else if (context.Request.Path.StartsWithSegments("/InvalidCountZeroRead"))
{
count = await context.Request.Body.ReadAsync(new byte[1], 0, 0);
}
else if (context.Request.Path.StartsWithSegments("/InvalidCountZeroReadPost"))
{
count = await context.Request.Body.ReadAsync(new byte[1], 0, 0);
}
await context.Response.WriteAsync(count == 0 ? "Success" : "Failure");
});
}
private void TestInvalidWriteOperations(IApplicationBuilder app) private void TestInvalidWriteOperations(IApplicationBuilder app)
{ {
app.Run(async context => app.Run(async context =>
{ {
var success = false; var success = false;
if (context.Request.Path.StartsWithSegments("/NullBuffer"))
{ if (context.Request.Path.StartsWithSegments("/InvalidOffsetSmall"))
try
{
await context.Response.Body.WriteAsync(null, 0, 0);
}
catch (ArgumentNullException)
{
success = true;
}
}
else if (context.Request.Path.StartsWithSegments("/InvalidOffsetSmall"))
{ {
try try
{ {
@ -629,6 +629,24 @@ namespace IISTestSite
}); });
} }
private void TestValidWriteOperations(IApplicationBuilder app)
{
app.Run(async context =>
{
if (context.Request.Path.StartsWithSegments("/NullBuffer"))
{
await context.Response.Body.WriteAsync(null, 0, 0);
}
else if (context.Request.Path.StartsWithSegments("/NullBufferPost"))
{
await context.Response.Body.WriteAsync(null, 0, 0);
}
await context.Response.WriteAsync("Success");
});
}
private void LargeResponseFile(IApplicationBuilder app) private void LargeResponseFile(IApplicationBuilder app)
{ {
app.Run(async ctx => app.Run(async ctx =>