实现proxy.pac

This commit is contained in:
老九 2021-09-14 21:46:22 +08:00
parent bc7a0b7084
commit 91a5ebbcee
5 changed files with 61 additions and 22 deletions

View File

@ -102,5 +102,14 @@ namespace FastGithub.Configuration
return key == null ? null : this.domainConfigs[key];
}
}
/// <summary>
/// 获取所有域名表达式
/// </summary>
/// <returns></returns>
public string[] GetDomainPatterns()
{
return this.domainConfigs.Keys.Select(item => item.ToString()).ToArray();
}
}
}

View File

@ -50,11 +50,15 @@ namespace FastGithub.Dns
return;
}
var httpProxyPort = this.options.Value.HttpProxyPort;
var loopbackProxyUri = new Uri($"http://127.0.0.1:{httpProxyPort}");
var localhostProxyUri = new Uri($"http://localhost:{httpProxyPort}");
foreach (var domain in this.options.Value.DomainConfigs.Keys)
{
var destination = new Uri($"https://{domain.Replace('*', 'a')}");
var proxyServer = systemProxy.GetProxy(destination);
if (proxyServer != null)
if (proxyServer != null && proxyServer != loopbackProxyUri && proxyServer != localhostProxyUri)
{
this.logger.LogError($"由于系统配置了{proxyServer}代理{domain}{nameof(FastGithub)}无法加速相关域名");
}

View File

@ -7,6 +7,7 @@ using System.IO.Pipelines;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Yarp.ReverseProxy.Forwarder;
@ -20,7 +21,7 @@ namespace FastGithub.ReverseProxy
private readonly FastGithubConfig fastGithubConfig;
private readonly IDomainResolver domainResolver;
private readonly IHttpForwarder httpForwarder;
private readonly SocketsHttpHandler socketsHttpHandler = new() { UseCookies = false, UseProxy = false, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None };
private readonly HttpMessageInvoker httpClient;
/// <summary>
/// http代理中间件
@ -36,6 +37,7 @@ namespace FastGithub.ReverseProxy
this.fastGithubConfig = fastGithubConfig;
this.domainResolver = domainResolver;
this.httpForwarder = httpForwarder;
this.httpClient = new HttpMessageInvoker(CreateHttpHandler(), disposeHandler: false);
}
/// <summary>
@ -45,11 +47,26 @@ namespace FastGithub.ReverseProxy
/// <returns></returns>
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Method != HttpMethods.Connect)
if (context.Request.Method == HttpMethods.Get && context.Request.Path == "/proxy.pac")
{
var buidler = new StringBuilder();
buidler.AppendLine("function FindProxyForURL(url, host){");
buidler.AppendLine($" var proxy = 'PROXY {context.Request.Host}';");
foreach (var domain in this.fastGithubConfig.GetDomainPatterns())
{
buidler.AppendLine($" if (shExpMatch(host, '{domain}')) return proxy;");
}
buidler.AppendLine(" return 'DIRECT';");
buidler.AppendLine("}");
var pacString = buidler.ToString();
context.Response.ContentType = "application/x-ns-proxy-autoconfig";
await context.Response.WriteAsync(pacString);
}
else if (context.Request.Method != HttpMethods.Connect)
{
var httpClient = new HttpMessageInvoker(this.socketsHttpHandler, false);
var destinationPrefix = $"{context.Request.Scheme}://{context.Request.Host}";
await this.httpForwarder.SendAsync(context, destinationPrefix, httpClient);
await this.httpForwarder.SendAsync(context, destinationPrefix, this.httpClient);
}
else
{
@ -102,5 +119,21 @@ namespace FastGithub.ReverseProxy
address = await this.domainResolver.ResolveAsync(new DnsEndPoint(targetHost, targetPort));
return new IPEndPoint(address, targetPort);
}
/// <summary>
/// 创建httpHandler
/// </summary>
/// <returns></returns>
private static SocketsHttpHandler CreateHttpHandler()
{
return new()
{
Proxy = null,
UseProxy = false,
UseCookies = false,
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None
};
}
}
}

View File

@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Runtime.CompilerServices;
namespace FastGithub
{

View File

@ -49,25 +49,17 @@ namespace FastGithub
/// <param name="app"></param>
public void Configure(IApplicationBuilder app)
{
if (OperatingSystem.IsWindows())
var httpProxyPort = app.ApplicationServices.GetRequiredService<IOptions<FastGithubOptions>>().Value.HttpProxyPort;
app.MapWhen(context => context.Connection.LocalPort == httpProxyPort, appBuilder =>
{
app.UseRequestLogging();
app.UseHttpReverseProxy();
}
else
{
var httpProxyPort = app.ApplicationServices.GetRequiredService<IOptions<FastGithubOptions>>().Value.HttpProxyPort;
app.MapWhen(context => context.Connection.LocalPort == httpProxyPort, appBuilder =>
{
appBuilder.UseHttpProxy();
});
appBuilder.UseHttpProxy();
});
app.MapWhen(context => context.Connection.LocalPort != httpProxyPort, appBuilder =>
{
appBuilder.UseRequestLogging();
appBuilder.UseHttpReverseProxy();
});
}
app.MapWhen(context => context.Connection.LocalPort != httpProxyPort, appBuilder =>
{
appBuilder.UseRequestLogging();
appBuilder.UseHttpReverseProxy();
});
}
}
}