可以使用Web API配置HTTP代理吗?

可以使用Web API配置HTTP代理吗?,http,.net-4.0,asp.net-web-api,Http,.net 4.0,Asp.net Web Api,我想构建一个HTTP代理,将所有请求路由到另一个HTTP服务。关于如何使用Web API实现这一点,有人有什么好的建议吗 我的情况是,我们有两组服务。一个是外部可访问的,另一个不是。我想从外部服务提供一个路由器,在所有逻辑和配置所在的地方调用我的内部服务。是的,这很容易做到。只需创建一个从DelegatingHandler派生的类,重写SendAsync并将其添加到配置对象上的MessageHandlers集合中 这里是我创建的一个自托管控制台应用程序代理,它将JSON转换为XML,反之亦然。它

我想构建一个HTTP代理,将所有请求路由到另一个HTTP服务。关于如何使用Web API实现这一点,有人有什么好的建议吗


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

是的,这很容易做到。只需创建一个从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"));
    }


}
类程序
{
静态void Main(字符串[]参数)
{
var config=新的HttpSelfHostConfiguration(“http://localhost:8081");
var server=新的HttpSelfHostServer(配置);
var originServerUri=新Uri(“http://example.org/origin-server/");      
Add(新转换器(originServerUri));
server.OpenAsync().Wait();
Console.Read();
server.CloseAsync().Wait();
}
}
公共类转换器:DelegatingHandler
{
私有HttpClient _HttpClient=新HttpClient();
私有Uri_OriginServer;
公共转换器(Uri原始服务器)
{
_OriginServer=OriginServer;
}
受保护的重写异步任务SendAsync(HttpRequestMessage请求,System.Threading.CancellationToken CancellationToken)
{
WriteLine(新的HttpMessageContent(request.ReadAsStringAsync().Result);
var newRequest=CreateNewRequest(请求);
var t=_HttpClient.SendAsync(newRequest);
等待t;
如果(t.已完成)
{
尝试
{
var response=CreateNewResponse(t.Result);
Console.WriteLine(“-->”);
WriteLine(新的HttpMessageContent(response.ReadAsStringAsync().Result);
返回响应;
}
捕获(例外情况除外)
{
控制台写入线(例如消息);
返回新的HttpResponseMessage(HttpStatusCode.InternalServerError){Content=newStringContent(ex.Message)};
}
}
其他的
{
返回新的HttpResponseMessage(HttpStatusCode.InternalServerError){Content=newStringContent(t.Exception.Message)};
}
}
私有HttpRequestMessage CreateNewRequest(HttpRequestMessage请求)
{
var newRequest=newhttprequestmessage();
newRequest.Headers.Clear();
foreach(request.Headers中的var头)
{
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=新Uri(_OriginServer,request.RequestUri.PathAndQuery);
返回新请求;
}
专用HttpResponseMessage CreateNewResponse(HttpResponseMessage响应)
{
response.Content=TranslateContent(response.Content);
返回响应;
}
私有HttpContent TranslateContent(HttpContent-HttpContent)
{
var mediatype=httpContent.Headers.ContentType.mediatype;
if(mediatype.Contains(“+xml”))
{
返回TranslateXmlToJson(httpContent);
}
其他的
{
返回TranslateJsonToXml(httpContent);
}
}
私有HttpContent TranslateJsonToXml(HttpContent内容)
{
var mediatype=content.Headers.ContentType.mediatype;
字符串json=content.ReadAsStringAsync().Result;
XmlDocument doc=(XmlDocument)JsonConvert.DeserializeXmlNode(json);
返回新的StringContent(doc.OuterXml、Encoding.UTF8、mediatype.Replace(“+json”、“+xml”);
}
私有HttpContent TranslateXmlToJson(HttpContent内容)
{
var mediatype=content.Headers.ContentType.mediatype;
XmlDocument doc=新的XmlDocument();
doc.Load(content.ReadAsStreamAsync().Result);
字符串jsonText=JsonConvert.SerializeXmlNode(doc);
返回新的StringContent(jsonText,Encoding.UTF8,mediatype.Replace(“+xml”,“+json”);
}
}

感谢各位的回复。最后,我决定使用IHttpHandler,因为需要代理的服务目前没有使用webapi。这是通过以下方式实现的:

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;
        }
    }
}

需要在发送请求的客户端上配置DelegatingHandler,对吗?我需要在服务器端设置此设置。如果我不能使用它,我想我可以随时检查HttpRequest并手动重新定向。@crankage否在这种情况下,您将在服务器上使用委派处理程序。您确定不只是想使用广泛可用且具有良好社区支持的程序吗,