Пример #1
0
        public async Task UseClientCertOnHttp2_OSSupportsIt_Success()
        {
            using X509Certificate2 clientCert = Test.Common.Configuration.Certificates.GetClientCertificate();
            await Http2LoopbackServer.CreateClientAndServerAsync(
                async address =>
                {
                    var handler = new WinHttpHandler();
                    handler.ServerCertificateValidationCallback = CustomServerCertificateValidationCallback;
                    handler.ClientCertificates.Add(clientCert);
                    handler.ClientCertificateOption = ClientCertificateOption.Manual;
                    using (var client = new HttpClient(handler))
                    using (HttpResponseMessage response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, address) { Version = HttpVersion20.Value }))
                    {
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        Assert.True(_validationCallbackHistory.WasCalled);
                        Assert.NotEmpty(_validationCallbackHistory.CertificateChain);
                        Assert.Equal(Test.Common.Configuration.Certificates.GetServerCertificate(), _validationCallbackHistory.CertificateChain[0]);
                    }
                },
                async s =>
                {
                    await using (Http2LoopbackConnection connection = await s.EstablishConnectionAsync().ConfigureAwait(false))
                    {
                        SslStream sslStream = connection.Stream as SslStream;
                        Assert.NotNull(sslStream);
                        Assert.True(sslStream.IsMutuallyAuthenticated);
                        Assert.Equal(clientCert, sslStream.RemoteCertificate);

                        int streamId = await connection.ReadRequestHeaderAsync();
                        await connection.SendDefaultResponseAsync(streamId);
                    }
                }, new Http2Options { ClientCertificateRequired = true });
        }
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        public async Task Http2GetAsync_TrailingHeaders_NoData_EmptyResponseObserved()
        {
            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    Task <HttpResponseMessage> sendTask = client.GetAsync(server.Address);

                    Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                    int streamId = await connection.ReadRequestHeaderAsync();

                    // Response header.
                    await connection.SendDefaultResponseHeadersAsync(streamId);

                    // No data.

                    // Response trailing headers
                    await connection.SendResponseHeadersAsync(streamId, isTrailingHeader : true, headers : TrailingHeaders);

                    HttpResponseMessage response = await sendTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    Assert.Equal <byte>(Array.Empty <byte>(), await response.Content.ReadAsByteArrayAsync());

                    var trailingHeaders = GetTrailingHeaders(response);
                    Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader"));
                    Assert.Contains("World", trailingHeaders.GetValues("Hello"));
                }
        }
Пример #5
0
        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);
        }
Пример #6
0
        public async Task Http2GetAsync_NoTrailingHeaders_EmptyCollection()
        {
            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    Task <HttpResponseMessage> sendTask = client.GetAsync(server.Address);

                    Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                    int streamId = await connection.ReadRequestHeaderAsync();

                    // Response header.
                    await connection.SendDefaultResponseHeadersAsync(streamId);

                    // Response data.
                    await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes, endStream : true));

                    // Server doesn't send trailing header frame.
                    HttpResponseMessage response = await sendTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                    var trailingHeaders = GetTrailingHeaders(response);
                    Assert.NotNull(trailingHeaders);
                    Assert.Equal(0, trailingHeaders.Count());
                }
        }
Пример #7
0
        public async Task Http2GetAsync_TrailerHeaders_TrailingHeaderNoBody()
        {
            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    Task <HttpResponseMessage> sendTask = client.GetAsync(server.Address);

                    Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                    int streamId = await connection.ReadRequestHeaderAsync();

                    // Response header.
                    await connection.SendDefaultResponseHeadersAsync(streamId);

                    await connection.SendResponseHeadersAsync(streamId, endStream : true, isTrailingHeader : true, headers : TrailingHeaders);

                    HttpResponseMessage response = await sendTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                    var trailingHeaders = GetTrailingHeaders(response);
                    Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count());
                    Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader"));
                    Assert.Contains("World", trailingHeaders.GetValues("Hello"));
                }
        }
        public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Available()
        {
            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    Task <HttpResponseMessage> sendTask = client.GetAsync(server.Address, HttpCompletionOption.ResponseHeadersRead);

                    Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                    int streamId = await connection.ReadRequestHeaderAsync();

                    // Response header.
                    await connection.SendDefaultResponseHeadersAsync(streamId);

                    // Response data, missing Trailers.
                    await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes));

                    HttpResponseMessage response = await sendTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                    // Pending read on the response content.
                    var trailingHeaders = GetTrailingHeaders(response);
                    Assert.True(trailingHeaders == null || trailingHeaders.Count() == 0);

                    Stream stream = await response.Content.ReadAsStreamAsync(TestAsync);

                    Byte[] data = new Byte[100];
                    await stream.ReadAsync(data, 0, data.Length);

                    // Intermediate test - haven't reached stream EOF yet.
                    trailingHeaders = GetTrailingHeaders(response);
                    Assert.True(trailingHeaders == null || trailingHeaders.Count() == 0);

                    // Finish data stream and write out trailing headers.
                    await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes));

                    await connection.SendResponseHeadersAsync(streamId, endStream : true, isTrailingHeader : true, headers : TrailingHeaders);

                    // Read data until EOF is reached
                    while (stream.Read(data, 0, data.Length) != 0)
                    {
                        ;
                    }

                    trailingHeaders = GetTrailingHeaders(response);
                    Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count());
                    Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader"));
                    Assert.Contains("World", trailingHeaders.GetValues("Hello"));

                    // Read when already zero. Trailers shouldn't be changed.
                    stream.Read(data, 0, data.Length);

                    trailingHeaders = GetTrailingHeaders(response);
                    Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count());
                }
        }
