我可以使用Ocelot将POST http请求重新路由到GET http请求吗?

时间:2019-07-30 08:19:20

标签: c# .net rest wcf ocelot

我们有一个ocelot网关,可以将以前的WCF请求重新路由到更新的.NET Core服务。一些旧的请求仍将发送到WCF服务。一切正常。

现在,我想将具有请求模型的 POST 重新路由到具有查询字符串标头的 GET。我似乎无法弄清楚该怎么做,所以我有点希望查询字符串参数可以直接使用并为标题做一些自定义。

这是我的重新路由json:

{
      "DownstreamPathTemplate": "/v1/attachments",
      "DownstreamScheme": "http",
      "DownstreamHttpMethod": [ "GET" ],
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 53737
        }
      ],
      "UpstreamPathTemplate": "/mobile/ImageService.svc/json/GetImage",
      "UpstreamHttpMethod": [ "POST" ],
      "UpstreamHost": "*"
    }

我的请求正文:

{
    "SessionId":"XXX", //needs to be a header
    "ImageId": "D13XXX", //needs to be added to query string
    "MaxWidth" : "78", //needs to be added to query string
    "MaxHeight" : "52", //needs to be added to query string
    "EditMode": "0" //needs to be added to query string
}

是否可以在ocelot中对其进行配置,以便正确地重新路由?如果是这样,您能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:0)

我认为这就是您需要的 https://ocelot.readthedocs.io/en/latest/features/delegatinghandlers.html

我还没有检查过您是否更改过http动词等,但是我想您可以在查询请求中添加查询字符串参数(您将获得http请求消息)。我认为您应该可以执行几乎所有您喜欢的事情!

这是您可以实现的代码类型的 unested 示例

public class PostToGetHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Only want to do this if it matches our route
        // See section later on about global or route specific handlers
        if (request.RequestUri.OriginalString.Contains("/mobile/ImageService.svc/json/GetImage") && request.Method.Equals(HttpMethod.Post))
        {
            var bodyString = await request.Content.ReadAsStringAsync();

            // Deserialize into a MyClass that will hold your request body data
            var myClass = JsonConvert.DeserializeObject<MyClass>(bodyString);

            // Append your querystrings
            var builder = new QueryBuilder();
            builder.Add("ImageId", myClass.ImageId);
            builder.Add("MaxWidth", myClass.MaxWidth);      // Keep adding queryString values

            // Build a new uri with the querystrings
            var uriBuilder = new UriBuilder(request.RequestUri);
            uriBuilder.Query = builder.ToQueryString().Value;

            // TODO - Check if querystring already exists etc
            request.RequestUri = uriBuilder.Uri;

            // Add your header - TODO - Check to see if this header already exists
            request.Headers.Add("SessionId", myClass.SessionId.ToString());

            // Get rid of the POST content
            request.Content = null;
        }

        // On it goes either amended or not
        // Assumes Ocelot will change the verb to a GET as part of its transformation
        return await base.SendAsync(request, cancellationToken);
    }
}

可以在Ocelot启动中像这样注册

services.AddDelegatingHandler<PostToGetHandler>();

services.AddDelegatingHandler<PostToGetHandler>(true);  // Make it global

这些处理程序可以是全局的,也可以是特定于路由的(因此,如果您将其设为特定于路由,则可能不需要上面代码中的路由检查)

这是来自Ocelot文档:

最后,如果要重新路由特定的DelegatingHandlers或订购 您的特定和/或全局(稍后会详细介绍)DelegatingHandlers 那么您必须将以下json添加到特定的ReRoute中 ocelot.json。数组中的名称必须与您的类的名称匹配 Ocelot的DelegatingHandler将它们匹配在一起。

"DelegatingHandlers": [
    "PostToGetHandler"
]

我建议最初向您的Ocelot实例添加一个简单的处理程序,然后对其进行测试和添加,以使其执行您想要的操作。希望这对您想做的事情有帮助。