#region License
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Web;
namespace Demo.Silverlight.Web.Modules
{
public class TweetSharpProxyModule : IHttpModule
{
private const string ProxyAcceptHeader = "X-Twitter-Accept";
private const string ProxyAgentHeader = "X-Twitter-Agent";
private const string ProxyAuthorizationHeader = "X-Twitter-Auth";
private const string ProxyMethodHeader = "X-Twitter-Method";
private const string ProxyQueryHeader = "X-Twitter-Query";
private const string ProxyStatusCode = "X-Twitter-StatusCode";
private const string ProxyStatusDescription = "X-Twitter-StatusDescription";
private static readonly ICollection<string>
_skipHeaders
= new[]
{
"Connection",
"Keep-Alive",
"Accept",
"Host",
"User-Agent",
"Content-Length",
"Content-Type",
"Accept-Encoding",
"Authorization",
"Referer",
ProxyMethodHeader,
ProxyAuthorizationHeader,
ProxyAcceptHeader,
ProxyAgentHeader,
ProxyQueryHeader
};
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += ContextBeginRequest;
}
#endregion
static void ContextBeginRequest(object sender, EventArgs e)
{
var context = (HttpApplication)sender;
var request = context.Request;
var path = request.Path.ToLowerInvariant();
if (!path.StartsWith("/proxy/"))
{
return;
}
var url = context.Request.Headers[ProxyQueryHeader];
Trace.WriteLine(String.Format("Proxy request handled for {0} from {1}.",
request.Path,
request.UserHostAddress));
string response;
try
{
var proxyRequest = (HttpWebRequest)WebRequest.Create(url);
var methodOverride = request.Headers[ProxyMethodHeader];
proxyRequest.Method = methodOverride != null
? request.Headers[ProxyMethodHeader]
: request.HttpMethod;
var userAgent = request.Headers[ProxyAgentHeader];
proxyRequest.UserAgent = userAgent != null
? request.Headers[ProxyAgentHeader]
: request.UserAgent;
var acceptEncoding =
request.Headers[ProxyAcceptHeader] ??
request.Headers["Accept-Encoding"];
if (acceptEncoding != null)
{
acceptEncoding = acceptEncoding.ToLower();
if (acceptEncoding.Contains("gzip"))
{
proxyRequest.AutomaticDecompression =
DecompressionMethods.GZip;
}
else if (acceptEncoding.Contains("deflate"))
{
proxyRequest.AutomaticDecompression =
DecompressionMethods.Deflate;
}
}
proxyRequest.ContentType = request.ContentType;
proxyRequest.ContentLength = request.ContentLength;
proxyRequest.Referer = request.UrlReferrer != null
? request.UrlReferrer.ToString()
: null;
proxyRequest.KeepAlive = true;
if (request.Headers[ProxyAuthorizationHeader] != null)
{
proxyRequest.Headers["Authorization"] =
request.Headers[ProxyAuthorizationHeader];
}
foreach (var header in request.Headers.Keys)
{
var name = header.ToString();
if (_skipHeaders.Contains(name))
{
continue;
}
var value = request.Headers[name];
proxyRequest.Headers[name] = value;
}
var stream = context.Request.InputStream;
var content = new byte[context.Request.InputStream.Length];
stream.Read(content, 0, (int)context.Request.InputStream.Length);
response = ProxyRequest(proxyRequest, content);
}
catch (WebException ex)
{
response = HandleWebException(ex);
if (ex.Response is HttpWebResponse)
{
var http = (HttpWebResponse)ex.Response;
context.Response.AddHeader(ProxyStatusCode, ((int)http.StatusCode).ToString());
context.Response.AddHeader(ProxyStatusDescription, http.StatusDescription);
}
}
context.Response.ClearContent();
context.Response.Write(response);
context.Response.End();
}
private static string ProxyRequest(WebRequest proxyRequest, byte[] content)
{
switch(proxyRequest.Method)
{
case "GET":
case "DELETE":
using (var response = proxyRequest.GetResponse())
{
try
{
var stream = response.GetResponseStream();
using (var reader = new StreamReader(stream))
{
var results = reader.ReadToEnd();
return results;
}
}
catch (WebException ex)
{
return HandleWebException(ex);
}
}
case "POST":
case "PUT":
try
{
using (var stream = proxyRequest.GetRequestStream())
{
stream.Write(content, 0, content.Length);
stream.Close();
using (var response = proxyRequest.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
var result = reader.ReadToEnd();
return result;
}
}
}
}
catch (WebException ex)
{
return HandleWebException(ex);
}
default:
throw new NotSupportedException();
}
}
private static string HandleWebException(WebException ex)
{
if (ex.Response is HttpWebResponse && ex.Response != null)
{
using (var reader = new StreamReader(ex.Response.GetResponseStream()))
{
var result = reader.ReadToEnd();
return result;
}
}
throw ex;
}
}
}