Пример #9
0
        public async Task ReadAndWriteAfterServerHasSentEndStream_Success()
        {
            TaskCompletionSource <Stream> requestStreamTcs  = new TaskCompletionSource <Stream>(TaskCreationOptions.RunContinuationsAsynchronously);
            TaskCompletionSource <object> completeStreamTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, server.Address);
                    message.Version = new Version(2, 0);
                    message.Content = new StreamingContent(async s =>
                    {
                        await s.WriteAsync(new byte[50]);

                        requestStreamTcs.SetResult(s);

                        await completeStreamTcs.Task;
                    });

                    Task serverActions = RunServer();

                    HttpResponseMessage response = await client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead);

                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                    await serverActions;

                    Stream requestStream  = await requestStreamTcs.Task;
                    Stream responseStream = await response.Content.ReadAsStreamAsync();

                    // Successfully because endstream hasn't been read yet.
                    await requestStream.WriteAsync(new byte[50]);

                    byte[] buffer    = new byte[50];
                    int    readCount = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                    Assert.Equal(DataBytes.Length, readCount);

                    readCount = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                    Assert.Equal(0, readCount);

                    async Task RunServer()
                    {
                        Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                        int streamId = await connection.ReadRequestHeaderAsync(expectEndOfStream : false);

                        await connection.SendDefaultResponseHeadersAsync(streamId, endStream : false);

                        await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes, endStream : true));
                    };
                }
        }
Пример #10
0
        public async Task AfterReadResponseServerError_ClientRead()
        {
            TaskCompletionSource <Stream> requestStreamTcs  = new TaskCompletionSource <Stream>(TaskCreationOptions.RunContinuationsAsynchronously);
            TaskCompletionSource <object> completeStreamTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, server.Address);
                    message.Version = new Version(2, 0);
                    message.Content = new StreamingContent(async s =>
                    {
                        requestStreamTcs.SetResult(s);

                        await completeStreamTcs.Task;
                    });

                    Task <HttpResponseMessage> sendTask = client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead);

                    Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                    Stream requestStream = await requestStreamTcs.Task;
                    await requestStream.WriteAsync(new byte[50]);

                    int streamId = await connection.ReadRequestHeaderAsync(expectEndOfStream : false);

                    Frame frame = await connection.ReadDataFrameAsync();

                    // Response header.
                    await connection.SendDefaultResponseHeadersAsync(streamId);

                    // Response data.
                    await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes, endStream : false));

                    HttpResponseMessage response = await sendTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                    Stream responseStream = await response.Content.ReadAsStreamAsync();

                    // Read response data.
                    byte[] buffer    = new byte[1024];
                    int    readCount = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                    Assert.Equal(DataBytes.Length, readCount);

                    // Server sends RST_STREAM.
                    await connection.WriteFrameAsync(new RstStreamFrame(FrameFlags.EndStream, 0, streamId));

                    await Assert.ThrowsAsync <IOException>(() => responseStream.ReadAsync(buffer, 0, buffer.Length));
                }
        }
Пример #11
0
        public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted(bool responseHasContentLength)
        {
            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    Task <HttpResponseMessage> sendTask = client.GetAsync(server.Address);

                    Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                    int streamId = await connection.ReadRequestHeaderAsync();

                    // Response header.
                    if (responseHasContentLength)
                    {
                        await connection.SendResponseHeadersAsync(streamId, endStream : false, headers : new[] { new HttpHeaderData("Content-Length", DataBytes.Length.ToString()) });
                    }
                    else
                    {
                        await connection.SendDefaultResponseHeadersAsync(streamId);
                    }

                    // Response data, missing Trailers.
                    await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes));

                    // Additional trailing header frame.
                    await connection.SendResponseHeadersAsync(streamId, isTrailingHeader : true, headers : TrailingHeaders, endStream : true);

                    HttpResponseMessage response = await sendTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                    var trailingHeaders = GetTrailingHeaders(response);
                    Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count());
                    Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader"));
                    Assert.Contains("World", trailingHeaders.GetValues("Hello"));
                }
        }
Пример #12
0
        public async Task WriteRequestAfterReadResponse()
        {
            TaskCompletionSource <object> tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
                using (HttpClient client = CreateHttpClient())
                {
                    HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, server.Address);
                    message.Version = new Version(2, 0);
                    message.Content = new StreamingContent(async s =>
                    {
                        await s.WriteAsync(new byte[50]);

                        await tcs.Task;

                        await s.WriteAsync(new byte[50]);
                    }, length: null);

                    Task <HttpResponseMessage> sendTask = client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead);

                    Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

                    int streamId = await connection.ReadRequestHeaderAsync(expectEndOfStream : false);

                    Frame frame = await connection.ReadDataFrameAsync();

                    // Response header.
                    await connection.SendDefaultResponseHeadersAsync(streamId);

                    // Response data.
                    await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes, endStream : false));

                    HttpResponseMessage response = await sendTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

                    using Stream responseStream = await response.Content.ReadAsStreamAsync();

                    // Read response data.
                    byte[] buffer    = new byte[1024];
                    int    readCount = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                    Assert.Equal(DataBytes.Length, readCount);

                    // Finish sending request data.
                    tcs.SetResult(null);

                    frame = await connection.ReadDataFrameAsync();

                    // Response data.
                    await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes, endStream : true));

                    // Finish reading response data.
                    readCount = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                    Assert.Equal(DataBytes.Length, readCount);

                    readCount = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                    Assert.Equal(0, readCount);
                }
        }