public async Task SendMoreThanStreamLimitRequests_Succeeds(int streamLimit) { using Http3LoopbackServer server = CreateHttp3LoopbackServer(); Task serverTask = Task.Run(async() => { using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync(); for (int i = 0; i < streamLimit + 1; ++i) { using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); await stream.HandleRequestAsync(); } }); Task clientTask = Task.Run(async() => { using HttpClient client = CreateHttpClient(); for (int i = 0; i < streamLimit + 1; ++i) { using HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = server.Address, Version = HttpVersion30, VersionPolicy = HttpVersionPolicy.RequestVersionExact }; using var response = await client.SendAsync(request).WaitAsync(TimeSpan.FromSeconds(10)); } }); await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); }
public async Task AltSvc_Header_Upgrade_Success(Version fromVersion) { // The test makes a request to a HTTP/1 or HTTP/2 server first, which supplies an Alt-Svc header pointing to the second server. using GenericLoopbackServer firstServer = fromVersion.Major switch { 1 => new LoopbackServer(new LoopbackServer.Options { UseSsl = true }), 2 => Http2LoopbackServer.CreateServer(), _ => throw new Exception("Unknown HTTP version.") }; // The second request is expected to come in on this HTTP/3 server. using var secondServer = new Http3LoopbackServer(); using HttpClient client = CreateHttpClient(); Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address); Task serverTask = firstServer.AcceptConnectionSendResponseAndCloseAsync(additionalHeaders: new[] { new HttpHeaderData("Alt-Svc", $"h3=\"{secondServer.Address.IdnHost}:{secondServer.Address.Port}\"") }); await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000); using HttpResponseMessage firstResponse = firstResponseTask.Result; Assert.True(firstResponse.IsSuccessStatusCode); await AltSvc_Upgrade_Success(firstServer, secondServer, client); }
public async Task AltSvc_ResponseFrame_UpgradeFrom20_Success() { using Http2LoopbackServer firstServer = Http2LoopbackServer.CreateServer(); using Http3LoopbackServer secondServer = new Http3LoopbackServer(); using HttpClient client = CreateHttpClient(); Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address); Task serverTask = Task.Run(async() => { using Http2LoopbackConnection connection = await firstServer.EstablishConnectionAsync(); int streamId = await connection.ReadRequestHeaderAsync(); await connection.SendDefaultResponseHeadersAsync(streamId); await connection.WriteFrameAsync(new AltSvcFrame("", $"h3=\"{secondServer.Address.IdnHost}:{secondServer.Address.Port}\"", streamId)); await connection.SendResponseDataAsync(streamId, Array.Empty <byte>(), true); }); await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000); HttpResponseMessage firstResponse = firstResponseTask.Result; Assert.True(firstResponse.IsSuccessStatusCode); await AltSvc_Upgrade_Success(firstServer, secondServer, client); }
public async Task AltSvc_ResponseFrame_UpgradeFrom20_Success() { using Http2LoopbackServer firstServer = Http2LoopbackServer.CreateServer(); using Http3LoopbackServer secondServer = new Http3LoopbackServer(); using HttpClient client = CreateHttpClient(CreateHttpClientHandler(HttpVersion.Version30)); Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address); using (Http2LoopbackConnection connection = await firstServer.EstablishConnectionAsync()) { int streamId = await connection.ReadRequestHeaderAsync(); await connection.SendDefaultResponseHeadersAsync(streamId); await connection.WriteFrameAsync(new AltSvcFrame("", $"h3={secondServer.Address.IdnHost}:{secondServer.Address.Port}", streamId)); await connection.SendResponseDataAsync(streamId, Array.Empty <byte>(), true); } HttpResponseMessage firstResponse = await firstResponseTask; Assert.True(firstResponse.IsSuccessStatusCode); await AltSvc_Upgrade_Success(firstServer, secondServer, client); }
public async Task AltSvc_ConnectionFrame_UpgradeFrom20_Success() { // [ActiveIssue("https://github.com/dotnet/runtime/issues/54050")] if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) { return; } using Http2LoopbackServer firstServer = Http2LoopbackServer.CreateServer(); using Http3LoopbackServer secondServer = CreateHttp3LoopbackServer(); using HttpClient client = CreateHttpClient(HttpVersion.Version20); Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address); Task serverTask = Task.Run(async() => { using Http2LoopbackConnection connection = await firstServer.EstablishConnectionAsync(); int streamId = await connection.ReadRequestHeaderAsync(); await connection.WriteFrameAsync(new AltSvcFrame($"https://{firstServer.Address.IdnHost}:{firstServer.Address.Port}", $"h3=\"{secondServer.Address.IdnHost}:{secondServer.Address.Port}\"", streamId: 0)); await connection.SendDefaultResponseAsync(streamId); }); await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000); HttpResponseMessage firstResponse = firstResponseTask.Result; Assert.True(firstResponse.IsSuccessStatusCode); await AltSvc_Upgrade_Success(firstServer, secondServer, client); }
private async Task AltSvc_Upgrade_Success(GenericLoopbackServer firstServer, Http3LoopbackServer secondServer, HttpClient client) { Task <HttpResponseMessage> secondResponseTask = client.GetAsync(firstServer.Address); HttpRequestData secondRequest = await secondServer.AcceptConnectionSendResponseAndCloseAsync(); string altUsed = secondRequest.GetSingleHeaderValue("Alt-Used"); Assert.Equal($"{secondServer.Address.IdnHost}:{secondServer.Address.Port}", altUsed); HttpResponseMessage secondResponse = await secondResponseTask; Assert.True(secondResponse.IsSuccessStatusCode); }
private async Task AltSvc_Upgrade_Success(GenericLoopbackServer firstServer, Http3LoopbackServer secondServer, HttpClient client) { Task <HttpResponseMessage> secondResponseTask = client.GetAsync(firstServer.Address); Task <HttpRequestData> secondRequestTask = secondServer.AcceptConnectionSendResponseAndCloseAsync(); await new[] { (Task)secondResponseTask, secondRequestTask }.WhenAllOrAnyFailed(30_000); HttpRequestData secondRequest = secondRequestTask.Result; using HttpResponseMessage secondResponse = secondResponseTask.Result; string altUsed = secondRequest.GetSingleHeaderValue("Alt-Used"); Assert.Equal($"{secondServer.Address.IdnHost}:{secondServer.Address.Port}", altUsed); Assert.True(secondResponse.IsSuccessStatusCode); }
[InlineData(10_000_000)] // 8 bytes settings value. public async Task ClientSettingsReceived_Success(int headerSizeLimit) { using Http3LoopbackServer server = CreateHttp3LoopbackServer(); Task serverTask = Task.Run(async() => { using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync(); (Http3LoopbackStream settingsStream, Http3LoopbackStream requestStream) = await connection.AcceptControlAndRequestStreamAsync(); using (settingsStream) using (requestStream) { Assert.False(settingsStream.CanWrite, "Expected unidirectional control stream."); long?streamType = await settingsStream.ReadIntegerAsync(); Assert.Equal(Http3LoopbackStream.ControlStream, streamType); List <(long settingId, long settingValue)> settings = await settingsStream.ReadSettingsAsync(); (long settingId, long settingValue) = Assert.Single(settings); Assert.Equal(Http3LoopbackStream.MaxHeaderListSize, settingId); Assert.Equal(headerSizeLimit * 1024L, settingValue); await requestStream.ReadRequestDataAsync(); await requestStream.SendResponseAsync(); } }); Task clientTask = Task.Run(async() => { using HttpClientHandler handler = CreateHttpClientHandler(); handler.MaxResponseHeadersLength = headerSizeLimit; using HttpClient client = CreateHttpClient(handler); using HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = server.Address, Version = HttpVersion30, VersionPolicy = HttpVersionPolicy.RequestVersionExact }; using HttpResponseMessage response = await client.SendAsync(request); }); await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); }
private async Task AltSvc_Header_Upgrade_Success(Version fromVersion) { using GenericLoopbackServer firstServer = GetFactoryForVersion(fromVersion).CreateServer(); using Http3LoopbackServer secondServer = new Http3LoopbackServer(); using HttpClient client = CreateHttpClient(CreateHttpClientHandler(HttpVersion.Version30)); Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address); await firstServer.AcceptConnectionSendResponseAndCloseAsync(additionalHeaders : new[] { new HttpHeaderData("Alt-Svc", $"h3={secondServer.Address.IdnHost}:{secondServer.Address.Port}") }); HttpResponseMessage firstResponse = await firstResponseTask; Assert.True(firstResponse.IsSuccessStatusCode); await AltSvc_Upgrade_Success(firstServer, secondServer, client); }
public async Task SendMoreThanStreamLimitRequests_Succeeds(int streamLimit) { // [ActiveIssue("https://github.com/dotnet/runtime/issues/55957")] if (this.UseQuicImplementationProvider == QuicImplementationProviders.Mock) { return; } using Http3LoopbackServer server = CreateHttp3LoopbackServer(new Http3Options() { MaxBidirectionalStreams = streamLimit }); Task serverTask = Task.Run(async() => { using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync(); for (int i = 0; i < streamLimit + 1; ++i) { using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); await stream.HandleRequestAsync(); } }); Task clientTask = Task.Run(async() => { using HttpClient client = CreateHttpClient(); for (int i = 0; i < streamLimit + 1; ++i) { HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = server.Address, Version = HttpVersion30, VersionPolicy = HttpVersionPolicy.RequestVersionExact }; using var response = await client.SendAsync(request).WaitAsync(TimeSpan.FromSeconds(10)); } }); await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); }
public async Task SendStreamLimitRequestsConcurrently_Succeeds(int streamLimit) { using Http3LoopbackServer server = CreateHttp3LoopbackServer(new Http3Options() { MaxBidirectionalStreams = streamLimit }); Task serverTask = Task.Run(async() => { using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync(); for (int i = 0; i < streamLimit; ++i) { using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); await stream.HandleRequestAsync(); } }); Task clientTask = Task.Run(async() => { using HttpClient client = CreateHttpClient(); var tasks = new Task <HttpResponseMessage> [streamLimit]; Parallel.For(0, streamLimit, i => { HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = server.Address, Version = HttpVersion30, VersionPolicy = HttpVersionPolicy.RequestVersionExact }; tasks[i] = client.SendAsync(request); }); var responses = await Task.WhenAll(tasks); foreach (var response in responses) { response.Dispose(); } });
public async Task AltSvc_Header_Upgrade_Success(Version fromVersion, bool overrideHost) { // [ActiveIssue("https://github.com/dotnet/runtime/issues/54050")] if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) { return; } // The test makes a request to a HTTP/1 or HTTP/2 server first, which supplies an Alt-Svc header pointing to the second server. using GenericLoopbackServer firstServer = fromVersion.Major switch { 1 => Http11LoopbackServerFactory.Singleton.CreateServer(new LoopbackServer.Options { UseSsl = true }), 2 => Http2LoopbackServer.CreateServer(), _ => throw new Exception("Unknown HTTP version.") }; // The second request is expected to come in on this HTTP/3 server. using Http3LoopbackServer secondServer = CreateHttp3LoopbackServer(); if (!overrideHost) { Assert.Equal(firstServer.Address.IdnHost, secondServer.Address.IdnHost); } using HttpClient client = CreateHttpClient(fromVersion); Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address); Task serverTask = firstServer.AcceptConnectionSendResponseAndCloseAsync(additionalHeaders: new[] { new HttpHeaderData("Alt-Svc", $"h3=\"{(overrideHost ? secondServer.Address.IdnHost : null)}:{secondServer.Address.Port}\"") }); await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000); using HttpResponseMessage firstResponse = firstResponseTask.Result; Assert.True(firstResponse.IsSuccessStatusCode); await AltSvc_Upgrade_Success(firstServer, secondServer, client); }
public async Task ReservedFrameType_Throws() { const int ReservedHttp2PriorityFrameId = 0x2; const long UnexpectedFrameErrorCode = 0x105; using Http3LoopbackServer server = CreateHttp3LoopbackServer(); Task serverTask = Task.Run(async() => { using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync(); using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); await stream.SendFrameAsync(ReservedHttp2PriorityFrameId, new byte[8]); QuicConnectionAbortedException ex = await Assert.ThrowsAsync <QuicConnectionAbortedException>(async() => { await stream.HandleRequestAsync(); using Http3LoopbackStream stream2 = await connection.AcceptRequestStreamAsync(); }); Assert.Equal(UnexpectedFrameErrorCode, ex.ErrorCode); }); Task clientTask = Task.Run(async() => { using HttpClient client = CreateHttpClient(); using HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = server.Address, Version = HttpVersion30, VersionPolicy = HttpVersionPolicy.RequestVersionExact }; await Assert.ThrowsAsync <HttpRequestException>(async() => await client.SendAsync(request)); }); await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); }