#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(); 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