-
Notifications
You must be signed in to change notification settings - Fork 234
/
Program.cs
129 lines (102 loc) · 4.89 KB
/
Program.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
// 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.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Crank.EventSources;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Proxy
{
public class Program
{
private static HttpMessageInvoker _httpMessageInvoker;
private static string _destinationPrefix;
private static QueryString _appendQuery;
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.AddCommandLine(args)
.Build();
// The url all requests will be forwarded to
var baseUriArg = config["baseUri"];
if (String.IsNullOrWhiteSpace(baseUriArg))
{
throw new ArgumentException("--baseUri is required");
}
var baseUri = new Uri(baseUriArg);
_destinationPrefix = $"{baseUri.Scheme}://{baseUri.Authority}{baseUri.AbsolutePath.TrimEnd('/')}/";
_appendQuery = new QueryString(baseUri.Query);
Console.WriteLine($"Base URI: {baseUriArg}");
BenchmarksEventSource.MeasureAspNetVersion();
BenchmarksEventSource.MeasureNetCoreAppVersion();
var builder = new WebHostBuilder()
.ConfigureLogging(loggerFactory =>
{
// Don't enable console logging if no specific level is defined (perf)
if (Enum.TryParse(config["LogLevel"], out LogLevel logLevel))
{
Console.WriteLine($"Console Logging enabled with level '{logLevel}'");
loggerFactory.AddConsole().SetMinimumLevel(logLevel);
}
})
.UseKestrel((context, kestrelOptions) =>
{
kestrelOptions.ConfigureHttpsDefaults(httpsOptions =>
{
// [SuppressMessage("Microsoft.Security", "CSCAN0220.DefaultPasswordContexts", Justification="Benchmark code, not a secret")]
httpsOptions.ServerCertificate = new X509Certificate2(Path.Combine(context.HostingEnvironment.ContentRootPath, "testCert.pfx"), "testPassword");
});
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseConfiguration(config)
;
InitializeHttpClient();
builder = builder.Configure(app => app.Run(ProxyRequest));
builder
.Build()
.Run();
}
private static void InitializeHttpClient()
{
var httpHandler = new SocketsHttpHandler();
httpHandler.AllowAutoRedirect = false;
httpHandler.UseProxy = false;
httpHandler.AutomaticDecompression = DecompressionMethods.None;
httpHandler.UseCookies = false;
httpHandler.EnableMultipleHttp2Connections = true;
// Accept any SSL certificate
httpHandler.SslOptions.RemoteCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true;
_httpMessageInvoker = new HttpMessageInvoker(httpHandler);
}
private static async Task ProxyRequest(HttpContext context)
{
var destinationUri = MakeDestinationAddress(context.Request.Path, context.Request.QueryString.Add(_appendQuery));
using var requestMessage = context.CreateProxyHttpRequest(destinationUri);
requestMessage.VersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
requestMessage.Version = HttpVersion.Version20;
using var responseMessage = await _httpMessageInvoker.SendAsync(requestMessage, context.RequestAborted);
await context.CopyProxyHttpResponse(responseMessage);
}
private static Uri MakeDestinationAddress(PathString path, QueryString query)
{
ReadOnlySpan<char> prefixSpan = _destinationPrefix;
if (path.HasValue)
{
// When PathString has a value it always starts with a '/'. Avoid double slashes when concatenating.
prefixSpan = prefixSpan[0..^1];
}
var targetAddress = string.Concat(prefixSpan, path.ToUriComponent(), query.ToUriComponent());
return new Uri(targetAddress, UriKind.Absolute);
}
}
}