Created
March 23, 2013 14:53
-
-
Save pmhsfelix/5227995 to your computer and use it in GitHub Desktop.
Naive HTTP intermediary using Web API with self-host
This file contains hidden or 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
| using System; | |
| using System.Collections.Concurrent; | |
| using System.Collections.Generic; | |
| using System.Diagnostics; | |
| using System.IO; | |
| using System.Linq; | |
| using System.Net; | |
| using System.Net.Http; | |
| using System.Net.Http.Headers; | |
| using System.ServiceModel; | |
| using System.Text; | |
| using System.Threading; | |
| using System.Threading.Tasks; | |
| using System.Web.Http.SelfHost; | |
| namespace SelfHostedProxy | |
| { | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| Trace.Listeners.Add(new ConsoleTraceListener()); | |
| var config = new HttpSelfHostConfiguration("http://localhost:8080") | |
| { | |
| TransferMode = TransferMode.Streamed | |
| }; | |
| var server = new HttpSelfHostServer(config, new ProxyMessageHandler()); | |
| server.OpenAsync().Wait(); | |
| Trace.TraceInformation("server is opened"); | |
| Console.ReadKey(); | |
| server.CloseAsync().Wait(); | |
| Trace.TraceInformation("server is closed, bye"); | |
| } | |
| } | |
| internal class ProxyMessageHandler : DelegatingHandler | |
| { | |
| async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | |
| { | |
| try{ | |
| var host = request.Headers.Host; | |
| request.RequestUri = new Uri(new Uri(request.RequestUri.Scheme + "://" + host), request.RequestUri.PathAndQuery); | |
| request.Headers.TransferEncoding.Clear(); | |
| RemoveConnectionHeadersFrom(request.Headers, request.Headers.Connection); | |
| var client = GetClientFor(host); | |
| if(request.Content != null && request.Content.Headers.ContentType == null) | |
| { | |
| request.Content = null; | |
| } | |
| Trace.TraceInformation("forwarding {0} request to {1}", request.Method, request.RequestUri); | |
| var response = await client.SendAsync(request, cancellationToken); | |
| response.Headers.TransferEncoding.Clear(); | |
| RemoveConnectionHeadersFrom(response.Headers, response.Headers.Connection); | |
| Trace.TraceInformation("received {0} response from {1} with status {2}", | |
| request.Method, request.RequestUri, response.StatusCode); | |
| return response; | |
| }catch(Exception e) | |
| { | |
| return new HttpResponseMessage(HttpStatusCode.InternalServerError) | |
| { | |
| Content = new StringContent(e.Message) | |
| }; | |
| } | |
| } | |
| private static void RemoveConnectionHeadersFrom(HttpHeaders headers, IEnumerable<string> names ) | |
| { | |
| foreach (var name in names) | |
| { | |
| headers.Remove(name); | |
| } | |
| headers.Remove("Connection"); | |
| } | |
| private HttpClient GetClientFor(string host) | |
| { | |
| return _clients.GetOrAdd(host, _ => new HttpClient()); | |
| } | |
| private readonly ConcurrentDictionary<string, HttpClient> _clients = new ConcurrentDictionary<string, HttpClient>(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment