Skip to content

Instantly share code, notes, and snippets.

@ToJans
Last active December 13, 2015 16:58
Show Gist options
  • Save ToJans/4944185 to your computer and use it in GitHub Desktop.
Save ToJans/4944185 to your computer and use it in GitHub Desktop.
Simple custom response handler for SelfHostHttp, with a reverse proxy (currently not async)
public class CustomResponseHandler : DelegatingHandler
{
public List<Func<HttpRequestMessage, HttpResponseMessage>> ContentProviders { get; private set; }
public CustomResponseHandler()
{
ContentProviders = new List<Func<HttpRequestMessage, HttpResponseMessage>>();
ContentProviders.Add(GetResult);
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var bldr = new UriBuilder(request.RequestUri);
if (bldr.Scheme == "http")
bldr.Port = 80;
else if (bldr.Scheme == "https")
bldr.Port = 443;
request.RequestUri = bldr.Uri;
// Console.WriteLine(new HttpMessageContent(request).ReadAsStringAsync().Result);
var tcs = new TaskCompletionSource<HttpResponseMessage>();
HttpResponseMessage result = null;
var toloop = ContentProviders;
toloop.Reverse();
foreach (var cp in toloop)
{
result = cp(request);
if (result != null)
{
break;
}
}
result = result ?? new HttpResponseMessage(HttpStatusCode.NotFound);
tcs.SetResult(result);
return tcs.Task;
}
HttpResponseMessage GetResult(HttpRequestMessage request)
{
var client = new HttpClient();
if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Head)
request.Content = null;
var task = client.SendAsync(request);
task.Wait();
var responseMessage = task.Result;
return responseMessage;
}
}
public class HttpSelfHostProxy
{
public Uri MyUri { get; set; }
HttpSelfHostServer ServerHttp;
CustomResponseHandler handler = new CustomResponseHandler();
public HttpSelfHostProxy(Uri MyUri = null)
{
this.MyUri = MyUri ?? new Uri("http://localhost:9100");
}
public void Start()
{
var config = new HttpSelfHostConfiguration(MyUri);
config.TransferMode = TransferMode.Streamed;
ServerHttp = new HttpSelfHostServer(config, handler);
ServerHttp.OpenAsync().Wait();
}
public void RespondWithString(string uri, string response, HttpStatusCode statuscode = HttpStatusCode.OK)
{
handler.ContentProviders.Add(msg => msg.RequestUri == new Uri(uri) ? new HttpResponseMessage(statuscode) { Content = new StringContent(response) } : null);
}
public void RespondWithFile(string uri, string filename, HttpStatusCode statuscode = HttpStatusCode.OK)
{
handler.ContentProviders.Add(msg => msg.RequestUri == new Uri(uri) ? new HttpResponseMessage(statuscode) { Content = new StreamContent(File.OpenRead(filename)) } : null);
}
public void Stop()
{
ServerHttp.CloseAsync().Wait();
}
}
[TestClass]
public class The_proxy_status_should_be_queryable
{
IProxyStuff SUT;
WebClient WC;
[TestInitialize]
public void Init()
{
SUT = new HttpSelfHostProxy();
WC = new WebClient { Proxy = new WebProxy(SUT.MyUri) { BypassProxyOnLocal = false} };
SUT.RespondWithString("http://proxy/ping","pong");
SUT.Start();
}
[TestMethod]
public void Ping_should_return_pong()
{
WC.DownloadString("http://proxy/ping").ShouldBe("pong");
}
[TestMethod]
[ExpectedException(typeof(WebException))]
public void Pang_should_return_error()
{
WC.DownloadString("http://proxy/pang");
}
[TestMethod]
public void Http_reverse_proxy_should_work()
{
var result = WC.DownloadString("http://www.somesite.be");
Console.WriteLine(result);
result.ShouldContain("Some site");
}
[TestMethod]
public void Https_reverse_proxy_should_work()
{
var result = WC.DownloadString("https://somesite.com/");
Console.WriteLine(result);
result.ShouldContain("Some site");
}
[TestMethod]
public void Intercepting_google_should_work()
{
SUT.RespondWithString("http://www.google.com", "<html><body>Fake it baby</body></html>");
var result = WC.DownloadString("http://www.google.com");
Console.WriteLine(result);
result.ShouldContain("Fake it baby");
}
[TestCleanup]
public void Done()
{
SUT.Stop();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment