0

We have an ocelot gateway that reroutes our former WCF requests to newer .NET Core services. Some of the old requests are still going to the WCF service. This all works fine.

Now I want to Reroute a POST with request model to a GET with query string and headers. 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:

{
      "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? If so, could you point me in the right direction?

Nick N.
  • 12,902
  • 7
  • 57
  • 75

1 Answers1

0

I think this is what you need 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). 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

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:

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. The names in the array must match the class names of your DelegatingHandlers for Ocelot to match them together.

"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. Ihope this helps with what you want to do.

PaulD
  • 206
  • 1
  • 5