-
Notifications
You must be signed in to change notification settings - Fork 838
/
TestEnvironment.cs
152 lines (140 loc) · 6.41 KB
/
TestEnvironment.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.ReverseProxy.Abstractions;
using Microsoft.ReverseProxy.Utilities.Tests;
using System.Text;
namespace Microsoft.ReverseProxy.Common
{
public class TestEnvironment
{
private readonly Action<IServiceCollection> _configureDestinationServices;
private readonly Action<IApplicationBuilder> _configureDestinationApp;
private readonly Action<IReverseProxyBuilder> _configureProxy;
private readonly Action<IApplicationBuilder> _configureProxyApp;
private readonly HttpProtocols _proxyProtocol;
private readonly bool _useHttpsOnDestination;
private readonly Encoding _headerEncoding;
public string ClusterId { get; set; } = "cluster1";
public TestEnvironment(
RequestDelegate destinationGetDelegate,
Action<IReverseProxyBuilder> configureProxy, Action<IApplicationBuilder> configureProxyApp,
HttpProtocols proxyProtocol = HttpProtocols.Http1AndHttp2, bool useHttpsOnDestination = false, Encoding headerEncoding = null)
: this(
destinationServices => { },
destinationApp =>
{
destinationApp.Use(async (context, next) => await destinationGetDelegate(context));
},
configureProxy,
configureProxyApp,
proxyProtocol,
useHttpsOnDestination,
headerEncoding)
{ }
public TestEnvironment(
Action<IServiceCollection> configureDestinationServices, Action<IApplicationBuilder> configureDestinationApp,
Action<IReverseProxyBuilder> configureProxy, Action<IApplicationBuilder> configureProxyApp,
HttpProtocols proxyProtocol = HttpProtocols.Http1AndHttp2, bool useHttpsOnDestination = false, Encoding headerEncoding = null)
{
_configureDestinationServices = configureDestinationServices;
_configureDestinationApp = configureDestinationApp;
_configureProxy = configureProxy;
_configureProxyApp = configureProxyApp;
_proxyProtocol = proxyProtocol;
_useHttpsOnDestination = useHttpsOnDestination;
_headerEncoding = headerEncoding;
}
public async Task Invoke(Func<string, Task> clientFunc, CancellationToken cancellationToken = default)
{
using var destination = CreateHost(HttpProtocols.Http1AndHttp2, _useHttpsOnDestination, _headerEncoding, _configureDestinationServices, _configureDestinationApp);
await destination.StartAsync(cancellationToken);
using var proxy = CreateProxy(_proxyProtocol, _useHttpsOnDestination, _headerEncoding, ClusterId, destination.GetAddress(), _configureProxy, _configureProxyApp);
await proxy.StartAsync(cancellationToken);
try
{
await clientFunc(proxy.GetAddress());
}
finally
{
await proxy.StopAsync(cancellationToken);
await destination.StopAsync(cancellationToken);
}
}
public static IHost CreateProxy(HttpProtocols protocols, bool useHttps, Encoding headerEncoding, string clusterId, string destinationAddress,
Action<IReverseProxyBuilder> configureProxy, Action<IApplicationBuilder> configureProxyApp)
{
return CreateHost(protocols, false, headerEncoding,
services =>
{
var proxyRoute = new ProxyRoute
{
RouteId = "route1",
ClusterId = clusterId,
Match = new ProxyMatch { Path = "/{**catchall}" }
};
var cluster = new Cluster
{
Id = clusterId,
Destinations = new Dictionary<string, Destination>(StringComparer.OrdinalIgnoreCase)
{
{ "destination1", new Destination() { Address = destinationAddress } }
},
HttpClient = new ProxyHttpClientOptions
{
DangerousAcceptAnyServerCertificate = useHttps
}
};
var proxyBuilder = services.AddReverseProxy().LoadFromMemory(new[] { proxyRoute }, new[] { cluster });
configureProxy(proxyBuilder);
},
app =>
{
configureProxyApp(app);
app.UseRouting();
app.UseEndpoints(builder =>
{
builder.MapReverseProxy();
});
});
}
private static IHost CreateHost(HttpProtocols protocols, bool useHttps, Encoding headerEncoding,
Action<IServiceCollection> configureServices, Action<IApplicationBuilder> configureApp)
{
return new HostBuilder()
.ConfigureWebHost(webHostBuilder =>
{
webHostBuilder
.ConfigureServices(configureServices)
.UseKestrel(kestrel =>
{
#if NET
if (headerEncoding != null)
{
kestrel.RequestHeaderEncodingSelector = _ => headerEncoding;
}
#endif
kestrel.Listen(IPAddress.Loopback, 0, listenOptions =>
{
listenOptions.Protocols = protocols;
if (useHttps)
{
listenOptions.UseHttps(TestResources.GetTestCertificate());
}
});
})
.Configure(configureApp);
}).Build();
}
}
}