-
-
Save tuxfamily/9871d437dd8a787c9e855f6b288a4c22 to your computer and use it in GitHub Desktop.
Defines a simple pass-through proxy interface for C#.NET (IIS) Server applications and web sites.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ WebHandler Language="C#" Class="PassThruProxy" Debug="true" %> | |
using System; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Text; | |
using System.Web; | |
/** | |
* <summary><c>PassThruProxy</c> is a simple pass-through proxy interface for C#.NET (IIS Servers).</summary> | |
* <remarks> | |
* The <c>PassThruProxy</c> class acts as a simple pass-through proxy as it does not have a mechanism for | |
* filtering a passed URL through a human-moderated list. The pass-through proxy works best on trusted | |
* networks where only trusted programs would ever access the proxy. For any outward-facing applications with | |
* a need for a proxy, a more robust solution with URL filtering would be suggested. | |
* </remarks> | |
*/ | |
public class PassThruProxy : IHttpHandler { | |
/** | |
* <summary>The constructor for the <see cref="PassThruProxy"/> Class.</summary> | |
*/ | |
public PassThruProxy( ) { } | |
/** | |
* <summary> | |
* <c>ProcessRequest</c> overrides the <see cref="IHttpHandler.ProcessRequest"/> method to process a | |
* request. | |
* </summary> | |
* <remarks> | |
* The <c>ProcessRequest</c> method enables the processing of HTTP Web requests on the passed | |
* <see cref="HttpContext"/> so that it can be analyzed, parsed, and processed for the proxy to | |
* forward the request. | |
* </remarks> | |
* <param name="Context">The <see cref="HttpContext"/> that needs to be processed for proxying.</param> | |
* <seealso cref="IHttpHandler.ProcessRequest"/> | |
*/ | |
public void ProcessRequest( HttpContext Context ) { | |
/* Create variables to hold the request and response. */ | |
HttpRequest Request = Context.Request; | |
HttpResponse Response = Context.Response; | |
string URI = null; | |
/* Attempt to get the URI the proxy is to pass along or fail. */ | |
try { | |
URI = Request.Url.Query.Substring( 1 ); | |
} catch ( Exception Passless ) { | |
Response.StatusCode = 500; | |
Response.StatusDescription = "Parameter Missing"; | |
Response.Write( "The parameter that makes this proxy worthwhile and functioning was not given." ); | |
Response.End( ); | |
return; | |
} | |
/* Create an HttpWebRequest to send the URI on and process results. */ | |
System.Net.HttpWebRequest ProxyRequest = ( System.Net.HttpWebRequest )System.Net.HttpWebRequest.Create( URI ); | |
/* Set the appropriate values to the request methods. */ | |
ProxyRequest.Method = Request.HttpMethod; | |
ProxyRequest.ServicePoint.Expect100Continue = false; | |
ProxyRequest.Referer = Request.Headers[ "referer" ]; | |
/* Set the body of ProxyRequest for POST requests to the proxy. */ | |
if ( Request.InputStream.Length > 0 ) { | |
/* | |
* Since we are using the same request method as the original request, and that is | |
* a POST, the values to send on in the new request must be grabbed from the | |
* original POSTed request. | |
*/ | |
byte[ ] Bytes = new byte[ Request.InputStream.Length ]; | |
Request.InputStream.Read( Bytes, 0, ( int )Request.InputStream.Length ); | |
ProxyRequest.ContentLength = Bytes.Length; | |
string ContentType = Request.ContentType; | |
if ( String.IsNullOrEmpty( ContentType ) ) { | |
ProxyRequest.ContentType = "application/x-www-form-urlencoded"; | |
} else { | |
ProxyRequest.ContentType = ContentType; | |
} | |
using ( Stream OutputStream = ProxyRequest.GetRequestStream( ) ) { | |
OutputStream.Write( Bytes, 0, Bytes.Length ); | |
} | |
} else { | |
/* | |
* When the original request is a GET, things are much easier, as we need only to | |
* pass the URI we collected earlier which will still have any parameters | |
* associated with the request attached to it. | |
*/ | |
ProxyRequest.Method = "GET"; | |
} | |
System.Net.WebResponse ServerResponse = null; | |
/* Send the proxy request to the remote server or fail. */ | |
try { | |
ServerResponse = ProxyRequest.GetResponse( ); | |
} catch ( System.Net.WebException WebEx ) { | |
Response.StatusCode = 500; | |
Response.StatusDescription = WebEx.Status.ToString( ); | |
Response.Write( WebEx.Response ); | |
Response.End( ); | |
return; | |
} | |
/* Set up the response to the client if there is one to set up. */ | |
if ( ServerResponse != null ) { | |
Response.ContentType = ServerResponse.ContentType; | |
using ( Stream ByteStream = ServerResponse.GetResponseStream( ) ) { | |
/* What is the response type? */ | |
if ( ServerResponse.ContentType.Contains( "text" ) || | |
ServerResponse.ContentType.Contains( "json" ) || | |
ServerResponse.ContentType.Contains( "xml" ) ) { | |
/* These "text" types are easy to handle. */ | |
using (StreamReader Reader = new StreamReader( ByteStream ) ) { | |
string ResponseString = Reader.ReadToEnd( ); | |
/* | |
* Tell the client not to cache the response since it | |
* could easily be dynamic, and we do not want to mess | |
* that up! | |
*/ | |
Response.CacheControl = "no-cache"; | |
Response.Write( ResponseString ); | |
} | |
} else if ((int)ServerResponse.ContentLength > 0) { | |
/* | |
* Handle binary responses (image, layer file, other binary | |
* files) differently than text. | |
*/ | |
BinaryReader BinReader = new BinaryReader( ByteStream ); | |
byte[] BinaryOutputs = BinReader.ReadBytes( ( int )ServerResponse.ContentLength ); | |
BinReader.Close( ); | |
/* | |
* Tell the client not to cache the response since it could | |
* easily be dynamic, and we do not want to mess that up! | |
*/ | |
Response.CacheControl = "no-cache"; | |
/* | |
* Send the binary response to the client. | |
* (Note: if large images/files are sent, we could modify this to | |
* send back in chunks instead...something to think about for | |
* future.) | |
*/ | |
Response.OutputStream.Write( BinaryOutputs, 0, BinaryOutputs.Length ); | |
} else { | |
string ResponseString = ""; | |
Response.CacheControl = "no-cache"; | |
Response.Write(ResponseString); | |
} | |
ServerResponse.Close( ); | |
} | |
} | |
Response.End( ); | |
} | |
/** | |
* <summary> | |
* <c>IsReusable</c> overrides the <see cref="IHttpHandler.IsReusable"/> property to indicate if | |
* another request can use this instance. | |
* </summary> | |
* <remarks> | |
* <c>IsReusable</c> gets a value indicating whether or not another request can use the | |
* <see cref="IHttpHandler"/> instance. | |
* </remarks> | |
*/ | |
public bool IsReusable { | |
get { return false; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment