2 changed files with 338 additions and 0 deletions
			
			
		@ -0,0 +1,285 @@ | 
				
			|||
#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
 | 
				
			|||
@ -0,0 +1,53 @@ | 
				
			|||
#if NETFRAMEWORK
 | 
				
			|||
 | 
				
			|||
using System; | 
				
			|||
using System.Collections.Generic; | 
				
			|||
using System.Web; | 
				
			|||
 | 
				
			|||
namespace Apewer.Web.HttpProxy | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
    /// <summary></summary>
 | 
				
			|||
    sealed class HttpModule : IHttpModule | 
				
			|||
    { | 
				
			|||
 | 
				
			|||
        /// <summary></summary>
 | 
				
			|||
        public void Dispose() { } | 
				
			|||
 | 
				
			|||
        /// <summary></summary>
 | 
				
			|||
        public void Init(HttpApplication context) | 
				
			|||
        { | 
				
			|||
            context.PreSendRequestHeaders += new EventHandler(ByContext); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        /// <summary></summary>
 | 
				
			|||
        void ByContext(object sender, EventArgs e) | 
				
			|||
        { | 
				
			|||
            var context = HttpContext.Current; | 
				
			|||
            if (context == null) return; | 
				
			|||
 | 
				
			|||
            var keys = new List<string>(); | 
				
			|||
            keys.AddRange(context.Response.Headers.AllKeys); | 
				
			|||
            if (keys.Contains("Server")) context.Response.Headers.Remove("Server"); | 
				
			|||
            if (keys.Contains("X-Powered-By")) context.Response.Headers.Remove("X-Powered-By"); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        /// <summary></summary>
 | 
				
			|||
        void ByApplication(object sender, EventArgs e) | 
				
			|||
        { | 
				
			|||
            var app = sender as HttpApplication; | 
				
			|||
            if (app == null) return; | 
				
			|||
            if (app.Request == null) return; | 
				
			|||
            if (app.Request.IsLocal == false) return; | 
				
			|||
            if (app.Context == null) return; | 
				
			|||
            if (app.Context.Response == null) return; | 
				
			|||
            if (app.Context.Response.Headers == null) return; | 
				
			|||
            var headers = app.Context.Response.Headers; | 
				
			|||
            app.Context.Response.Headers.Remove("Server"); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
#endif
 | 
				
			|||
					Loading…
					
					
				
		Reference in new issue