Implement Begin/End Read/Write methods in LoggingStream
- This allows the reads and writes from SslStream to be logged on desktop .NET
This commit is contained in:
parent
0d559468f1
commit
194059a198
|
|
@ -1,6 +1,7 @@
|
||||||
// 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 System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
@ -125,5 +126,84 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Filter.Internal
|
||||||
|
|
||||||
_logger.LogDebug(builder.ToString());
|
_logger.LogDebug(builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NET451
|
||||||
|
// The below APM methods call the underlying Read/WriteAsync methods which will still be logged.
|
||||||
|
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||||
|
{
|
||||||
|
var task = ReadAsync(buffer, offset, count, default(CancellationToken), state);
|
||||||
|
if (callback != null)
|
||||||
|
{
|
||||||
|
task.ContinueWith(t => callback.Invoke(t));
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int EndRead(IAsyncResult asyncResult)
|
||||||
|
{
|
||||||
|
return ((Task<int>)asyncResult).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, object state)
|
||||||
|
{
|
||||||
|
var tcs = new TaskCompletionSource<int>(state);
|
||||||
|
var task = ReadAsync(buffer, offset, count, cancellationToken);
|
||||||
|
task.ContinueWith((task2, state2) =>
|
||||||
|
{
|
||||||
|
var tcs2 = (TaskCompletionSource<int>)state2;
|
||||||
|
if (task2.IsCanceled)
|
||||||
|
{
|
||||||
|
tcs2.SetCanceled();
|
||||||
|
}
|
||||||
|
else if (task2.IsFaulted)
|
||||||
|
{
|
||||||
|
tcs2.SetException(task2.Exception);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcs2.SetResult(task2.Result);
|
||||||
|
}
|
||||||
|
}, tcs, cancellationToken);
|
||||||
|
return tcs.Task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||||
|
{
|
||||||
|
var task = WriteAsync(buffer, offset, count, default(CancellationToken), state);
|
||||||
|
if (callback != null)
|
||||||
|
{
|
||||||
|
task.ContinueWith(t => callback.Invoke(t));
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void EndWrite(IAsyncResult asyncResult)
|
||||||
|
{
|
||||||
|
((Task<object>)asyncResult).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, object state)
|
||||||
|
{
|
||||||
|
var tcs = new TaskCompletionSource<object>(state);
|
||||||
|
var task = WriteAsync(buffer, offset, count, cancellationToken);
|
||||||
|
task.ContinueWith((task2, state2) =>
|
||||||
|
{
|
||||||
|
var tcs2 = (TaskCompletionSource<object>)state2;
|
||||||
|
if (task2.IsCanceled)
|
||||||
|
{
|
||||||
|
tcs2.SetCanceled();
|
||||||
|
}
|
||||||
|
else if (task2.IsFaulted)
|
||||||
|
{
|
||||||
|
tcs2.SetException(task2.Exception);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcs2.SetResult(null);
|
||||||
|
}
|
||||||
|
}, tcs, cancellationToken);
|
||||||
|
return tcs.Task;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||||
|
{
|
||||||
|
public class LoggingConnectionFilterTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task LoggingConnectionFilterCanBeAddedBeforeAndAfterHttpsFilter()
|
||||||
|
{
|
||||||
|
var host = new WebHostBuilder()
|
||||||
|
.UseUrls($"https://127.0.0.1:0")
|
||||||
|
.UseKestrel(options =>
|
||||||
|
{
|
||||||
|
options.UseConnectionLogging();
|
||||||
|
options.UseHttps(@"TestResources/testCert.pfx", "testPassword");
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.Run(context =>
|
||||||
|
{
|
||||||
|
context.Response.ContentLength = 12;
|
||||||
|
return context.Response.WriteAsync("Hello World!");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
using (host)
|
||||||
|
{
|
||||||
|
host.Start();
|
||||||
|
|
||||||
|
var response = await HttpClientSlim.GetStringAsync($"https://localhost:{host.GetPort()}/", validateCertificate: false)
|
||||||
|
.TimeoutAfter(TimeSpan.FromSeconds(10));
|
||||||
|
|
||||||
|
Assert.Equal("Hello World!", response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,19 +88,12 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||||
{
|
{
|
||||||
using (var connection = server.CreateConnection())
|
using (var connection = server.CreateConnection())
|
||||||
{
|
{
|
||||||
try
|
// Will throw because the exception in the connection filter will close the connection.
|
||||||
{
|
await Assert.ThrowsAsync<IOException>(async () => await connection.SendEnd(
|
||||||
await connection.SendEnd(
|
"POST / HTTP/1.0",
|
||||||
"POST / HTTP/1.0",
|
"Content-Length: 12",
|
||||||
"Content-Length: 12",
|
"",
|
||||||
"",
|
"Hello World?"));
|
||||||
"Hello World?");
|
|
||||||
}
|
|
||||||
catch (IOException)
|
|
||||||
{
|
|
||||||
// Will throw because the exception in the connection filter will close the connection.
|
|
||||||
Assert.True(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel;
|
using Microsoft.AspNetCore.Server.Kestrel;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.KestrelTests.TestHelpers;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Filter.Internal;
|
||||||
using Microsoft.AspNetCore.Testing;
|
using Microsoft.AspNetCore.Testing;
|
||||||
using Microsoft.Extensions.Internal;
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers
|
||||||
{
|
{
|
||||||
|
|
||||||
public class PassThroughConnectionFilter : IConnectionFilter
|
public class PassThroughConnectionFilter : IConnectionFilter
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue