2012-10-17 29 views
0

我想建立一个HTTP代理,将所有请求路由到另一个HTTP服务。有没有人有任何好的建议,以如何实现这一点与Web API?可以使用Web API配置HTTP代理吗?

我现在的情况是我们有两组服务。一个是外部访问的,一个不是。我想从外部服务提供一个路由器来调用我所有的逻辑和配置所在的内部服务。

+0

你确定你不只是想使用一些广泛可用的,有良好的社区支持? [Varnish](https://www.varnish-cache.org/),[Nginx](http://wiki.nginx.org/Main),[Apache HTTPD](http://httpd.apache.org/ ),[HAProxy](http://haproxy.1wt.eu/) – marklap

回答

2

是的,这很容易做到。只需创建一个派生自DelegatingHandler的类,重写SendAsync并将其添加到配置对象的MessageHandlers集合中。

这里是我创建的自我托管的控制台应用程序代理,它将JSON转换为XML,反之亦然。它应该让你知道它是如何完成的。

class Program 
{ 
    static void Main(string[] args) 
    { 
     var config = new HttpSelfHostConfiguration("http://localhost:8081"); 
     var server = new HttpSelfHostServer(config); 


     var originServerUri = new Uri("http://example.org/origin-server/");  
     config.MessageHandlers.Add(new Converter(originServerUri)); 

     server.OpenAsync().Wait(); 

     Console.Read(); 

     server.CloseAsync().Wait(); 

    } 
} 


public class Converter : DelegatingHandler 
{ 
    private HttpClient _HttpClient = new HttpClient(); 
    private Uri _OriginServer; 
    public Converter(Uri originServer) 
    { 
     _OriginServer = originServer; 
    } 
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
    { 
      Console.WriteLine(new HttpMessageContent(request).ReadAsStringAsync().Result); 


      var newRequest = CreateNewRequest(request); 

      var t = _HttpClient.SendAsync(newRequest); 

      await t; 

      if (t.IsCompleted) 
      { 
       try 
       { 
        var response = CreateNewResponse(t.Result); 
        Console.WriteLine("--->"); 
        Console.WriteLine(new HttpMessageContent(response).ReadAsStringAsync().Result); 
        return response; 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine(ex.Message); 
        return new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(ex.Message)}; 

       } 
      } 
      else 
      { 
       return new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(t.Exception.Message)}; 
      } 
    } 

    private HttpRequestMessage CreateNewRequest(HttpRequestMessage request) 
    { 
     var newRequest = new HttpRequestMessage(); 

     newRequest.Headers.Clear(); 
     foreach (var header in request.Headers) 
     { 
      newRequest.Headers.Add(header.Key, header.Value); 
     } 
     if (request.Content.Headers.ContentLength != 0) 
     { 
      newRequest.Content = TranslateContent(request.Content); 
     } 
     newRequest.Headers.Host = null; 
     newRequest.Method = request.Method; 
     newRequest.RequestUri = new Uri(_OriginServer, request.RequestUri.PathAndQuery); 
     return newRequest; 
    } 

    private HttpResponseMessage CreateNewResponse(HttpResponseMessage response) 
    { 
     response.Content = TranslateContent(response.Content); 
     return response; 
    } 

    private HttpContent TranslateContent(HttpContent httpContent) 
    { 
     var mediatype = httpContent.Headers.ContentType.MediaType; 
     if (mediatype.Contains("+xml")) 
     { 
      return TranslateXmlToJson(httpContent); 
     } 
     else 
     { 
      return TranslateJsonToXml(httpContent); 
     } 
    } 

    private HttpContent TranslateJsonToXml(HttpContent content) 
    { 
     var mediatype = content.Headers.ContentType.MediaType; 

     string json = content.ReadAsStringAsync().Result; 
     XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json); 
     return new StringContent(doc.OuterXml, Encoding.UTF8, mediatype.Replace("+json", "+xml")); 
    } 

    private HttpContent TranslateXmlToJson(HttpContent content) 
    { 
     var mediatype = content.Headers.ContentType.MediaType; 
     XmlDocument doc = new XmlDocument(); 
     doc.Load(content.ReadAsStreamAsync().Result); 

     string jsonText = JsonConvert.SerializeXmlNode(doc); 
     return new StringContent(jsonText, Encoding.UTF8, mediatype.Replace("+xml", "+json")); 
    } 


} 
+0

需要在发送请求的客户端上配置DelegatingHandler权限?我把这个设置在服务器端。如果我不能使用它,我想我总是可以检查HttpRequest并手动重定向它。 –

+0

@crankage在这种情况下,您不会在服务器上使用委托处理程序。 –

0

感谢您的回复家伙。最后,我决定使用IHttpHandler作为需要代理的服务,目前不使用web-api。这是通过做这样的事情:

public class MyProxy : IHttpHandler 
{ 
    private static readonly string CoreServicesUrl = "localhost:1234"; 

    public void ProcessRequest(HttpContext context) 
    { 
     string serviceUrl = context.Request.Headers.Get("ServiceUrl"); 
     if (serviceUrl == null) 
     { 
      context.Response.StatusCode = (int)HttpStatusCode.BadRequest; 
      return; 
     } 

     string url = string.Format("http://{0}/api/{1}", CoreServicesUrl, serviceUrl); 
     HttpResponseMessage response = RouteRequest(context, url); 

     // This will handle both successful and unsuccessful responses 
     context.Response.StatusCode = (int)response.StatusCode; 
     var content = response.Content.ReadAsStringAsync().Result; 
     context.Response.Write(content); 
    } 

    private static HttpResponseMessage RouteRequest(HttpContext context, string url) 
    { 
     var client = new HttpClient(); 

     if (context.Request.HttpMethod == "GET") 
      return client.GetAsync(url).Result; 

     if (context.Request.HttpMethod == "POST") 
     { 
      var stream = context.Request.GetBufferlessInputStream(); 
      var sr = new StreamReader(stream); 
      var body = sr.ReadToEnd(); 
      try 
      { 
       return client.PostAsync(url, new StringContent(body, Encoding.UTF8, "application/json")).Result; 
      } 
      catch (Exception ex) 
      { 
       var response = new HttpResponseMessage(HttpStatusCode.InternalServerError) {ReasonPhrase = ex.Message}; 
       return response; 
      } 
     } 

     // Other HTTP verbs are not supported 
     return new HttpResponseMessage(HttpStatusCode.NotImplemented); 
    }   

    public bool IsReusable 
    { 
     get 
     { 
      return false; 
     } 
    } 
} 
相关问题