diff --git a/.github/workflows/build-natives.yaml b/.github/workflows/build-natives.yaml index d6a8659..3afd5b1 100644 --- a/.github/workflows/build-natives.yaml +++ b/.github/workflows/build-natives.yaml @@ -49,6 +49,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - uses: Cysharp/Actions/.github/actions/setup-dotnet@main - run: cargo build --target x86_64-pc-windows-msvc --profile ${{ env._RUST_BUILD_CONFIG == 'debug' && 'dev' || env._RUST_BUILD_CONFIG }} - uses: Cysharp/Actions/.github/actions/upload-artifact@main @@ -73,6 +75,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - uses: Cysharp/Actions/.github/actions/setup-dotnet@main - run: rustup target add aarch64-pc-windows-msvc - run: | @@ -100,6 +104,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - uses: Cysharp/Actions/.github/actions/setup-dotnet@main - run: rustup toolchain install nightly-2024-07-10-x86_64-pc-windows-msvc - run: rustup component add rust-src --toolchain nightly-2024-07-10-x86_64-pc-windows-msvc @@ -154,9 +160,9 @@ jobs: env: DEBIAN_FRONTEND: noninteractive - uses: Cysharp/Actions/.github/actions/checkout@main - - uses: Cysharp/Actions/.github/actions/setup-dotnet@main with: - dotnet-version: 8.0.x + submodules: true + - uses: Cysharp/Actions/.github/actions/setup-dotnet@main - uses: actions-rust-lang/setup-rust-toolchain@2fcdc490d667999e01ddbbf0f2823181beef6b39 # v1.15.0 - run: cargo build --target x86_64-unknown-linux-gnu --profile ${{ env._RUST_BUILD_CONFIG == 'debug' && 'dev' || env._RUST_BUILD_CONFIG }} - uses: Cysharp/Actions/.github/actions/upload-artifact@main @@ -181,6 +187,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - uses: Cysharp/Actions/.github/actions/setup-dotnet@main - run: rustup target add x86_64-apple-darwin - run: cargo build --target x86_64-apple-darwin --profile ${{ env._RUST_BUILD_CONFIG == 'debug' && 'dev' || env._RUST_BUILD_CONFIG }} @@ -206,6 +214,9 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true + - uses: Cysharp/Actions/.github/actions/setup-dotnet@main - run: rustup target add aarch64-apple-darwin - run: cargo build --target aarch64-apple-darwin --profile ${{ env._RUST_BUILD_CONFIG == 'debug' && 'dev' || env._RUST_BUILD_CONFIG }} - uses: Cysharp/Actions/.github/actions/upload-artifact@main @@ -228,6 +239,8 @@ jobs: timeout-minutes: 30 steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - uses: Cysharp/Actions/.github/actions/download-artifact@main with: path: native/artifacts @@ -250,6 +263,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - run: rustup target add x86_64-apple-ios - run: cargo build --target x86_64-apple-ios --profile ${{ env._RUST_BUILD_CONFIG == 'debug' && 'dev' || env._RUST_BUILD_CONFIG }} env: @@ -272,6 +287,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - run: rustup target add aarch64-apple-ios - run: cargo build --target aarch64-apple-ios --profile ${{ env._RUST_BUILD_CONFIG == 'debug' && 'dev' || env._RUST_BUILD_CONFIG }} env: @@ -294,6 +311,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - run: rustup target add aarch64-apple-ios-sim - run: cargo build --target aarch64-apple-ios-sim --profile ${{ env._RUST_BUILD_CONFIG == 'debug' && 'dev' || env._RUST_BUILD_CONFIG }} env: @@ -316,6 +335,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - name: Use latest Android NDK run: | echo "ANDROID_NDK=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV @@ -343,6 +364,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - name: Use latest Android NDK run: | echo "ANDROID_NDK=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV @@ -370,6 +393,8 @@ jobs: working-directory: native steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true - name: Use latest Android NDK run: | echo "ANDROID_NDK=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV @@ -407,6 +432,9 @@ jobs: timeout-minutes: 30 steps: - uses: Cysharp/Actions/.github/actions/checkout@main + with: + submodules: true + - uses: Cysharp/Actions/.github/actions/setup-dotnet@main - uses: Cysharp/Actions/.github/actions/download-artifact@main with: path: native/artifacts diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6b94f3e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/HttpClientTestServer"] + path = external/HttpClientTestServer + url = https://github.com/Cysharp/HttpClientTestServer.git diff --git a/YetAnotherHttpHandler.slnx b/YetAnotherHttpHandler.slnx index f362572..39d1ec6 100644 --- a/YetAnotherHttpHandler.slnx +++ b/YetAnotherHttpHandler.slnx @@ -14,8 +14,12 @@ - + + + + + diff --git a/external/HttpClientTestServer b/external/HttpClientTestServer new file mode 160000 index 0000000..0f8be71 --- /dev/null +++ b/external/HttpClientTestServer @@ -0,0 +1 @@ +Subproject commit 0f8be7153c4ee789e97b40ef6c303fdf0d636843 diff --git a/test/YetAnotherHttpHandler.StandaloneTestServer/Program.cs b/test/YetAnotherHttpHandler.StandaloneTestServer/Program.cs deleted file mode 100644 index acc22b9..0000000 --- a/test/YetAnotherHttpHandler.StandaloneTestServer/Program.cs +++ /dev/null @@ -1,9 +0,0 @@ -using _YetAnotherHttpHandler.Test; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddGrpc(); - -var app = TestServerForHttp1AndHttp2.BuildApplication(builder); - -app.Run(); diff --git a/test/YetAnotherHttpHandler.StandaloneTestServer/Properties/launchSettings.json b/test/YetAnotherHttpHandler.StandaloneTestServer/Properties/launchSettings.json deleted file mode 100644 index 0b480f8..0000000 --- a/test/YetAnotherHttpHandler.StandaloneTestServer/Properties/launchSettings.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5115", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/test/YetAnotherHttpHandler.StandaloneTestServer/YetAnotherHttpHandler.StandaloneTestServer.csproj b/test/YetAnotherHttpHandler.StandaloneTestServer/YetAnotherHttpHandler.StandaloneTestServer.csproj deleted file mode 100644 index 9f35951..0000000 --- a/test/YetAnotherHttpHandler.StandaloneTestServer/YetAnotherHttpHandler.StandaloneTestServer.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - - - - - diff --git a/test/YetAnotherHttpHandler.StandaloneTestServer/appsettings.Development.json b/test/YetAnotherHttpHandler.StandaloneTestServer/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/test/YetAnotherHttpHandler.StandaloneTestServer/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/test/YetAnotherHttpHandler.StandaloneTestServer/appsettings.json b/test/YetAnotherHttpHandler.StandaloneTestServer/appsettings.json deleted file mode 100644 index 0b2039c..0000000 --- a/test/YetAnotherHttpHandler.StandaloneTestServer/appsettings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "Kestrel": { - "Endpoints": { - "Http1ClearText": { - "Url": "http://localhost:5115", - "Protocols": "Http1" - }, - "Http2ClearText": { - "Url": "http://localhost:5116", - "Protocols": "Http2" - } - } - }, - "AllowedHosts": "*" -} diff --git a/test/YetAnotherHttpHandler.Test/BackPressureTest.cs b/test/YetAnotherHttpHandler.Test/BackPressureTest.cs index 53c8fd2..03120d2 100644 --- a/test/YetAnotherHttpHandler.Test/BackPressureTest.cs +++ b/test/YetAnotherHttpHandler.Test/BackPressureTest.cs @@ -15,7 +15,7 @@ public async Task FlushTest(int size) { using var httpHandler = new YetAnotherHttpHandler(); using var client = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); var numRequests = Environment.ProcessorCount + 1; // more than the number of tokio worker threads @@ -36,4 +36,4 @@ public async Task FlushTest(int size) foreach (var stream in pendingStreams) await stream.DisposeAsync(); } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/ClientCertificateTest.cs b/test/YetAnotherHttpHandler.Test/ClientCertificateTest.cs index 0d45267..7ff8175 100644 --- a/test/YetAnotherHttpHandler.Test/ClientCertificateTest.cs +++ b/test/YetAnotherHttpHandler.Test/ClientCertificateTest.cs @@ -1,8 +1,6 @@ -using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography.X509Certificates; using Cysharp.Net.Http; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Https; +using HttpClientTestServer; namespace _YetAnotherHttpHandler.Test; @@ -12,34 +10,14 @@ public ClientCertificateTest(ITestOutputHelper testOutputHelper) : base(testOutp { } - protected Task LaunchServerAsync(Action? configure = null) - where T : ITestServerBuilder - { - return LaunchServerAsync(TestWebAppServerListenMode.SecureHttp1AndHttp2, builder => - { - // Use self-signed certificate for testing purpose. - builder.WebHost.ConfigureKestrel(options => - { - options.ConfigureHttpsDefaults(options => - { - options.ServerCertificate = new X509Certificate2("Certificates/localhost.pfx"); - options.ClientCertificateMode = ClientCertificateMode.RequireCertificate; - options.ClientCertificateValidation = (certificate2, chain, policyError) => - { - return certificate2.Subject == "CN=client.example.com"; - }; - }); - }); - - configure?.Invoke(builder); - }); - } + protected Task LaunchServerAsync() + => LaunchServerAsync(new TestServerOptions(ListenHttpProtocols.Http1AndHttp2, isSecure: true) { EnableClientCertificateValidation = true }); [Fact] public async Task NotSet() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { //ClientAuthCertificates = File.ReadAllText("./Certificates/client.crt"), @@ -61,7 +39,7 @@ public async Task NotSet() public async Task UseClientCertificate() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { ClientAuthCertificates = File.ReadAllText("./Certificates/client.crt"), @@ -78,12 +56,12 @@ public async Task UseClientCertificate() // Assert Assert.Equal("__OK__", result); } - + [Fact] public async Task Invalid() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { ClientAuthCertificates = File.ReadAllText("./Certificates/client_unknown.crt"), // CN=unknown.example.com @@ -104,7 +82,7 @@ public async Task Invalid() public async Task Reference_SocketHttpHandler_NotSet() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new SocketsHttpHandler(); httpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true; var httpClient = new HttpClient(httpHandler); @@ -121,7 +99,7 @@ public async Task Reference_SocketHttpHandler_NotSet() public async Task Reference_SocketHttpHandler_UseClientCertificate() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new SocketsHttpHandler(); httpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true; httpHandler.SslOptions.ClientCertificates = new X509CertificateCollection() @@ -143,7 +121,7 @@ public async Task Reference_SocketHttpHandler_UseClientCertificate() public async Task Reference_SocketHttpHandler_Invalid() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new SocketsHttpHandler(); httpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true; httpHandler.SslOptions.ClientCertificates = new X509CertificateCollection() @@ -159,4 +137,4 @@ public async Task Reference_SocketHttpHandler_Invalid() // Assert Assert.IsType(ex); } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/Helpers/TestServerHelper.cs b/test/YetAnotherHttpHandler.Test/Helpers/TestServerHelper.cs deleted file mode 100644 index 5360d7c..0000000 --- a/test/YetAnotherHttpHandler.Test/Helpers/TestServerHelper.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Net; -using System.Net.Sockets; - -namespace _YetAnotherHttpHandler.Test.Helpers; - -public class TestServerHelper -{ - private static readonly HashSet _usedPortInSession = new HashSet(); - - public static int GetUnusedEphemeralPort() - { - lock (_usedPortInSession) - { - var retryCount = 5; - do - { - var port = GetUnusedEphemeralPortCore(); - if (!_usedPortInSession.Contains(port)) - { - _usedPortInSession.Add(port); - return port; - } - } while (retryCount-- > 0); - - throw new Exception("Cannot allocate unused port in this test session."); - } - - static int GetUnusedEphemeralPortCore() - { - using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - socket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); - return ((IPEndPoint)socket.LocalEndPoint!).Port; - } - } -} \ No newline at end of file diff --git a/test/YetAnotherHttpHandler.Test/Helpers/TestWebAppServer.cs b/test/YetAnotherHttpHandler.Test/Helpers/TestWebAppServer.cs deleted file mode 100644 index f39238b..0000000 --- a/test/YetAnotherHttpHandler.Test/Helpers/TestWebAppServer.cs +++ /dev/null @@ -1,135 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Connections; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using TestWebApp; - -namespace _YetAnotherHttpHandler.Test.Helpers; - -public class TestWebAppServer : IAsyncDisposable -{ - private readonly Task _appTask; - private readonly IHostApplicationLifetime _appLifetime; - private readonly TaskCompletionSource _waitForAppStarted; - private readonly ConcurrentDictionary _activeConnectionsById = new(); - private int _activeConnections; - - public int Port { get; } - public bool IsSecure { get; } - - public string BaseUri => $"{(IsSecure ? "https" : "http")}://localhost:{Port}"; - - public int ActiveConnections => _activeConnections; - public IReadOnlyList ActiveConnectionIds => _activeConnectionsById.Keys.ToArray(); - - private TestWebAppServer(int port, TestWebAppServerListenMode listenMode, ITestOutputHelper? testOutputHelper, Func webAppBuilder, Action? configure) - { - Port = port; - IsSecure = listenMode is TestWebAppServerListenMode.SecureHttp1Only or - TestWebAppServerListenMode.SecureHttp2Only or - TestWebAppServerListenMode.SecureHttp1AndHttp2; - - var builder = WebApplication.CreateBuilder(Array.Empty()); - - configure?.Invoke(builder); - - builder.Services.AddGrpc(); - - builder.WebHost.ConfigureKestrel(options => - { - options.ListenLocalhost(port, listenOptions => - { - listenOptions.Protocols = listenMode switch - { - TestWebAppServerListenMode.InsecureHttp1Only => HttpProtocols.Http1, - TestWebAppServerListenMode.InsecureHttp2Only => HttpProtocols.Http2, - TestWebAppServerListenMode.SecureHttp1Only => HttpProtocols.Http1, - TestWebAppServerListenMode.SecureHttp2Only => HttpProtocols.Http2, - TestWebAppServerListenMode.SecureHttp1AndHttp2 => HttpProtocols.Http1AndHttp2, - _ => throw new NotSupportedException(), - }; - - if (IsSecure) - { - listenOptions.UseHttps(); - } - - listenOptions.Use(async (ctx, next) => - { - try - { - Interlocked.Increment(ref _activeConnections); - _activeConnectionsById.TryAdd(ctx.ConnectionId, true); - await next(); - } - finally - { - Interlocked.Decrement(ref _activeConnections); - _activeConnectionsById.TryRemove(ctx.ConnectionId, out _); - } - }); - }); - }); - if (testOutputHelper is not null) - { - if (Debugger.IsAttached) - { - builder.Logging.SetMinimumLevel(LogLevel.Trace); - } - builder.Logging.AddProvider(new TestOutputLoggerProvider(testOutputHelper)); - } - - var app = webAppBuilder(builder); - - _waitForAppStarted = new TaskCompletionSource(); - _appLifetime = app.Services.GetRequiredService(); - _appLifetime.ApplicationStarted.Register(() => _waitForAppStarted.SetResult()); - _appTask = app.RunAsync(); - } - - public static async Task LaunchAsync(TestWebAppServerListenMode listenMode, ITestOutputHelper? testOutputHelper = null, CancellationToken shutdownToken = default, Action? configure = null) - where T : ITestServerBuilder - { - var port = TestServerHelper.GetUnusedEphemeralPort(); - var server = new TestWebAppServer(port, listenMode, testOutputHelper, T.BuildApplication, configure); - await server._waitForAppStarted.Task; - - shutdownToken.Register(() => - { - server.Shutdown(); - }); - - return server; - } - - public void Shutdown() - { - _appLifetime.StopApplication(); - } - - public async ValueTask DisposeAsync() - { - _appLifetime.StopApplication(); - try - { - await _appTask.WaitAsync(TimeSpan.FromSeconds(1)); - } - catch (TimeoutException) - { - } - } -} - -public enum TestWebAppServerListenMode -{ - InsecureHttp1Only, - InsecureHttp2Only, - SecureHttp1Only, - SecureHttp2Only, - SecureHttp1AndHttp2, -} \ No newline at end of file diff --git a/test/YetAnotherHttpHandler.Test/Http1Test.cs b/test/YetAnotherHttpHandler.Test/Http1Test.cs index 86741a7..369ed9c 100644 --- a/test/YetAnotherHttpHandler.Test/Http1Test.cs +++ b/test/YetAnotherHttpHandler.Test/Http1Test.cs @@ -13,7 +13,7 @@ public async Task FailedToConnect() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); // Act var ex = await Record.ExceptionAsync(async () => await httpClient.GetAsync($"http://localhost.exmample/")); @@ -29,7 +29,7 @@ public async Task FailedToConnect_VersionMismatch() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler() { Http2Only = true }; var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); // Act var ex = await Record.ExceptionAsync(async () => (await httpClient.GetAsync($"{server.BaseUri}/")).EnsureSuccessStatusCode()); @@ -51,17 +51,7 @@ public async Task Request_Version_20_Http1OnlyServer_Secure() RootCertificates = File.ReadAllText("./Certificates/localhost.crt") }; var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.SecureHttp1Only, builder => - { - // Use self-signed certificate for testing purpose. - builder.WebHost.ConfigureKestrel(options => - { - options.ConfigureHttpsDefaults(options => - { - options.ServerCertificate = new X509Certificate2("Certificates/localhost.pfx"); - }); - }); - }); + await using var server = await LaunchServerAsync(TestServerListenMode.SecureHttp1Only); var request = new HttpRequestMessage(HttpMethod.Get, $"{server.BaseUri}/") { Version = HttpVersion.Version20, @@ -84,7 +74,7 @@ public async Task Request_Version_Downgrade() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); var request = new HttpRequestMessage(HttpMethod.Get, $"{server.BaseUri}/") { Version = HttpVersion.Version20, @@ -107,7 +97,7 @@ public async Task Get_Ok() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); // Act var response = await httpClient.GetAsync($"{server.BaseUri}/"); @@ -125,7 +115,7 @@ public async Task Get_NotOk() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); // Act var response = await httpClient.GetAsync($"{server.BaseUri}/not-found"); @@ -143,7 +133,7 @@ public async Task Get_ResponseHeaders() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); // Act var response = await httpClient.GetAsync($"{server.BaseUri}/response-headers"); @@ -161,7 +151,7 @@ public async Task Get_NonAsciiPath() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); // Act var response = await httpClient.GetAsync($"{server.BaseUri}/ハロー"); @@ -178,7 +168,7 @@ public async Task Post_Cancel() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); var pipe = new Pipe(); var content = new StreamContent(pipe.Reader.AsStream()); var cts = new CancellationTokenSource(); @@ -201,7 +191,7 @@ public async Task Post_Timeout() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler(); var httpClient = new HttpClient(httpHandler) { Timeout = TimeSpan.FromSeconds(2) }; - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp1Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp1Only); var pipe = new Pipe(); var content = new StreamContent(pipe.Reader.AsStream()); var cts = new CancellationTokenSource(); @@ -227,17 +217,7 @@ public async Task Secure_Get_Ok() RootCertificates = File.ReadAllText("./Certificates/localhost.crt") }; var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.SecureHttp1Only, builder => - { - // Use self-signed certificate for testing purpose. - builder.WebHost.ConfigureKestrel(options => - { - options.ConfigureHttpsDefaults(options => - { - options.ServerCertificate = new X509Certificate2("Certificates/localhost.pfx"); - }); - }); - }); + await using var server = await LaunchServerAsync(TestServerListenMode.SecureHttp1Only); // Act var response = await httpClient.GetAsync($"{server.BaseUri}/"); @@ -248,4 +228,4 @@ public async Task Secure_Get_Ok() Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal("__OK__", responseBody); } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/Http2ClearTextTest.cs b/test/YetAnotherHttpHandler.Test/Http2ClearTextTest.cs index 1c8ffbb..1b09f43 100644 --- a/test/YetAnotherHttpHandler.Test/Http2ClearTextTest.cs +++ b/test/YetAnotherHttpHandler.Test/Http2ClearTextTest.cs @@ -1,6 +1,6 @@ -using System.Net; +using System.Net; using Cysharp.Net.Http; -using Microsoft.AspNetCore.Builder; +using HttpClientTestServer; namespace _YetAnotherHttpHandler.Test; @@ -10,11 +10,9 @@ protected override YetAnotherHttpHandler CreateHandler() { return new YetAnotherHttpHandler() { Http2Only = true }; } - - protected override Task LaunchServerAsyncCore(Action? configure = null) - { - return LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp2Only, configure); - } + + protected override Task LaunchServerAsync() + => LaunchServerAsync(new TestServerOptions(ListenHttpProtocols.Http2, isSecure: false)); [Fact] public async Task FailedToConnect_VersionMismatch() @@ -22,7 +20,7 @@ public async Task FailedToConnect_VersionMismatch() // Arrange using var httpHandler = new Cysharp.Net.Http.YetAnotherHttpHandler() { Http2Only = false }; var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var ex = await Record.ExceptionAsync(async () => (await httpClient.GetAsync($"{server.BaseUri}/")).EnsureSuccessStatusCode()); @@ -31,4 +29,4 @@ public async Task FailedToConnect_VersionMismatch() Assert.IsType(ex); Assert.Equal(HttpStatusCode.BadRequest, ((HttpRequestException)ex).StatusCode); } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/Http2Test.cs b/test/YetAnotherHttpHandler.Test/Http2Test.cs index b0781ab..6cd314d 100644 --- a/test/YetAnotherHttpHandler.Test/Http2Test.cs +++ b/test/YetAnotherHttpHandler.Test/Http2Test.cs @@ -1,7 +1,6 @@ -using System.Security.Cryptography.X509Certificates; +using System.Security.Cryptography.X509Certificates; using Cysharp.Net.Http; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; +using HttpClientTestServer; namespace _YetAnotherHttpHandler.Test; @@ -17,29 +16,14 @@ protected override YetAnotherHttpHandler CreateHandler() }; } - protected override Task LaunchServerAsyncCore(Action? configure = null) - { - return LaunchServerAsync(TestWebAppServerListenMode.SecureHttp2Only, builder => - { - // Use self-signed certificate for testing purpose. - builder.WebHost.ConfigureKestrel(options => - { - //options.Limits.Http2.MaxFrameSize = 1024 * 1024; - options.ConfigureHttpsDefaults(options => - { - options.ServerCertificate = new X509Certificate2("Certificates/localhost.pfx"); - }); - }); - - configure?.Invoke(builder); - }); - } + protected override Task LaunchServerAsync() + => LaunchServerAsync(new TestServerOptions(ListenHttpProtocols.Http2, isSecure: true)); [Fact] public async Task SelfSignedCertificate_NotTrusted() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { SkipCertificateVerification = false }; // We need to verify server certificate. var httpClient = new HttpClient(httpHandler); @@ -55,7 +39,7 @@ public async Task SelfSignedCertificate_NotTrusted() public async Task SelfSignedCertificate_NotTrusted_SkipValidation() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { SkipCertificateVerification = true }; var httpClient = new HttpClient(httpHandler); @@ -72,7 +56,7 @@ public async Task SelfSignedCertificate_NotTrusted_SkipValidation() public async Task SelfSignedCertificate_Trusted_CustomRootCA() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { // We need to verify server certificate. @@ -94,7 +78,7 @@ public async Task SelfSignedCertificate_Trusted_CustomRootCA() public async Task CustomCertificateVerificationHandler_Success() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { OnVerifyServerCertificate = (name, certificate, now) => @@ -118,7 +102,7 @@ public async Task CustomCertificateVerificationHandler_Success() public async Task CustomCertificateVerificationHandler_Failure() { // Arrange - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { OnVerifyServerCertificate = (name, certificate, now) => @@ -142,7 +126,7 @@ public async Task CustomCertificateVerificationHandler_Certificate() { // Arrange byte[] receivedCertificate = Array.Empty(); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var httpHandler = new YetAnotherHttpHandler() { OnVerifyServerCertificate = (name, certificate, now) => @@ -165,4 +149,4 @@ public async Task CustomCertificateVerificationHandler_Certificate() Assert.Equal("143a97beaaf96af9cdbc8769f523251b7c60625b", cert.Thumbprint, StringComparer.OrdinalIgnoreCase); Assert.Equal("3082020a0282020100caec8d9f7e92bfceeef2aed4981ee786e31eef5c3a81e52cb5c60a84ee596a161f77d23d9866532a952f4e1826eb99eb20f4fccc4ef246aae06a03fe32db91b70072b7dc3b94ef18fe525d6b88876935dd7bd62ad25646aefd02799ecd2590867cf1bd1891c6f018782238e133019c35e6b9d2f7e4cbbda7b999c274b28b6ebe79d37edb210ed1d9b3dfc6a353a342dc8a3e40a48ebf625a49675e2f8b4c870d20b24c033d3d4960bfa12c61d437bdfd426dd8365659cf880c982367fb4d1677601aeb514f3fa9c052b0fa1335880268195ddf9ff7262ccb649956ba43d69db7b74ee53d17046ffd587e5270f6727bfba74f895b67286bff58ae4fd6ee8485c46a2e8e0fdf2a6ecef63efa24a0ffd3853bc86922cd01b8b9a928dc14dc20380746c0eac88a7d311daffe76dbf17a25d9c1cbf67137fa8beb827f6ea4816f81993e9c0b91800981e08681b4c4b98a1d1026794b07916a0e3f8f9091beb3c8aa3a9860e15dcfd3bcc0bce4e4d49f7a5432ce967407a63c0c197a1869ebd61d153e5669b6ae4b694f2255b79c6d96a8e837f1419c261b429028b12e5f72237b82172ccc298a54a0b4ae209aeccc0f528a1539afd3a83cefe6b18fa76bc55d374a0e8bdaece953a366287c377682b3b03393bb4d0a7b30752cd60b671d211874c78a5a2e9f49bb71e09aeed776e55d5ecc3141da402836629248aa87e75d0e7ef4530203010001", cert.GetPublicKeyString(), StringComparer.OrdinalIgnoreCase); } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/Http2TestBase.cs b/test/YetAnotherHttpHandler.Test/Http2TestBase.cs index fde6c7d..0feebd5 100644 --- a/test/YetAnotherHttpHandler.Test/Http2TestBase.cs +++ b/test/YetAnotherHttpHandler.Test/Http2TestBase.cs @@ -1,5 +1,4 @@ -using Microsoft.AspNetCore.Builder; -using System.IO.Pipelines; +using System.IO.Pipelines; using System.Net; using System.Net.Http.Headers; using Cysharp.Net.Http; @@ -12,10 +11,8 @@ namespace _YetAnotherHttpHandler.Test; public abstract class Http2TestBase(ITestOutputHelper testOutputHelper) : UseTestServerTestBase(testOutputHelper) { protected abstract YetAnotherHttpHandler CreateHandler(); - protected abstract Task LaunchServerAsyncCore(Action? configure = null) where T : ITestServerBuilder; - protected Task LaunchServerAsync(Action? configure = null) where T : ITestServerBuilder - => LaunchServerAsyncCore(configure); + protected abstract Task LaunchServerAsync(); [Fact] public async Task Get_Ok() @@ -23,7 +20,7 @@ public async Task Get_Ok() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var request = new HttpRequestMessage(HttpMethod.Get, $"{server.BaseUri}/") @@ -45,7 +42,7 @@ public async Task Get_NotOk() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var request = new HttpRequestMessage(HttpMethod.Get, $"{server.BaseUri}/not-found") @@ -67,7 +64,7 @@ public async Task Post_Body() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var content = new ByteArrayContent(new byte[] { 1, 2, 3, 45, 67 }); @@ -93,7 +90,7 @@ public async Task Post_NotDuplex_Receive_ResponseHeaders_Before_ResponseBody() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var content = new ByteArrayContent(new byte[] { 0 }); @@ -113,7 +110,7 @@ public async Task Post_NotDuplex_Receive_ResponseHeaders_Before_ResponseBody() Assert.Equal("foo", response.Headers.TryGetValues("x-header-1", out var values) ? string.Join(',', values) : null); Assert.False(responseBodyTask.IsCompleted); } - + // NOTE: SocketHttpHandler waits for the completion of sending the request body before the response headers. // https://github.com/dotnet/runtime/blob/v7.0.0/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs#L1980-L1988 // https://github.com/dotnet/runtime/blob/v7.0.0/src/libraries/System.Net.Http/src/System/Net/Http/HttpContent.cs#L343-L349 @@ -147,7 +144,7 @@ public async Task Post_NotDuplex_Body_StreamingBody() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var pipe = new Pipe(); @@ -188,7 +185,7 @@ public async Task Post_Duplex_Body_StreamingBody() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var pipe = new Pipe(); @@ -230,7 +227,7 @@ public async Task Post_ResponseTrailers() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var content = new ByteArrayContent(new byte[] { 1, 2, 3, 45, 67 }); @@ -256,7 +253,7 @@ public async Task AbortOnServer_Post_SendingBody() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var content = new ByteArrayContent(Enumerable.Range(0, 1024 * 1024).Select(x => (byte)(x % 255)).ToArray()); @@ -279,7 +276,7 @@ public async Task Cancel_Post_SendingBody() using var httpHandler = CreateHandler(); //using var httpHandler = new SocketsHttpHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var pipe = new Pipe(); @@ -309,7 +306,7 @@ public async Task Cancel_Post_SendingBody_Duplex() // Arrange /*using*/ var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var pipe = new Pipe(); @@ -320,7 +317,7 @@ public async Task Cancel_Post_SendingBody_Duplex() Version = HttpVersion.Version20, Content = content, }; - + var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).WaitAsync(TimeoutToken); var connectionId = response.Headers.TryGetValues("x-connection-id", out var values) ? string.Join(',', values) : string.Empty; var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(500)); @@ -342,7 +339,14 @@ public async Task Cancel_Post_SendingBody_Duplex() // Assert var operationCanceledException = Assert.IsAssignableFrom(ex); Assert.Equal(cts.Token, operationCanceledException.CancellationToken); - Assert.DoesNotContain(connectionId, server.ActiveConnectionIds); + + using var handler2 = CreateHandler(); + using var httpClient2 = new HttpClient(handler2); + httpClient2.DefaultRequestVersion = HttpVersion.Version20; + httpClient2.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher; + var activeConnectionIdsCsv = await httpClient2.GetStringAsync($"{server.BaseUri}/connection-state/active-connections"); + var activeConnectionIds = activeConnectionIdsCsv.Split(','); + Assert.Single(activeConnectionIds); } #endif @@ -352,7 +356,7 @@ public async Task DisposeHttpResponseMessage_Post_SendingBody_Duplex() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var pipe = new Pipe(); @@ -382,16 +386,16 @@ public async Task Cancel_Get_BeforeReceivingResponseHeaders() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); var id = Guid.NewGuid().ToString(); // Act var request = new HttpRequestMessage(HttpMethod.Get, $"{server.BaseUri}/slow-response-headers") { Version = HttpVersion.Version20, - Headers = { { TestServerForHttp1AndHttp2.SessionStateHeaderKey, id } } + Headers = { { "x-test-session-id" /*SessionStateHeaderKey*/, id } } }; - + // The server responds after one second. But the client cancels the request before receiving response headers. var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(300)); var ex = await Record.ExceptionAsync(async () => await httpClient.SendAsync(request, cts.Token).WaitAsync(TimeoutToken)); @@ -413,7 +417,7 @@ public async Task Cancel_Post_BeforeRequest() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var pipe = new Pipe(); @@ -441,7 +445,7 @@ public async Task Grpc_Unary() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); var client = new Greeter.GreeterClient(GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler })); // Act @@ -457,7 +461,7 @@ public async Task Grpc_Duplex() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); var client = new Greeter.GreeterClient(GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler })); // Act @@ -495,7 +499,7 @@ public async Task Grpc_Duplex_Concurrency() const int RequestCount = 10; const int Concurrency = 10; using var httpHandler = CreateHandler(); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var channel = GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler }); // Act @@ -544,7 +548,7 @@ public async Task Grpc_Duplex_Concurrency() [Fact] public async Task Grpc_ShutdownAndDispose() { - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); for (var i = 0; i < 10; i++) { @@ -593,7 +597,7 @@ public async Task Grpc_Error_Status_ErrorCode() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); var client = new Greeter.GreeterClient(GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler })); // Act @@ -626,7 +630,7 @@ public async Task Grpc_Error_TimedOut_With_HttpClientTimeout() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler) { Timeout = TimeSpan.FromSeconds(3) }; - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); var client = new Greeter.GreeterClient(GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpClient = httpClient })); // Act @@ -635,11 +639,7 @@ public async Task Grpc_Error_TimedOut_With_HttpClientTimeout() // Assert Assert.IsType(ex); Assert.Equal(StatusCode.Cancelled, ((RpcException)ex).StatusCode); -#if UNITY_2021_1_OR_NEWER Assert.IsType(((RpcException)ex).Status.DebugException); -#else - Assert.IsType(((RpcException)ex).Status.DebugException); -#endif } [Fact] @@ -648,7 +648,7 @@ public async Task Grpc_Error_TimedOut_With_Deadline() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); var client = new Greeter.GreeterClient(GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpClient = httpClient })); // Act @@ -665,7 +665,7 @@ public async Task Grpc_Error_TimedOut_With_CancellationToken() // Arrange using var httpHandler = CreateHandler(); var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); var client = new Greeter.GreeterClient(GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpClient = httpClient })); // Act @@ -687,7 +687,7 @@ public async Task Enable_Http2KeepAlive() httpHandler.Http2KeepAliveWhileIdle = true; var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); // Act var request = new HttpRequestMessage(HttpMethod.Get, $"{server.BaseUri}/") @@ -723,4 +723,4 @@ protected override bool TryComputeLength(out long length) return false; } } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/StressTest.cs b/test/YetAnotherHttpHandler.Test/StressTest.cs index 6cf3958..3806d71 100644 --- a/test/YetAnotherHttpHandler.Test/StressTest.cs +++ b/test/YetAnotherHttpHandler.Test/StressTest.cs @@ -1,4 +1,4 @@ -#define ENABLE_STRESS_TEST +#define ENABLE_STRESS_TEST #if ENABLE_STRESS_TEST using System.Security.Cryptography; @@ -7,9 +7,13 @@ using Cysharp.Net.Http; using Grpc.Core; using Grpc.Net.Client; +using HttpClientTestServer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using TestWebApp; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using EchoRequest = TestWebApp.EchoRequest; +using Greeter = TestWebApp.Greeter; +using HelloRequest = TestWebApp.HelloRequest; namespace _YetAnotherHttpHandler.Test; @@ -31,27 +35,12 @@ protected HttpMessageHandler CreateHandler() }; } - protected Task LaunchServerAsyncCore(Action? configure = null) - where T : ITestServerBuilder - { - return LaunchServerAsync(TestWebAppServerListenMode.SecureHttp2Only, builder => + protected Task LaunchServerAsync() + => LaunchServerAsync(new TestServerOptions(ListenHttpProtocols.Http2, true).With(x => { - // Use self-signed certificate for testing purpose. - builder.WebHost.ConfigureKestrel(options => - { - //options.Limits.Http2.MaxFrameSize = 1024 * 1024; - options.ConfigureHttpsDefaults(options => - { - options.ServerCertificate = new X509Certificate2("Certificates/localhost.pfx"); - }); - }); - - configure?.Invoke(builder); - }); - } - - protected Task LaunchServerAsync(Action? configure = null) where T : ITestServerBuilder - => LaunchServerAsyncCore(configure); + x.IsSecure = true; + x.HttpProtocols = ListenHttpProtocols.Http2; + })); [Fact] public async Task Grpc_Duplex_Concurrency() @@ -62,7 +51,7 @@ public async Task Grpc_Duplex_Concurrency() var requestStringSuffix = CreateRandomString(1024 * 32 /* UTF-8 = 32KB */); using var httpHandler = CreateHandler(); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var channel = GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler }); // Act @@ -120,7 +109,7 @@ public async Task Grpc_Duplex_Concurrency_CompleteFromServerWhileSendingData() var data = CreateRandomString(1024 * 64 /* UTF-8 = 64KB */); using var httpHandler = CreateHandler(); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var channel = GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler }); // Act @@ -181,7 +170,7 @@ public async Task Grpc_Duplex_Concurrency_AbortFromServerWhileSendingData() var data = CreateRandomString(1024 * 64 /* UTF-8 = 64KB */); using var httpHandler = CreateHandler(); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var channel = GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler }); // Act @@ -249,7 +238,7 @@ public async Task Grpc_Duplex_Large_Data() var hash = SHA1.HashData(Encoding.UTF8.GetBytes(data)); using var httpHandler = CreateHandler(); - await using var server = await LaunchServerAsync(); + await using var server = await LaunchServerAsync(); using var channel = GrpcChannel.ForAddress(server.BaseUri, new GrpcChannelOptions() { HttpHandler = httpHandler }); // Act @@ -300,4 +289,4 @@ private static string CreateRandomString(int length) => } }); } -#endif \ No newline at end of file +#endif diff --git a/test/YetAnotherHttpHandler.Test/TestServerForHttp1AndHttp2.cs b/test/YetAnotherHttpHandler.Test/TestServerForHttp1AndHttp2.cs deleted file mode 100644 index 5845e64..0000000 --- a/test/YetAnotherHttpHandler.Test/TestServerForHttp1AndHttp2.cs +++ /dev/null @@ -1,278 +0,0 @@ -using System.Buffers; -using System.Collections.Concurrent; -using System.IO.Pipelines; -using System.Net; -using Grpc.Core; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.DependencyInjection; -using TestWebApp; - -namespace _YetAnotherHttpHandler.Test; - -class TestServerForHttp1AndHttp2 : ITestServerBuilder -{ - private const string SessionStateKey = "SessionState"; - public const string SessionStateHeaderKey = "x-yahatest-session-id"; - - record SessionStateFeature(ConcurrentDictionary Items); - - public static WebApplication BuildApplication(WebApplicationBuilder builder) - { - builder.Services.AddKeyedSingleton(SessionStateKey, new ConcurrentDictionary>()); - - var app = builder.Build(); - - // ConnectionId header - app.Use((ctx, next) => - { - ctx.Response.Headers["x-connection-id"] = ctx.Connection.Id; - return next(ctx); - }); - - // SessionState - app.Use((ctx, next) => - { - if (ctx.Request.Headers.TryGetValue(SessionStateHeaderKey, out var headerValues)) - { - var sessionStates = ctx.RequestServices.GetRequiredKeyedService>>(SessionStateKey); - var sessionStateItems = sessionStates.GetOrAdd(headerValues.ToString(), _ => new ConcurrentDictionary()); - ctx.Features.Set(new SessionStateFeature(sessionStateItems)); - } - else - { - ctx.Features.Set(new SessionStateFeature(new ConcurrentDictionary())); - } - - return next(ctx); - }); - app.MapGet("/session-state", (HttpContext ctx, string id, string key) => - { - var sessionStates = ctx.RequestServices.GetRequiredKeyedService>>(SessionStateKey); - if (sessionStates.TryGetValue(id, out var items)) - { - if (items.TryGetValue(key, out var value)) - { - return Results.Content(value.ToString()); - } - return Results.Content(string.Empty); - } - - return Results.NotFound(); - }); - - // HTTP/1 and HTTP/2 - app.MapGet("/", () => Results.Content("__OK__")); - app.MapGet("/not-found", () => Results.Content("__Not_Found__", statusCode: 404)); - app.MapGet("/response-headers", (HttpContext httpContext) => - { - httpContext.Response.Headers["x-test"] = "foo"; - return Results.Content("__OK__"); - }); - app.MapGet("/slow-response-headers", async (HttpContext httpContext) => - { - using var _ = httpContext.RequestAborted.Register(() => - { - httpContext.Features.GetRequiredFeature().Items["IsCanceled"] = true; - }); - - await Task.Delay(1000); - httpContext.Response.Headers["x-test"] = "foo"; - - return Results.Content("__OK__"); - }); - app.MapGet("/ハロー", () => Results.Content("Konnichiwa")); - app.MapPost("/slow-upload", async (HttpContext ctx, PipeReader reader) => - { - while (true) - { - await Task.Delay(1000); - var readResult = await reader.ReadAsync(); - reader.AdvanceTo(readResult.Buffer.End); - if (readResult.IsCompleted || readResult.IsCanceled) break; - } - return Results.Content("OK"); - }); - app.MapPost("/post-echo", async (HttpContext httpContext, Stream bodyStream) => - { - httpContext.Response.Headers["x-request-content-type"] = httpContext.Request.ContentType; - - return Results.Bytes(await bodyStream.ToArrayAsync(), "application/octet-stream"); - }); - app.MapPost("/post-streaming", async (HttpContext httpContext, PipeReader reader) => - { - // Send status code and response headers. - httpContext.Response.Headers["x-header-1"] = "foo"; - httpContext.Response.StatusCode = (int)HttpStatusCode.OK; - await httpContext.Response.BodyWriter.FlushAsync(); - - var readLen = 0L; - while (true) - { - var readResult = await reader.ReadAsync(); - readLen += readResult.Buffer.Length; - reader.AdvanceTo(readResult.Buffer.End); - if (readResult.IsCompleted || readResult.IsCanceled) break; - } - - await httpContext.Response.WriteAsync(readLen.ToString()); - - return Results.Empty; - }); - app.MapPost("/post-response-trailers", (HttpContext httpContext) => - { - httpContext.Response.AppendTrailer("x-trailer-1", "foo"); - httpContext.Response.AppendTrailer("x-trailer-2", "bar"); - - return Results.Ok("__OK__"); - }); - app.MapPost("/post-response-headers-immediately", async (HttpContext httpContext, PipeReader reader) => - { - // Send status code and response headers. - httpContext.Response.Headers["x-header-1"] = "foo"; - httpContext.Response.StatusCode = (int)HttpStatusCode.Accepted; - await httpContext.Response.BodyWriter.FlushAsync(); - - await Task.Delay(100000); - await httpContext.Response.WriteAsync("__OK__"); - return Results.Empty; - }); - app.MapPost("/post-abort-while-reading", async (HttpContext httpContext, PipeReader reader) => - { - var readResult = await reader.ReadAsync(); - reader.AdvanceTo(readResult.Buffer.End); - httpContext.Abort(); - - return Results.Empty; - }); - app.MapPost("/post-null", async (HttpContext httpContext, PipeReader reader) => - { - while (!httpContext.RequestAborted.IsCancellationRequested) - { - var readResult = await reader.ReadAsync(); - reader.AdvanceTo(readResult.Buffer.End); - if (readResult.IsCompleted || readResult.IsCanceled) break; - } - return Results.Empty; - }); - app.MapPost("/post-null-duplex", async (HttpContext httpContext, PipeReader reader) => - { - // Send status code and response headers. - httpContext.Response.Headers["x-header-1"] = "foo"; - httpContext.Response.StatusCode = (int)HttpStatusCode.OK; - await httpContext.Response.BodyWriter.FlushAsync(); - - while (!httpContext.RequestAborted.IsCancellationRequested) - { - var readResult = await reader.ReadAsync(); - reader.AdvanceTo(readResult.Buffer.End); - if (readResult.IsCompleted || readResult.IsCanceled) break; - } - return Results.Empty; - }); - app.MapPost("/post-never-read", async (HttpContext httpContext) => - { - // Send status code and response headers. - httpContext.Response.Headers["x-header-1"] = "foo"; - httpContext.Response.StatusCode = (int)HttpStatusCode.OK; - await httpContext.Response.BodyWriter.FlushAsync(); - - while (!httpContext.RequestAborted.IsCancellationRequested) - { - await Task.Delay(100); - } - return Results.Empty; - }); - app.MapGet("/random", (int size) => - { - var buffer = new byte[size]; - Random.Shared.NextBytes(buffer); - return Results.Bytes(buffer, "application/octet-stream"); - }); - - // HTTP/2 - app.MapGet("/error-reset", (HttpContext httpContext) => - { - // https://learn.microsoft.com/ja-jp/aspnet/core/fundamentals/servers/kestrel/http2?view=aspnetcore-7.0#reset-1 - var resetFeature = httpContext.Features.Get(); - resetFeature!.Reset(errorCode: 2); // INTERNAL_ERROR - return Results.Empty; - }); - - // gRPC - app.MapGrpcService(); - - return app; - } - - class GreeterService : Greeter.GreeterBase - { -#pragma warning disable CS1998 - public override async Task SayHello(HelloRequest request, ServerCallContext context) - { - return new HelloReply { Message = $"Hello {request.Name}" }; - } - - public override async Task SayHelloSlow(HelloRequest request, ServerCallContext context) - { - await Task.Delay(TimeSpan.FromSeconds(30)); - return new HelloReply { Message = $"Hello {request.Name}" }; - } - - public override async Task SayHelloNever(HelloRequest request, ServerCallContext context) - { - await Task.Delay(-1); - throw new NotImplementedException(); - } - - public override async Task SayHelloDuplex(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) - { - await foreach (var request in requestStream.ReadAllAsync(context.CancellationToken)) - { - await responseStream.WriteAsync(new HelloReply { Message = $"Hello {request.Name}" }); - } - } - - public override async Task SayHelloDuplexCompleteRandomly(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) - { - await foreach (var request in requestStream.ReadAllAsync(context.CancellationToken)) - { - await responseStream.WriteAsync(new HelloReply { Message = request.Name }); - if (Random.Shared.Next(0, 9) == 0) - { - return; - } - } - } - - public override async Task SayHelloDuplexAbortRandomly(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) - { - await foreach (var request in requestStream.ReadAllAsync(context.CancellationToken)) - { - await responseStream.WriteAsync(new HelloReply { Message = request.Name }); - if (Random.Shared.Next(0, 9) == 0) - { - context.GetHttpContext().Abort(); - return; - } - } - } - - public override async Task ResetByServer(ResetRequest request, ServerCallContext context) - { - context.GetHttpContext().Features.GetRequiredFeature().Reset(errorCode: request.ErrorCode); - return new ResetReply { }; - } - - public override async Task EchoDuplex(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) - { - await foreach (var request in requestStream.ReadAllAsync(context.CancellationToken)) - { - await responseStream.WriteAsync(new EchoReply() { Message = request.Message }); - } - } -#pragma warning restore CS1998 - } - -} \ No newline at end of file diff --git a/test/YetAnotherHttpHandler.Test/UdsTest.cs b/test/YetAnotherHttpHandler.Test/UdsTest.cs index 6c87957..941a95d 100644 --- a/test/YetAnotherHttpHandler.Test/UdsTest.cs +++ b/test/YetAnotherHttpHandler.Test/UdsTest.cs @@ -1,8 +1,5 @@ -using System.Security.Cryptography.X509Certificates; -using Cysharp.Net.Http; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; +using Cysharp.Net.Http; +using HttpClientTestServer; namespace _YetAnotherHttpHandler.Test; @@ -19,25 +16,12 @@ protected override YetAnotherHttpHandler CreateHandler() }; } - protected override Task LaunchServerAsyncCore(Action? configure = null) - { - return LaunchServerAsync(TestWebAppServerListenMode.SecureHttp2Only, builder => + protected override Task LaunchServerAsync() + => LaunchServerAsync(new TestServerOptions(ListenHttpProtocols.Http2, isSecure: true) { - builder.WebHost.ConfigureKestrel(options => - { - options.ListenUnixSocket(_udsPath, listenOptions => - { - listenOptions.Protocols = HttpProtocols.Http2; - }); - - // hyperlocal uses the 'unix' scheme and passes the URI to hyper. As a result, the ':scheme' header in the request is set to 'unix'. - // By default, Kestrel does not accept non-HTTP schemes. To allow non-HTTP schemes, we need to set 'AllowAlternateSchemes' to true. - options.AllowAlternateSchemes = true; - }); - - configure?.Invoke(builder); + UnixDomainSocketPath = _udsPath, }); - } + } [OSSkipCondition(OperatingSystems.MacOSX | OperatingSystems.Linux)] @@ -59,4 +43,4 @@ await Assert.ThrowsAsync(async () => await httpClient.GetAsync("http://localhost/"); }); } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/UseTestServerBase.cs b/test/YetAnotherHttpHandler.Test/UseTestServerBase.cs index 73e3eaa..6121bbb 100644 --- a/test/YetAnotherHttpHandler.Test/UseTestServerBase.cs +++ b/test/YetAnotherHttpHandler.Test/UseTestServerBase.cs @@ -1,3 +1,4 @@ +using HttpClientTestServer.Launcher; using Microsoft.AspNetCore.Builder; namespace _YetAnotherHttpHandler.Test; @@ -18,14 +19,23 @@ protected UseTestServerTestBase(ITestOutputHelper testOutputHelper) }); } - protected async Task LaunchServerAsync(TestWebAppServerListenMode listenMode, Action? configure = null) - where T : ITestServerBuilder + protected virtual TestServerOptions ConfigureServerOptions(TestServerOptions options) + => options; + + protected Task LaunchServerAsync(TestServerListenMode listenMode) + => LaunchServerAsync(ConfigureServerOptions(TestServerOptions.CreateFromListenMode(listenMode))); + + protected async Task LaunchServerAsync(TestServerOptions serverOptions) { - return await TestWebAppServer.LaunchAsync(listenMode, TestOutputHelper, TimeoutToken, configure); + return await InProcessTestServer.LaunchAsync( + ConfigureServerOptions(serverOptions), + new TestOutputLoggerProvider(TestOutputHelper), + TimeoutToken + ); } public void Dispose() { _tokenRegistration.Dispose(); } -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/Usings.cs b/test/YetAnotherHttpHandler.Test/Usings.cs index 28c3087..e185109 100644 --- a/test/YetAnotherHttpHandler.Test/Usings.cs +++ b/test/YetAnotherHttpHandler.Test/Usings.cs @@ -1,3 +1,4 @@ global using Xunit; global using _YetAnotherHttpHandler.Test.Helpers; +global using HttpClientTestServer.Launcher; diff --git a/test/YetAnotherHttpHandler.Test/VersionNegotiationTest.cs b/test/YetAnotherHttpHandler.Test/VersionNegotiationTest.cs index fcf6fb1..6cc2530 100644 --- a/test/YetAnotherHttpHandler.Test/VersionNegotiationTest.cs +++ b/test/YetAnotherHttpHandler.Test/VersionNegotiationTest.cs @@ -16,14 +16,14 @@ public async Task Negotiate(NegotiationCriteria criteria) var listenMode = (serverIsHttp11 && serverIsHttp20) - ? (serverIsHttps ? TestWebAppServerListenMode.SecureHttp1AndHttp2 : throw new InvalidOperationException("To listen to HTTP/1 and HTTP/2 on a single port, TLS is required.")) + ? (serverIsHttps ? TestServerListenMode.SecureHttp1AndHttp2 : throw new InvalidOperationException("To listen to HTTP/1 and HTTP/2 on a single port, TLS is required.")) : serverIsHttp11 - ? (serverIsHttps ? TestWebAppServerListenMode.SecureHttp1Only : TestWebAppServerListenMode.InsecureHttp1Only) + ? (serverIsHttps ? TestServerListenMode.SecureHttp1Only : TestServerListenMode.InsecureHttp1Only) : serverIsHttp20 - ? (serverIsHttps ? TestWebAppServerListenMode.SecureHttp2Only : TestWebAppServerListenMode.InsecureHttp2Only) + ? (serverIsHttps ? TestServerListenMode.SecureHttp2Only : TestServerListenMode.InsecureHttp2Only) : throw new InvalidOperationException(); - await using var server = await LaunchServerAsync(listenMode); + await using var server = await LaunchServerAsync(listenMode); using var httpHandler = new YetAnotherHttpHandler() { Http2Only = criteria.ClientHttp2Only, @@ -92,4 +92,4 @@ public enum ServerListenHttpVersion } public record NegotiationCriteria(Version RequestVersion, ServerListenHttpVersion ServerListenVersions, Version ResponseVersion, bool ClientHttp2Only, bool IsHttps, bool ExpectsException); -} \ No newline at end of file +} diff --git a/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandler.Test.csproj b/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandler.Test.csproj index 872d59a..993f896 100644 --- a/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandler.Test.csproj +++ b/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandler.Test.csproj @@ -9,10 +9,11 @@ false true _$(MSBuildProjectName.Replace(" ", "_")) + $(NoWarn);xUnit1051 - + Always @@ -35,10 +36,12 @@ - + + + diff --git a/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandlerTest.cs b/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandlerTest.cs index 87b2fb0..2363801 100644 --- a/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandlerTest.cs +++ b/test/YetAnotherHttpHandler.Test/YetAnotherHttpHandlerTest.cs @@ -44,7 +44,7 @@ async Task RunAsync() // Arrange var httpHandler = new YetAnotherHttpHandler() { Http2Only = true }; var httpClient = new HttpClient(httpHandler); - await using var server = await LaunchServerAsync(TestWebAppServerListenMode.InsecureHttp2Only); + await using var server = await LaunchServerAsync(TestServerListenMode.InsecureHttp2Only); // Act var pipe = new Pipe(); @@ -162,4 +162,4 @@ public async Task SetWorkerThreads() Assert.Equal(0, NativeRuntime.Instance._refCount); } -} \ No newline at end of file +} diff --git a/test/certs/README.md b/test/certs/README.md deleted file mode 100644 index d6b7802..0000000 --- a/test/certs/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Certificates for tests - -- localhost.{crt,key,pfx}: Server certifiacte (localhost) -- client.{crt,key,pfx}: Client cerfiticate (CN=client.example.com) -- client_unknown.{crt,key,pfx}: Client cerfiticate (CN=unknown.example.com) - -## To generate client certificates - -```bash -openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out client.key -openssl req -key client.key -config client.conf -new -out client.csr -openssl x509 -req -in client.csr -CA localhost.crt -CAkey localhost.key -days 3650 -CAcreateserial -out client.crt -openssl pkcs12 -export -in client.crt -inkey client.key -out client.pfx -``` \ No newline at end of file diff --git a/test/certs/client.conf b/test/certs/client.conf deleted file mode 100644 index 0bbad16..0000000 --- a/test/certs/client.conf +++ /dev/null @@ -1,14 +0,0 @@ -[client-cert] -keyUsage = critical, digitalSignature, keyEncipherment -extendedKeyUsage = clientAuth -subjectAltName = @alt_name - -[req] -distinguished_name = dn -prompt = no - -[dn] -CN = client.example.com - -[clnt_alt_name] -email = diff --git a/test/certs/client.crt b/test/certs/client.crt deleted file mode 100644 index 9a9a210..0000000 --- a/test/certs/client.crt +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC7DCB1QIUNkpGguldG9R3BHelyLc4Gh1E8wQwDQYJKoZIhvcNAQELBQAwFDES -MBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMTAzMTA5NTc1N1oXDTMzMTAyODA5NTc1 -N1owHTEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYI -KoZIzj0DAQcDQgAEcKYOEMIsJpYKDME82T2PboLnzcCtQYJUMgZJK3Uyn4Cp+Z8Z -8LXIZIic4uF3iNh/jU7+HX0IQSXRPLCZHSws0jANBgkqhkiG9w0BAQsFAAOCAgEA -svonO0AshuqwE6Y+MBQWYSwwUz+kC9Ot6GywrUz1hxMDAeEKBPDnGFOR/qd5fMmj -6LfVALJwze57eVgmsnhcaqyJlTHN3FvKDP1WaGX5FYvlnFwpj7yADvATe7p3lW2/ -IFv2Stq6KSBkkuqrB1QKCFmUtssYQ1QJXlrBTYuCUpg/6dd81N8bsjE6XYRpJtiT -b4MuSJLENofVI2citdGgcdFD1Axckh+qIPwz2y1C5HzVx80bLgPxmo1hC6A4KGhP -LScnAtp6GgdpkNvYTEJHeY90zM7k2LcNDEASjrspwQVZhWvT50lH4z2ZlCn7A8ZF -C4cSNIR7eOs5lDkCf+z5x3vbp+uuidGEN8PfacJKf5nYepYBFZHEz0VCBnJjMZ6R -buzoemjfeN1W8EB0bdMSUhKytzhV1NabI2vqxr1Qy2syTem4Hwenk7ivodWMWjSW -WMknnDOMHVv+0AwdhZpuBdkf4ONHYszkqQQIrWpgEOfaI6YjUCvizgqJwdOE8ezf -V59eKkgSyXwloswu80wEaCzolAaK0K5BiPYznhBIHROkHzpbtEXvpVOEgxYaxxHj -PveAWmQ1FxLwjg4MXMOjp+nLu3HqNGk08446Qyo144bV3yExVfFBJS7NtBnqowcH -0xZD3k/ydOjk9Bse1RGR2y7KdJjTNkYzNFBaIukczFo= ------END CERTIFICATE----- diff --git a/test/certs/client.csr b/test/certs/client.csr deleted file mode 100644 index 4139cca..0000000 --- a/test/certs/client.csr +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIHXMH8CAQAwHTEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUuY29tMFkwEwYHKoZI -zj0CAQYIKoZIzj0DAQcDQgAEcKYOEMIsJpYKDME82T2PboLnzcCtQYJUMgZJK3Uy -n4Cp+Z8Z8LXIZIic4uF3iNh/jU7+HX0IQSXRPLCZHSws0qAAMAoGCCqGSM49BAMC -A0gAMEUCIQD6K6X3oaCCBmYAYrjSQTKYxn3U93ImWHg0Xe94//bt0gIgMpHuH7tn -iYiBRTQQP8aJAWmlz8CZRNUJu6C9JyPLDfQ= ------END CERTIFICATE REQUEST----- diff --git a/test/certs/client.key b/test/certs/client.key deleted file mode 100644 index 6881643..0000000 --- a/test/certs/client.key +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg1t2JNg3f49/Hb5kt -FrcW5rcCa30cCwz8e/JojjsGOnGhRANCAARwpg4QwiwmlgoMwTzZPY9ugufNwK1B -glQyBkkrdTKfgKn5nxnwtchkiJzi4XeI2H+NTv4dfQhBJdE8sJkdLCzS ------END PRIVATE KEY----- diff --git a/test/certs/client.pfx b/test/certs/client.pfx deleted file mode 100644 index 2bfdf53..0000000 Binary files a/test/certs/client.pfx and /dev/null differ diff --git a/test/certs/client_unknown.conf b/test/certs/client_unknown.conf deleted file mode 100644 index 7f82176..0000000 --- a/test/certs/client_unknown.conf +++ /dev/null @@ -1,14 +0,0 @@ -[client-cert] -keyUsage = critical, digitalSignature, keyEncipherment -extendedKeyUsage = clientAuth -subjectAltName = @alt_name - -[req] -distinguished_name = dn -prompt = no - -[dn] -CN = unknown.example.com - -[clnt_alt_name] -email = diff --git a/test/certs/client_unknown.crt b/test/certs/client_unknown.crt deleted file mode 100644 index d73b7d7..0000000 --- a/test/certs/client_unknown.crt +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC7TCB1gIUNkpGguldG9R3BHelyLc4Gh1E8wUwDQYJKoZIhvcNAQELBQAwFDES -MBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMTEwMTA1MDYxMVoXDTMzMTAyOTA1MDYx -MVowHjEcMBoGA1UEAwwTdW5rbm93bi5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEG -CCqGSM49AwEHA0IABHH2A8kl1b47Hr9JEc7HMi1DR25BPFiJw89zUcBV4onrCOxv -zLrPSPgp8zGAQPaF7loJrPvxiN379UOmKOifSswwDQYJKoZIhvcNAQELBQADggIB -AEiqRY2sNGQT8EHgHt9JCasI1XnyCpoUBr88vAYeeTaK1mgP6bF+NtLyPAraYZnR -ZPAFIX8iQ25Rxz+goCa/svcnsJRB8EQd7qmoADIk2V+C00jo0fU/Bnj3l1Q7twr6 -1PnanN+znOLPoWUx+P+ssEWhM2Z4hZplw/ovJGjZfp1zc6yeA3fL+J7d6CXmdv9R -DfWCPYch7GUTuXevH51ZQWUeoeaYcpVbygLCrPTG5M8Q+Aq4Ogg1VURYe2ZyVUcx -wsFVVcm97pI6gG6zGPvKBuvVyISzRpNcUIQkkrpz6+qziHQF1PnyGSLDsgFDJEig -9N3ZKnLaZu4e/vN6psd7JMX/DbqtYPSgxCxvVKbaJ/wWK85mkV9RGeP4c0wtn+aY -eP3nV6NJQ9WXXtTmzhl1epjcYQM48vKWfXgOxAdClmXV3sBfIXPKHB5EM7otHaQe -JJYYQb43SoQe48Dh5Q0SEC2LX46/Ik91AsO/jWAjf3pvwiLrypQSkOimFYuzvqfG -7lo9ncVtCyFGxMt4fUEtt/u1zDB6apIluvFT2/Ak9imtQ6Rb41l+6L3XcamIHSV2 -/HTq8lPleXXl35WgWR6emxWNWcxcnb4UnE787UdUtnuIbQDoGQuHwpBPruefTu8t -3sqIbJVu6TWNXcUI5LdcH2IAwjPE7fOQ7iOkD889qxc3 ------END CERTIFICATE----- diff --git a/test/certs/client_unknown.csr b/test/certs/client_unknown.csr deleted file mode 100644 index 241abbf..0000000 --- a/test/certs/client_unknown.csr +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIHaMIGAAgEAMB4xHDAaBgNVBAMME3Vua25vd24uZXhhbXBsZS5jb20wWTATBgcq -hkjOPQIBBggqhkjOPQMBBwNCAARx9gPJJdW+Ox6/SRHOxzItQ0duQTxYicPPc1HA -VeKJ6wjsb8y6z0j4KfMxgED2he5aCaz78Yjd+/VDpijon0rMoAAwCgYIKoZIzj0E -AwIDSQAwRgIhAPuR2XZzQ06I9ynH5iFaFxdPmGgDJdg8y93TzPyy2jDSAiEAo2AM -Xj13uVKmAof6BdF/9QLoDlSuQPCkFrDvYPzi71Q= ------END CERTIFICATE REQUEST----- diff --git a/test/certs/client_unknown.key b/test/certs/client_unknown.key deleted file mode 100644 index feb83a8..0000000 --- a/test/certs/client_unknown.key +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgnA83PApWtXl3VWg5 -xi3Qb02/92/YbPJikLO8NU1yhWyhRANCAARx9gPJJdW+Ox6/SRHOxzItQ0duQTxY -icPPc1HAVeKJ6wjsb8y6z0j4KfMxgED2he5aCaz78Yjd+/VDpijon0rM ------END PRIVATE KEY----- diff --git a/test/certs/client_unknown.pfx b/test/certs/client_unknown.pfx deleted file mode 100644 index 5a328b5..0000000 Binary files a/test/certs/client_unknown.pfx and /dev/null differ diff --git a/test/certs/localhost.crt b/test/certs/localhost.crt deleted file mode 100644 index fb72a6d..0000000 --- a/test/certs/localhost.crt +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIE9TCCAt2gAwIBAgIUUQ33LbUPwlgKXmzA77KmDbV2uYkwDQYJKoZIhvcNAQEL -BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMDcyNTAzNDYzNFoXDTMzMDcy -MjAzNDYzNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEAyuyNn36Sv87u8q7UmB7nhuMe71w6geUstcYKhO5ZahYf -d9I9mGZTKpUvThgm65nrIPT8zE7yRqrgagP+MtuRtwByt9w7lO8Y/lJda4iHaTXd -e9Yq0lZGrv0CeZ7NJZCGfPG9GJHG8Bh4IjjhMwGcNea50vfky72nuZnCdLKLbr55 -037bIQ7R2bPfxqNTo0Lcij5ApI6/YlpJZ14vi0yHDSCyTAM9PUlgv6EsYdQ3vf1C -bdg2VlnPiAyYI2f7TRZ3YBrrUU8/qcBSsPoTNYgCaBld35/3JizLZJlWukPWnbe3 -TuU9FwRv/Vh+UnD2cnv7p0+JW2coa/9Yrk/W7oSFxGoujg/fKm7O9j76JKD/04U7 -yGkizQG4uako3BTcIDgHRsDqyIp9MR2v/nbb8Xol2cHL9nE3+ovrgn9upIFvgZk+ -nAuRgAmB4IaBtMS5ih0QJnlLB5FqDj+PkJG+s8iqOphg4V3P07zAvOTk1J96VDLO -lnQHpjwMGXoYaevWHRU+Vmm2rktpTyJVt5xtlqjoN/FBnCYbQpAosS5fciN7ghcs -zCmKVKC0riCa7MwPUooVOa/TqDzv5rGPp2vFXTdKDova7OlTo2YofDd2grOwM5O7 -TQp7MHUs1gtnHSEYdMeKWi6fSbtx4Jru13blXV7MMUHaQCg2YpJIqofnXQ5+9FMC -AwEAAaM/MD0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwIwYDVR0RBBwwGoINd3d3 -LmxvY2FsaG9zdIIJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4ICAQAByseWC2Fp -K8S9c/6aHQRwJPgkq1CGMx20wid1XvD9e+F8xF//L5MPa21gx6TC/dRO3rC6Oyqt -mR011vMIh0/DMOhF8eFg9bn8dGSkUiWanw8OKsewTGzJFkoq4cDgO0hjfQTLRNnf -KlDMZLISsnPFSQnhRN7c71j0dXrG+flsazK4CFy9FtXJEePkiCyS5ZSBDkfBKerp -fif6Wz2Zk4yLwmmw0c/sNsgHkRfj3q+Zf1RgpcuUYmYbPigHSI2qpsWbqMeQmIvS -+s7Tap3sQFCYIGCvSmOV4STY2JqxeWOGgR/xLZBpfJgdllfy1mpe7dHpi0kVTEdE -cC1pNeFDn8xYm2M61oGUYy+b035HqD9SfPsnHOFzwgwINuHdL4xjmT+HwAtW+WOj -105d+aIK55gOaJPGa7Pc7UMYtN7Oc/9hWfYti0MXnsyYfCNx6Fl7jtKs1AG2BbQd -sReZj7em23DBe75I4+DCcNWQg40HXsDo2h+z+Xk3SFb/gvHMtmzFudKCDIpD0PS5 -gEXEzkKRg/++6iXGF16eBibZ8PED6416rGJz1Bo1YpXSyYCZG6oWwXZTg9fvDZX5 -FfLnQACV02y2Gs74h23Yq+QmA30Ly5GPrR5SBRaNiCY1SS7gCAfRah9zJjvbXNGw -h0Eq48Dlw12GaUww3y05/IoAJxtHxZigdQ== ------END CERTIFICATE----- diff --git a/test/certs/localhost.key b/test/certs/localhost.key deleted file mode 100644 index 311e33d..0000000 --- a/test/certs/localhost.key +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -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 -ThIs987FU8HXD54GnfB03s/HOCaUpozh ------END PRIVATE KEY----- diff --git a/test/certs/localhost.pfx b/test/certs/localhost.pfx deleted file mode 100644 index 8cb9579..0000000 Binary files a/test/certs/localhost.pfx and /dev/null differ diff --git a/test/certs/localhost.srl b/test/certs/localhost.srl deleted file mode 100644 index 91e02ab..0000000 --- a/test/certs/localhost.srl +++ /dev/null @@ -1 +0,0 @@ -364A4682E95D1BD4770477A5C8B7381A1D44F305