简体   繁体   English

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

[英]Can I Reroute POST http request to a GET http request with Ocelot?

We have an ocelot gateway that reroutes our former WCF requests to newer .NET Core services.我们有一个 ocelot 网关,可以将我们以前的 WCF 请求重新路由到更新的 .NET Core 服务。 Some of the old requests are still going to the WCF service.一些旧的请求仍然会转到 WCF 服务。 This all works fine.这一切正常。

Now I want to Reroute a POST with request model to a GET with query string and headers .现在我想将带有请求模型POST重新路由到带有查询字符串标头GET I can't seem to figure out how to do this, so I kind of expected the query string parameters to work out of the box and do something custom for the header.我似乎无法弄清楚如何做到这一点,所以我有点期望查询字符串参数开箱即用,并为标题做一些自定义的事情。

Here is my reroute json:这是我的重新路由json:

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

My request body:我的请求正文:

{
    "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
}

Is it possible to configure this in ocelot so that it gets correctly rerouted?是否可以在 ocelot 中配置它以便正确重新路由? If so, could you point me in the right direction?如果是这样,你能指出我正确的方向吗?

I think this is what you need https://ocelot.readthedocs.io/en/latest/features/delegatinghandlers.html我认为这就是你需要的https://ocelot.readthedocs.io/en/latest/features/delegatinghandlers.html

I have not checked that you change the http verbs etc but I would guess you can along with adding querystring params to the onward request (you will have the http request message).我没有检查你是否更改了 http 动词等,但我猜你可以将查询字符串参数添加到向前的请求中(你将有 http 请求消息)。 I think you should be able to do almost anything you like!我认为你应该能够做几乎任何你喜欢的事情!

Here is an untested example of the type of code you could implement这是您可以实现的代码类型的未经测试的示例

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

It can be registered like this in the Ocelot startup在Ocelot启动中可以这样注册

services.AddDelegatingHandler<PostToGetHandler>();

or或者

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

These handlers can be global or route specific (so you may not need the route check in the code above if you make it route specific)这些处理程序可以是全局的或特定于路由的(因此,如果您将其设为特定于路由,则可能不需要在上面的代码中进行路由检查)

This is from the Ocelot docs:这是来自 Ocelot 文档:

Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers then you must add the following json to the specific ReRoute in ocelot.json.最后,如果您想要 ReRoute 特定的 DelegatingHandlers 或订购您的特定和/或全局(稍后会详细介绍)DelegatingHandlers,那么您必须将以下 json 添加到 ocelot.json 中的特定 ReRoute。 The names in the array must match the class names of your DelegatingHandlers for Ocelot to match them together.数组中的名称必须与 Ocelot 的 DelegatingHandlers 的类名称匹配才能将它们匹配在一起。

"DelegatingHandlers": [
    "PostToGetHandler"
]

I would suggest initially adding a simple handler to your Ocelot instance and testing and adding to it to get it to do what you want.我建议最初向您的 Ocelot 实例添加一个简单的处理程序并进行测试并添加到它以使其执行您想要的操作。 Ihope this helps with what you want to do.我希望这有助于你想做的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM