React to Testing#280.
This commit is contained in:
parent
c83f606b22
commit
3084227314
|
|
@ -1,6 +1,6 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26510.0
|
||||
VisualStudioVersion = 15.0.26621.2
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7972A5D6-3385-4127-9277-428506DD44FF}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
|
@ -20,7 +20,6 @@ EndProject
|
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0EF2ACDF-012F-4472-A13A-4272419E2903}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
test\shared\DummyApplication.cs = test\shared\DummyApplication.cs
|
||||
test\shared\HttpClientSlim.cs = test\shared\HttpClientSlim.cs
|
||||
test\shared\HttpParsingData.cs = test\shared\HttpParsingData.cs
|
||||
test\shared\KestrelTestLoggerProvider.cs = test\shared\KestrelTestLoggerProvider.cs
|
||||
test\shared\LifetimeNotImplemented.cs = test\shared\LifetimeNotImplemented.cs
|
||||
|
|
@ -270,4 +269,7 @@ Global
|
|||
{D95A7EC3-48AC-4D03-B2E2-0DA3E13BD3A4} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
{4F1C30F8-CCAA-48D7-9DF6-2A84021F5BCC} = {D3273454-EA07-41D2-BF0B-FCC3675C2483}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -1,109 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
||||
{
|
||||
public class HttpClientSlimTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetStringAsyncHttp()
|
||||
{
|
||||
using (var host = StartHost())
|
||||
{
|
||||
Assert.Equal("test", await HttpClientSlim.GetStringAsync(host.GetUri()));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetStringAsyncHttps()
|
||||
{
|
||||
using (var host = StartHost(protocol: "https"))
|
||||
{
|
||||
Assert.Equal("test", await HttpClientSlim.GetStringAsync(host.GetUri(isHttps: true), validateCertificate: false));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetStringAsyncThrowsForErrorResponse()
|
||||
{
|
||||
using (var host = StartHost(statusCode: StatusCodes.Status500InternalServerError))
|
||||
{
|
||||
await Assert.ThrowsAnyAsync<HttpRequestException>(() => HttpClientSlim.GetStringAsync(host.GetUri()));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostAsyncHttp()
|
||||
{
|
||||
using (var host = StartHost(handler: (context) => context.Request.Body.CopyToAsync(context.Response.Body)))
|
||||
{
|
||||
Assert.Equal("test post", await HttpClientSlim.PostAsync(host.GetUri(), new StringContent("test post")));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostAsyncHttps()
|
||||
{
|
||||
using (var host = StartHost(protocol: "https",
|
||||
handler: (context) => context.Request.Body.CopyToAsync(context.Response.Body)))
|
||||
{
|
||||
Assert.Equal("test post", await HttpClientSlim.PostAsync(host.GetUri(isHttps: true),
|
||||
new StringContent("test post"), validateCertificate: false));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostAsyncThrowsForErrorResponse()
|
||||
{
|
||||
using (var host = StartHost(statusCode: StatusCodes.Status500InternalServerError))
|
||||
{
|
||||
await Assert.ThrowsAnyAsync<HttpRequestException>(
|
||||
() => HttpClientSlim.PostAsync(host.GetUri(), new StringContent("")));
|
||||
}
|
||||
}
|
||||
|
||||
private IWebHost StartHost(string protocol = "http", int statusCode = StatusCodes.Status200OK, Func<HttpContext, Task> handler = null)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
|
||||
{
|
||||
if (protocol == "https")
|
||||
{
|
||||
listenOptions.UseHttps(TestResources.TestCertificatePath, "testPassword");
|
||||
}
|
||||
});
|
||||
})
|
||||
.Configure((app) =>
|
||||
{
|
||||
app.Run(context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
if (handler == null)
|
||||
{
|
||||
return context.Response.WriteAsync("test");
|
||||
}
|
||||
else
|
||||
{
|
||||
return handler(context);
|
||||
}
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
host.Start();
|
||||
return host;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,24 +10,11 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
{
|
||||
public static class IWebHostPortExtensions
|
||||
{
|
||||
public static string GetHost(this IWebHost host, bool isHttps = false)
|
||||
{
|
||||
return host.GetUri(isHttps).Host;
|
||||
}
|
||||
|
||||
public static int GetPort(this IWebHost host)
|
||||
{
|
||||
return host.GetPorts().First();
|
||||
}
|
||||
|
||||
public static int GetPort(this IWebHost host, string scheme)
|
||||
{
|
||||
return host.GetUris()
|
||||
.Where(u => u.Scheme.Equals(scheme, StringComparison.OrdinalIgnoreCase))
|
||||
.Select(u => u.Port)
|
||||
.First();
|
||||
}
|
||||
|
||||
public static IEnumerable<int> GetPorts(this IWebHost host)
|
||||
{
|
||||
return host.GetUris()
|
||||
|
|
@ -39,27 +26,5 @@ namespace Microsoft.AspNetCore.Hosting
|
|||
return host.ServerFeatures.Get<IServerAddressesFeature>().Addresses
|
||||
.Select(a => new Uri(a));
|
||||
}
|
||||
|
||||
public static Uri GetUri(this IWebHost host, bool isHttps = false)
|
||||
{
|
||||
var uri = host.GetUris().First();
|
||||
|
||||
if (isHttps && uri.Scheme == "http")
|
||||
{
|
||||
var uriBuilder = new UriBuilder(uri)
|
||||
{
|
||||
Scheme = "https",
|
||||
};
|
||||
|
||||
if (uri.Port == 80)
|
||||
{
|
||||
uriBuilder.Port = 443;
|
||||
}
|
||||
|
||||
return uriBuilder.Uri;
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Authentication;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Testing
|
||||
{
|
||||
// Lightweight version of HttpClient implemented using Socket and SslStream
|
||||
public static class HttpClientSlim
|
||||
{
|
||||
public static async Task<string> GetStringAsync(string requestUri, bool validateCertificate = true)
|
||||
=> await GetStringAsync(new Uri(requestUri), validateCertificate).ConfigureAwait(false);
|
||||
|
||||
public static async Task<string> GetStringAsync(Uri requestUri, bool validateCertificate = true)
|
||||
{
|
||||
using (var stream = await GetStream(requestUri, validateCertificate).ConfigureAwait(false))
|
||||
{
|
||||
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize: 1024, leaveOpen: true))
|
||||
{
|
||||
await writer.WriteAsync($"GET {requestUri.PathAndQuery} HTTP/1.0\r\n").ConfigureAwait(false);
|
||||
await writer.WriteAsync($"Host: {requestUri.Authority}\r\n").ConfigureAwait(false);
|
||||
await writer.WriteAsync("\r\n").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await ReadResponse(stream).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> PostAsync(string requestUri, HttpContent content, bool validateCertificate = true)
|
||||
=> await PostAsync(new Uri(requestUri), content, validateCertificate).ConfigureAwait(false);
|
||||
|
||||
public static async Task<string> PostAsync(Uri requestUri, HttpContent content, bool validateCertificate = true)
|
||||
{
|
||||
using (var stream = await GetStream(requestUri, validateCertificate))
|
||||
{
|
||||
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize: 1024, leaveOpen: true))
|
||||
{
|
||||
await writer.WriteAsync($"POST {requestUri.PathAndQuery} HTTP/1.0\r\n").ConfigureAwait(false);
|
||||
await writer.WriteAsync($"Host: {requestUri.Authority}\r\n").ConfigureAwait(false);
|
||||
await writer.WriteAsync($"Content-Type: {content.Headers.ContentType}\r\n").ConfigureAwait(false);
|
||||
await writer.WriteAsync($"Content-Length: {content.Headers.ContentLength}\r\n").ConfigureAwait(false);
|
||||
await writer.WriteAsync("\r\n").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await content.CopyToAsync(stream).ConfigureAwait(false);
|
||||
|
||||
return await ReadResponse(stream).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<string> ReadResponse(Stream stream)
|
||||
{
|
||||
using (var reader = new StreamReader(stream, Encoding.ASCII, detectEncodingFromByteOrderMarks: true,
|
||||
bufferSize: 1024, leaveOpen: true))
|
||||
{
|
||||
var response = await reader.ReadToEndAsync().ConfigureAwait(false);
|
||||
|
||||
var status = GetStatus(response);
|
||||
new HttpResponseMessage(status).EnsureSuccessStatusCode();
|
||||
|
||||
var body = response.Substring(response.IndexOf("\r\n\r\n") + 4);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static HttpStatusCode GetStatus(string response)
|
||||
{
|
||||
var statusStart = response.IndexOf(' ') + 1;
|
||||
var statusEnd = response.IndexOf(' ', statusStart) - 1;
|
||||
var statusLength = statusEnd - statusStart + 1;
|
||||
return (HttpStatusCode)int.Parse(response.Substring(statusStart, statusLength));
|
||||
}
|
||||
|
||||
private static async Task<Stream> GetStream(Uri requestUri, bool validateCertificate)
|
||||
{
|
||||
var socket = await GetSocket(requestUri);
|
||||
var stream = new NetworkStream(socket, ownsSocket: true);
|
||||
|
||||
if (requestUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var sslStream = new SslStream(stream, leaveInnerStreamOpen: false, userCertificateValidationCallback:
|
||||
validateCertificate ? null : (RemoteCertificateValidationCallback)((a, b, c, d) => true));
|
||||
|
||||
await sslStream.AuthenticateAsClientAsync(requestUri.Host, clientCertificates: null,
|
||||
enabledSslProtocols: SslProtocols.Tls11 | SslProtocols.Tls12,
|
||||
checkCertificateRevocation: validateCertificate).ConfigureAwait(false);
|
||||
return sslStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<Socket> GetSocket(Uri requestUri)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<Socket>();
|
||||
|
||||
var socketArgs = new SocketAsyncEventArgs();
|
||||
socketArgs.RemoteEndPoint = new DnsEndPoint(requestUri.DnsSafeHost, requestUri.Port);
|
||||
socketArgs.Completed += (s, e) => tcs.TrySetResult(e.ConnectSocket);
|
||||
|
||||
// Must use static ConnectAsync(), since instance Connect() does not support DNS names on OSX/Linux.
|
||||
if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, socketArgs))
|
||||
{
|
||||
await tcs.Task.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var socket = socketArgs.ConnectSocket;
|
||||
|
||||
if (socket == null)
|
||||
{
|
||||
throw new SocketException((int)socketArgs.SocketError);
|
||||
}
|
||||
else
|
||||
{
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue