C#编写的一个反向代理工具,可以缓存网页到本地

From , 3 Years ago, written in C#, viewed 213 times.
URL https://pastebin.vip/view/bcfa8a78
  1. <%@ WebHandler Language="C#" Class="proxy" %>
  2.  
  3. using System;
  4. using System.Web;
  5. using System.Net;
  6. using System.Text;
  7. using System.IO;
  8. using System.Collections.Generic;
  9. using System.Configuration;
  10.  
  11.  
  12.  
  13. /// <summary>
  14. /// 把http headers 和 http 响应的内容 分别存储在 /proxy/header/ 和 /proxy/body/ 中
  15. /// 分层次创建目录
  16. /// </summary>
  17. public class proxy : IHttpHandler
  18. {
  19.  
  20.     HttpResponse Response;
  21.     HttpRequest Request;
  22.     HttpApplicationState Application;
  23.     HttpServerUtility Server;
  24.  
  25.     static string proxyCacheFolder = ConfigurationManager.AppSettings["proxyCacheFolder"];
  26.     static string proxyDomain = ConfigurationManager.AppSettings["proxyDomain"];
  27.     static string proxyReferer = ConfigurationManager.AppSettings["proxyReferer"];
  28.     bool proxyCacheDirectAccess = ConfigurationManager.AppSettings["proxyCacheDirectAccess"] == "true";
  29.     int proxyCacheSeconds = int.Parse(ConfigurationManager.AppSettings["proxyCacheSeconds"]);
  30.  
  31.  
  32.  
  33.     public void ProcessRequest(HttpContext context)
  34.     {
  35.         Response = context.Response;
  36.         Request = context.Request;
  37.         Application = context.Application;
  38.         Server = context.Server;
  39.  
  40.         string path = context.Request.RawUrl;
  41.         bool delCache = path.IndexOf("?del") > 0;
  42.         if (delCache)
  43.         {
  44.             path = path.Replace("?del", string.Empty);
  45.             DeleteCacheFile(path);
  46.             return;
  47.         }
  48.  
  49.  
  50.         bool allowCache = Request.QueryString["cache"] == "true";
  51.         string seconds = Request.QueryString["seconds"] ?? string.Empty;
  52.         if (!int.TryParse(seconds, out proxyCacheSeconds))
  53.         {
  54.             proxyCacheSeconds = 3600;
  55.         }
  56.  
  57.         if (allowCache)
  58.         {
  59.  
  60.             EchoData(path);
  61.         }
  62.         else
  63.         {
  64.  
  65.             WebClient wc = new WebClient();
  66.             wc.Headers.Set("Referer", proxyReferer);
  67.             byte[] buffer = wc.DownloadData(proxyDomain + path);
  68.             Response.ContentType = wc.ResponseHeaders["Content-Type"];
  69.             foreach (string key in wc.ResponseHeaders.AllKeys)
  70.             {
  71.  
  72.                 Response.Headers.Set(key, wc.ResponseHeaders[key]);
  73.             }
  74.             wc.Dispose();
  75.             Response.OutputStream.Write(buffer, 0, buffer.Length);
  76.         }
  77.  
  78.  
  79.  
  80.     }
  81.  
  82.  
  83.     /// <summary>
  84.     /// 清理失效的缓存
  85.     /// </summary>
  86.     /// <param name="d"></param>
  87.     void ClearTimeoutCache(DirectoryInfo d)
  88.     {
  89.         if (d.Exists)
  90.         {
  91.             FileInfo[] files = d.GetFiles();
  92.             foreach (FileInfo file in files)
  93.             {
  94.                 TimeSpan timeSpan = DateTime.Now - file.LastAccessTime;
  95.                 if (timeSpan.TotalSeconds > proxyCacheSeconds)
  96.                 {
  97.                     file.Delete();
  98.                 }
  99.             }
  100.         }
  101.     }
  102.  
  103.     string GetCacheFolderPath(string hash)
  104.     {
  105.         string s = string.Empty;
  106.         for (int i = 0; i <= 2; i++)
  107.         {
  108.             s += hash[i] + "/";
  109.         }
  110.  
  111.         return s;
  112.     }
  113.  
  114.     /// <summary>
  115.     /// 读取缓存的header 并输出
  116.     /// </summary>
  117.     /// <param name="cacheHeaderPath"></param>
  118.     void EchoCacheHeader(string cacheHeaderPath)
  119.     {
  120.         string[] headers = File.ReadAllLines(cacheHeaderPath);
  121.         for (int i = 0; i < headers.Length; i++)
  122.         {
  123.             string[] headerKeyValue = headers[i].Split(':');
  124.             if (headerKeyValue.Length == 2)
  125.             {
  126.                 if (headerKeyValue[0] == "Content-Type")
  127.                 {
  128.                     Response.ContentType = headerKeyValue[1];
  129.                 }
  130.                 Response.Headers.Set(headerKeyValue[0], headerKeyValue[1]);
  131.             }
  132.  
  133.         }
  134.  
  135.     }
  136.  
  137.  
  138.  
  139.     void DeleteCacheFile(string path)
  140.     {
  141.         string absFolder = Server.MapPath(proxyCacheFolder);
  142.         string hash = GetHashString(path);
  143.  
  144.         string folder = GetCacheFolderPath(hash);
  145.  
  146.         string cacheBodyPath = absFolder + "/body/" + folder + hash;
  147.         string cacheHeaderPath = absFolder + "/header/" + folder + hash;
  148.  
  149.         FileInfo cacheBody = new FileInfo(cacheBodyPath);
  150.         FileInfo cacheHeader = new FileInfo(cacheHeaderPath);
  151.  
  152.         if (cacheBody.Exists)
  153.         {
  154.             cacheBody.Delete();
  155.         }
  156.  
  157.         if (cacheHeader.Exists)
  158.         {
  159.             cacheHeader.Delete();
  160.         }
  161.  
  162.         Response.Write("delete cache file Success!\r\n" + path);
  163.     }
  164.  
  165.     /// <summary>
  166.     /// 输出缓存
  167.     /// </summary>
  168.     /// <param name="cacheHeaderPath">缓存header 的文件路径</param>
  169.     /// <param name="cacheBodyPath">缓存 body 的文件路径</param>
  170.     /// <param name="ifTimeout">是否进行判断文件过期</param>
  171.     /// <returns>是否输出成功</returns>
  172.     bool EchoCacheFile(string cacheHeaderPath, string cacheBodyPath, bool ifTimeout)
  173.     {
  174.         FileInfo cacheBody = new FileInfo(cacheBodyPath);
  175.         FileInfo cacheHeader = new FileInfo(cacheHeaderPath);
  176.  
  177.         ClearTimeoutCache(cacheBody.Directory);
  178.         ClearTimeoutCache(cacheHeader.Directory);
  179.  
  180.         if (cacheBody.Exists && cacheHeader.Exists)
  181.         {
  182.  
  183.             if (ifTimeout)
  184.             {
  185.                 TimeSpan timeSpan = DateTime.Now - cacheBody.LastWriteTime;
  186.                 if (timeSpan.TotalSeconds < proxyCacheSeconds)
  187.                 {
  188.                     EchoCacheHeader(cacheHeaderPath);
  189.  
  190.                     Response.TransmitFile(cacheBodyPath);
  191.                     return true;
  192.                 }
  193.             }
  194.             else
  195.             {
  196.                 EchoCacheHeader(cacheHeaderPath);
  197.  
  198.                 Response.TransmitFile(cacheBodyPath);
  199.                 return true;
  200.             }
  201.  
  202.         }
  203.  
  204.         return false;
  205.     }
  206.  
  207.     void EchoData(string path)
  208.     {
  209.  
  210.         string absFolder = Server.MapPath(proxyCacheFolder);
  211.         string hash = GetHashString(path);
  212.  
  213.         string folder = GetCacheFolderPath(hash);
  214.  
  215.         string cacheBodyPath = absFolder + "/body/" + folder + hash;
  216.         string cacheHeaderPath = absFolder + "/header/" + folder + hash;
  217.  
  218.         bool success;
  219.         if (proxyCacheDirectAccess)
  220.         {
  221.             success = EchoCacheFile(cacheHeaderPath, cacheBodyPath, false);
  222.             if (!success)
  223.             {
  224.                 Response.Write("直接从缓存读取失败!");
  225.             }
  226.             return;
  227.         }
  228.  
  229.         success = EchoCacheFile(cacheHeaderPath, cacheBodyPath, true);
  230.  
  231.         if (success)
  232.         {
  233.             return;
  234.         }
  235.  
  236.  
  237.  
  238.  
  239.         //更新Cache File
  240.         string ApplicationKey = "CacheList";
  241.         List<string> List = null;
  242.  
  243.  
  244.         if (Application[ApplicationKey] == null)
  245.         {            
  246.             Application.Lock();
  247.             Application[ApplicationKey] = List = new List<string>(1000);
  248.             Application.UnLock();
  249.         }
  250.         else
  251.         {
  252.  
  253.             List = (List<string>)Application[ApplicationKey];
  254.  
  255.         }
  256.  
  257.  
  258.         //判断是否已有另一个进程正在更新Cache File
  259.         if (List.Contains(hash))
  260.         {
  261.             success = EchoCacheFile(cacheHeaderPath, cacheBodyPath, false);
  262.             if (success)
  263.             {
  264.                 return;
  265.             }
  266.             else
  267.             {
  268.  
  269.                 WebClient wc = new WebClient();
  270.                 wc.Headers.Set("Referer", proxyReferer);
  271.                 //主体内容
  272.                 byte[] data = wc.DownloadData(proxyDomain + path);
  273.  
  274.                 //处理header
  275.                 Response.ContentType = wc.ResponseHeaders["Content-Type"];
  276.                 foreach (string key in wc.ResponseHeaders.AllKeys)
  277.                 {
  278.                     Response.Headers.Set(key, wc.ResponseHeaders[key]);
  279.                 }
  280.                 wc.Dispose();
  281.                 Response.BinaryWrite(data);
  282.                
  283.             }
  284.         }
  285.         else
  286.         {
  287.  
  288.          
  289.  
  290.  
  291.             WebClient wc = new WebClient();
  292.             wc.Headers.Set("Referer", proxyReferer);
  293.             StringBuilder headersb = new StringBuilder();
  294.  
  295.             List.Add(hash);
  296.             //主体内容
  297.             byte[] data = wc.DownloadData(proxyDomain + path);
  298.  
  299.  
  300.  
  301.  
  302.  
  303.             //处理header
  304.  
  305.             Response.ContentType = wc.ResponseHeaders["Content-Type"];
  306.             foreach (string key in wc.ResponseHeaders.AllKeys)
  307.             {
  308.                 headersb.Append(key);
  309.                 headersb.Append(":");
  310.                 headersb.Append(wc.ResponseHeaders[key]);
  311.                 headersb.Append("\r\n");
  312.                 Response.Headers.Set(key, wc.ResponseHeaders[key]);
  313.             }
  314.             wc.Dispose();
  315.  
  316.             string headers = headersb.ToString().Trim();
  317.             if (!Directory.Exists(absFolder + "/header/" + folder))
  318.             {
  319.                 Directory.CreateDirectory(absFolder + "/header/" + folder);
  320.             }
  321.  
  322.             StreamWriter sw = File.CreateText(absFolder + "/header/" + folder + hash);
  323.             sw.Write(headers);
  324.             sw.Close();
  325.             sw.Dispose();
  326.  
  327.  
  328.             //处理缓存内容
  329.             if (!Directory.Exists(absFolder + "/body/" + folder))
  330.             {
  331.                 Directory.CreateDirectory(absFolder + "/body/" + folder);
  332.             }
  333.  
  334.             FileStream fs = File.Create(absFolder + "/body/" + folder + hash);
  335.             fs.Write(data, 0, data.Length);
  336.             fs.Close();
  337.             fs.Dispose();
  338.  
  339.             List.Remove(hash);
  340.            
  341.          
  342.  
  343.             Response.BinaryWrite(data);
  344.         }
  345.     }
  346.  
  347.  
  348.  
  349.  
  350.     string GetHashString(string path)
  351.     {
  352.         string md5 = GetMd5Str(path);
  353.         return md5;
  354.     }
  355.  
  356.  
  357.     static string GetMd5Str(string ConvertString)
  358.     {
  359.         System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
  360.         string t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(ConvertString)), 4, 8);
  361.         t2 = t2.Replace("-", "");
  362.  
  363.         return t2;
  364.     }
  365.  
  366.  
  367.     public bool IsReusable
  368.     {
  369.         get
  370.         {
  371.             return false;
  372.         }
  373.     }
  374.  
  375. }
  376.  
  377.  
  378. //csharp/6299

Reply to " C#编写的一个反向代理工具,可以缓存网页到本地"

Here you can reply to the paste above

captcha

https://burned.cc - Burn After Reading Website