This article describes the C# implementation of a reverse proxy tool that can cache web pages to the local area. Share it for your reference. The specific implementation method is as follows:
Main file:
<%@ WebHandler Language="C#" Class="proxy" %> using System; using ; using ; using ; using ; using ; using ; /// <summary> ///Storing the contents of http headers and http responses in /proxy/header/ and /proxy/body/ respectively/// Create a directory in hierarchy/// </summary> public class proxy : IHttpHandler { HttpResponse Response; HttpRequest Request; HttpApplicationState Application; HttpServerUtility Server; static string proxyCacheFolder = ["proxyCacheFolder"]; static string proxyDomain = ["proxyDomain"]; static string proxyReferer = ["proxyReferer"]; bool proxyCacheDirectAccess = ["proxyCacheDirectAccess"] == "true"; int proxyCacheSeconds = (["proxyCacheSeconds"]); public void ProcessRequest(HttpContext context) { Response = ; Request = ; Application = ; Server = ; string path = ; bool delCache = ("?del") > 0; if (delCache) { path = ("?del", ); DeleteCacheFile(path); return; } bool allowCache = ["cache"] == "true"; string seconds = ["seconds"] ?? ; if (!(seconds, out proxyCacheSeconds)) { proxyCacheSeconds = 3600; } if (allowCache) { EchoData(path); } else { WebClient wc = new WebClient(); ("Referer", proxyReferer); byte[] buffer = (proxyDomain + path); = ["Content-Type"]; foreach (string key in ) { (key, [key]); } (); (buffer, 0, ); } } /// <summary> /// Clean up invalid cache /// </summary> /// <param name="d"></param> void ClearTimeoutCache(DirectoryInfo d) { if () { FileInfo[] files = (); foreach (FileInfo file in files) { TimeSpan timeSpan = - ; if ( > proxyCacheSeconds) { (); } } } } string GetCacheFolderPath(string hash) { string s = ; for (int i = 0; i <= 2; i++) { s += hash[i] + "/"; } return s; } /// <summary> /// Read the cached header and output it /// </summary> /// <param name="cacheHeaderPath"></param> void EchoCacheHeader(string cacheHeaderPath) { string[] headers = (cacheHeaderPath); for (int i = 0; i < ; i++) { string[] headerKeyValue = headers[i].Split(':'); if ( == 2) { if (headerKeyValue[0] == "Content-Type") { = headerKeyValue[1]; } (headerKeyValue[0], headerKeyValue[1]); } } } void DeleteCacheFile(string path) { string absFolder = (proxyCacheFolder); string hash = GetHashString(path); string folder = GetCacheFolderPath(hash); string cacheBodyPath = absFolder + "/body/" + folder + hash; string cacheHeaderPath = absFolder + "/header/" + folder + hash; FileInfo cacheBody = new FileInfo(cacheBodyPath); FileInfo cacheHeader = new FileInfo(cacheHeaderPath); if () { (); } if () { (); } ("delete cache file Success!\r\n" + path); } /// <summary> /// Output cache /// </summary> /// <param name="cacheHeaderPath">File path to cache header</param> /// <param name="cacheBodyPath">File path to cache body</param> /// <param name="ifTimeout">Whether to determine the file expired</param> /// <returns> Is the output successful?</returns> bool EchoCacheFile(string cacheHeaderPath, string cacheBodyPath, bool ifTimeout) { FileInfo cacheBody = new FileInfo(cacheBodyPath); FileInfo cacheHeader = new FileInfo(cacheHeaderPath); ClearTimeoutCache(); ClearTimeoutCache(); if ( && ) { if (ifTimeout) { TimeSpan timeSpan = - ; if ( < proxyCacheSeconds) { EchoCacheHeader(cacheHeaderPath); (cacheBodyPath); return true; } } else { EchoCacheHeader(cacheHeaderPath); (cacheBodyPath); return true; } } return false; } void EchoData(string path) { string absFolder = (proxyCacheFolder); string hash = GetHashString(path); string folder = GetCacheFolderPath(hash); string cacheBodyPath = absFolder + "/body/" + folder + hash; string cacheHeaderPath = absFolder + "/header/" + folder + hash; bool success; if (proxyCacheDirectAccess) { success = EchoCacheFile(cacheHeaderPath, cacheBodyPath, false); if (!success) { ("Failed to read directly from cache!"); } return; } success = EchoCacheFile(cacheHeaderPath, cacheBodyPath, true); if (success) { return; } //Update Cache File string ApplicationKey = "CacheList"; List<string> List = null; if (Application[ApplicationKey] == null) { (); Application[ApplicationKey] = List = new List<string>(1000); (); } else { List = (List<string>)Application[ApplicationKey]; } //Judge whether another process is updating the Cache File if ((hash)) { success = EchoCacheFile(cacheHeaderPath, cacheBodyPath, false); if (success) { return; } else { WebClient wc = new WebClient(); ("Referer", proxyReferer); // Subject content byte[] data = (proxyDomain + path); //Processing header = ["Content-Type"]; foreach (string key in ) { (key, [key]); } (); (data); } } else { WebClient wc = new WebClient(); ("Referer", proxyReferer); StringBuilder headersb = new StringBuilder(); (hash); // Subject content byte[] data = (proxyDomain + path); //Processing header = ["Content-Type"]; foreach (string key in ) { (key); (":"); ([key]); ("\r\n"); (key, [key]); } (); string headers = ().Trim(); if (!(absFolder + "/header/" + folder)) { (absFolder + "/header/" + folder); } StreamWriter sw = (absFolder + "/header/" + folder + hash); (headers); (); (); //Processing cached content if (!(absFolder + "/body/" + folder)) { (absFolder + "/body/" + folder); } FileStream fs = (absFolder + "/body/" + folder + hash); (data, 0, ); (); (); (hash); (data); } } string GetHashString(string path) { string md5 = GetMd5Str(path); return md5; } static string GetMd5Str(string ConvertString) { .MD5CryptoServiceProvider md5 = new .MD5CryptoServiceProvider(); string t2 = (((ConvertString)), 4, 8); t2 = ("-", ""); return t2; } public bool IsReusable { get { return false; } } }
The file is as follows:
<?xml version="1.0"?> <configuration> <configSections> <section name="RewriterConfig" type=", URLRewriter"/> </configSections> <RewriterConfig> <Rules> <RewriterRule> <LookFor>~/.*$</LookFor> <SendTo> <!--cache=true Set this path for cache--> <![CDATA[~/?cache=true&seconds=30]]> </SendTo> </RewriterRule> <RewriterRule> <LookFor>~/ajax/.*$</LookFor> <SendTo> <!--cache=false Setting this path does not allow cache--> <![CDATA[~/?cache=false]]> </SendTo> </RewriterRule> </Rules> </RewriterConfig> <appSettings> <!--#Reverse proxy settings start--> <!--Set up a site--> <add key="proxyDomain" value="http://127.0.0.1:12123/"/> <!--Cache folder--> <add key="proxyCacheFolder" value="/proxyCache/"/> <!--Cache duration--> <add key="proxyCacheSeconds" value="3600"/> <!--Setting no longer determines whether the cached file is timed out,Read directly from the cache--> <add key="proxyCacheDirectAccess" value="false"/> <!--Set up a reverse proxyReferer--> <add key="proxyReferer" value="/"/> <!--#Reverse proxy settings end--> </appSettings> <> <modules runAllManagedModulesForAllRequests="true"> <add type=", URLRewriter" name="ModuleRewriter"/> </modules> </> <> <compilation debug="true"/> </> </configuration>
I hope this article will be helpful to everyone's C# programming.