|
|
#if NETFRAMEWORK
using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Web;
namespace Apewer.Web.HttpProxy {
sealed class HttpHandler : IHttpHandler {
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context) { if (context.Request.HttpMethod.ToLower().Contains("options")) return;
context.Response.Buffer = true; try { Proxy(context); } catch (Exception exception) { try { context.Response.Clear(); context.Response.ContentType = "text/plain"; context.Response.Write(exception.ToString()); } catch { } } }
// const int SegmentalUrlOffset = 0;
static void Proxy(HttpContext context) { var url = GetUrl(context.Request.Url);
context.Response.Headers.Add("-Proxy-Url", url); context.Response.Headers.Add("-Proxy-Http-X-Forwarded-For", Variable("http_x_forwarded_for")); context.Response.Headers.Add("-Proxy-Remote-Addr", Variable("remote_addr"));
// 忽略跨域选项请求。
if (context.Request.HttpMethod.ToLower().Contains("options")) return;
// 阻止浏览器请求网站图标。
if (context.Request.Url.AbsolutePath.ToLower() == "/favicon.ico") return;
// 阻止搜索引擎收录。
if (context.Request.Url.AbsolutePath.ToLower() == "/robot.txt") { context.Response.ContentType = "text/plain"; context.Response.Write("User-agent: *\nDisallow: / \n"); return; }
var ShowStack = false; try { context.Response.Buffer = false;
var request = GetRequest(url, context.Request); var response = GetResponse(request);
WriteHeaders(response, context.Response); WriteStream(response, context.Response); } catch (System.Net.Sockets.SocketException exception) // 无法连接服务器。
{ context.Response.ContentType = "text/plain"; context.Response.Write(ShowStack ? exception.ToString() : exception.Message); } catch (System.Net.WebException exception) // 无法连接服务器;超时。
{ context.Response.ContentType = "text/plain"; context.Response.Write(ShowStack ? exception.ToString() : exception.Message); } catch (System.UriFormatException exception) // 链接无效。
{ context.Response.ContentType = "text/plain"; context.Response.Write(ShowStack ? exception.ToString() : exception.Message); }
context.Response.Flush(); context.Response.Close(); }
static string GetUrl(Uri uri) { var paq = uri.PathAndQuery; var array = uri.PathAndQuery.Split('/'); if (array.Length < 2) return null;
var lower = string.IsNullOrEmpty(array[1]) ? null : array[1].ToLower(); var start = 1; var fragments = new List<string>(); switch (lower) { case "http:": case "https:": fragments.Add(lower); start = 2; break; default: start = 1; var scheme = uri.Scheme.ToLower(); if (!scheme.EndsWith(":")) scheme = scheme + ":"; fragments.Add(scheme); break; } fragments.Add("");
for (var i = start; i < array.Length; i++) fragments.Add(array[i]); var url = string.Join("/", fragments.ToArray()); return url; }
static HttpWebRequest GetRequest(string url, HttpRequest input) { var https = url.ToLower().Trim().StartsWith("https"); if (https) ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateCallback);
var request = (HttpWebRequest)WebRequest.Create(url); request.Method = input.HttpMethod; request.AllowAutoRedirect = true;
request.Timeout = 60000;
// Headers
foreach (var key in input.Headers.AllKeys) { try { if (string.IsNullOrEmpty(key)) continue;
var value = input.Headers[key]; if (string.IsNullOrEmpty(value)) continue;
var lower = key.ToLower(); if (lower == "accept") continue; else if (lower == "accept-encoding") continue; else if (lower == "ali-swift-log-host") continue; else if (lower == "ali-swift-stat-host") continue; else if (lower == "cache-control") continue; else if (lower == "connection") continue; else if (lower == "dnt") continue; else if (lower == "eagleeye-traceid") continue; else if (lower == "host") continue; else if (lower == "if-modified-since") request.IfModifiedSince = new DateTime(1970, 1, 1, 0, 0, 0, 0); else if (lower == "referer") request.Referer = value; else if (lower == "timing-allow-origin") continue; else if (lower == "user-agent") request.UserAgent = value; else if (lower == "via") continue; else if (lower == "x-alicdn-da-via") continue; else request.Headers.Add(key, value); } catch { } }
// POST
if (request.Method.ToLower().Contains("post")) ReadStream(input.InputStream, request.GetRequestStream());
return request; }
static HttpWebResponse GetResponse(HttpWebRequest request) { return (HttpWebResponse)request.GetResponse(); }
static void WriteHeaders(HttpWebResponse response, HttpResponse output) { foreach (var key in response.Headers.AllKeys) { try { if (string.IsNullOrEmpty(key)) continue;
var value = response.Headers[key]; if (string.IsNullOrEmpty(value)) continue;
output.Headers.Add("-Origin-" + key, value);
var lower = key.ToLower(); if (lower == "access-control-allow-origin") continue; else if (lower == "access-control-allow-methods") continue; else if (lower == "connection") continue; else if (lower == "content-type") output.ContentType = value; else if (lower == "timing-allow-origin") continue; else if (lower == "transfer-encoding") continue; else if (lower == "x-content-type-options") continue; else output.Headers.Add(key, value); } catch { } } }
static void WriteStream(HttpWebResponse response, HttpResponse output) { ReadStream(response.GetResponseStream(), output.OutputStream); }
static bool ValidateCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { //return (errors == SslPolicyErrors.None) ? true : false;
return true; }
static string QueryString(string name) { try { if (!string.IsNullOrEmpty(name)) return HttpContext.Current.Request.QueryString[name]; } finally { } return ""; }
static Int32 GetInt32(string text) { try { if (!string.IsNullOrEmpty(text)) return Convert.ToInt32(text); } catch { } return 0; }
static long ReadStream(Stream source, Stream destination) { var buffer = 1024;
if (source == null) return 0; if (destination == null) return 0; if (!source.CanRead) return 0; if (!destination.CanWrite) return 0; if (buffer < 1) return 0;
long result = 0; try { while (true) { var temp = new byte[buffer]; var count = source.Read(temp, 0, temp.Length); if (count == 0) break; destination.Write(temp, 0, count); result += count; } } finally { } return result; }
static string Variable(string name) { var result = ""; if (!string.IsNullOrEmpty(name)) { string vname = name.ToLower(); try { result = HttpContext.Current.Request.ServerVariables[vname]; } finally { } } return result ?? ""; }
static string ClientIP() { string vip = Variable("http_x_forwarded_for"); if (string.IsNullOrEmpty(vip)) vip = Variable("remote_addr"); return vip; }
}
}
#endif
|