Asp.net 让一个Web API向另一个转发请求的最佳方法

Asp.net 让一个Web API向另一个转发请求的最佳方法,asp.net,asp.net-web-api,asp.net-web-api2,Asp.net,Asp.net Web Api,Asp.net Web Api2,我有几个web服务在不同的服务器上运行,我希望有一个web服务在其余的服务器之前运行,以根据头值决定请求应该转发到哪个web服务(服务器) 其思想是客户端将发送一个请求,例如: http://api.mysite.com/cars mysite.com上的API将检查请求,从API密钥(在标题中提供)提取信息,并重定向到适当的服务器,例如 http://server4.mysite.com/api/cars 这样行吗?我关心的是如何将响应(带数据)从“server4”返回到客户端。响应将只返

我有几个web服务在不同的服务器上运行,我希望有一个web服务在其余的服务器之前运行,以根据头值决定请求应该转发到哪个web服务(服务器)

其思想是客户端将发送一个请求,例如:

http://api.mysite.com/cars
mysite.com上的API将检查请求,从API密钥(在标题中提供)提取信息,并重定向到适当的服务器,例如

http://server4.mysite.com/api/cars

这样行吗?我关心的是如何将响应(带数据)从“server4”返回到客户端。响应将只返回到第一台服务器,还是客户端将实现该响应?

您需要做的就是构建一个Web API DelegatingHandler,如下所示:

public class ProxyHandler : DelegatingHandler
{
  protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
  {
    UriBuilder forwardUri = new UriBuilder(request.RequestUri);
    //strip off the proxy port and replace with an Http port
    forwardUri.Port = 80;
    //send it on to the requested URL
    request.RequestUri = forwardUri.Uri;
    HttpClient client = new HttpClient();
    var response = await  client.SendAsync(request,HttpCompletionOption.ResponseHeadersRead);
    return response;
  }
} 
public类代理处理程序:DelegatingHandler
{
受保护的重写异步System.Threading.Tasks.Task SendAsync(HttpRequestMessage请求,System.Threading.CancellationToken CancellationToken)
{
UriBuilder forwardUri=新的UriBuilder(request.RequestUri);
//剥离代理端口并替换为Http端口
forwardUri.Port=80;
//将其发送到请求的URL
request.RequestUri=forwardUri.Uri;
HttpClient=新的HttpClient();
var response=wait client.sendaync(请求,HttpCompletionOption.ResponseHeadersRead);
返回响应;
}
} 

只需执行相同的任务,并且必须在Yazan Ati answer之外再添加一些行

    [HttpPost]
    [HttpGet]
    [Route("api/TestBot/{*remaining}")]
    public Task<HttpResponseMessage> SendMessage()
    {
        const string host = "facebook.botframework.com";
        string forwardUri = $"https://{host}/api/v1/bots/billycom{Request.RequestUri.Query}";

        Request.Headers.Remove("Host");
        Request.RequestUri = new Uri(forwardUri);
        if (Request.Method == HttpMethod.Get)
        {
            Request.Content = null;
        }

        var client = new HttpClient();
        return client.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead);
    }
[HttpPost]
[HttpGet]
[路由(“api/TestBot/{*剩余}”)]
公共任务发送消息()
{
const string host=“facebook.botframework.com”;
string forwardUri=$“https://{host}/api/v1/bots/billycom{Request.RequestUri.Query}”;
Request.Headers.Remove(“主机”);
Request.RequestUri=新Uri(forwardUri);
if(Request.Method==HttpMethod.Get)
{
Request.Content=null;
}
var client=新的HttpClient();
返回client.sendaync(请求,HttpCompletionOption.ResponseHeadersRead);
}

这两种方案都是可行的。你想要哪一个?什么不起作用?我希望客户只需要与他们真正联系的服务器独立地交谈。我只是担心这是否可能。我想客户端可能会自动(?)从第一个服务器接收到响应,从而错过“第二个”响应。也许这只是一个愚蠢的想法。。。我只是想知道是否能够将第二台服务器的响应直接返回到客户端。您可以重定向它们(它们将直接与该服务器通信)。假设您的站点是无会话的,那么它是好的,因为负载平衡(并且它不会影响您的服务器资源)。相反,如果您想“过滤”他们的请求(例如,因为在您的服务器上进行了身份验证),那么您必须首先从第二台服务器下载响应,然后将其发送回客户端。优点:他们只看到你,你可以进行会话(不费吹灰之力),但缺点是:你需要在服务器中使用更多的资源(而且负载平衡会更加困难)。我的设置完全相同,客户端调用外部api端点,然后根据输入将它们重定向到内部api端点(在不同的内部服务器上)一切都正常,就响应而言,如果您想在发送响应之前对响应进行按摩,您可以这样做,否则您可以按照内部API调用的原样发送响应。因此,结论是,您所讨论的是一个有效的场景,它应该可以工作。有关此答案的更多详细信息,请参阅此解决方案不适用于GET和DELETE,因为SendAsync的实现本身尝试读取请求流,这会导致错误“无法发送具有此动词类型的内容体”。(请参见此)。要使其工作,我必须调用client.GetAsync或client.PostAsync或client.PutAsync或client.deleteAync,而不是调用client.sendaync,这取决于请求的Http方法。因此,我必须手动将所有头从请求对象复制到HttpClient对象。@HungNguyen您不应该也重写其他方法吗?SendAsync仅用于发送数据。@HungngGuyen尝试添加以下内容,以使其在(request.Method==HttpMethod.get){request.Content=null;}的情况下使用GETs。它不在Https上工作,如果有人有一些想法,请提供帮助。它可以完美地工作。