Ocelot icon indicating copy to clipboard operation
Ocelot copied to clipboard

Aggregators : allow sequential calls

Open cfeltz34 opened this issue 2 years ago • 2 comments

Expected Behavior / New Feature

Currently when using the query aggregators all the calls merge synchronously. In some cases it may be interesting to ensure that these calls are made synchronously:

  • the result of request 1 is retrieved
  • then, after a possible business processing, it is added to the parameters of the request 2 I made the change on a personal fork, it is quite easy to set up (I started from the principle that by default the parameters are pre-filled identically for all requests. Here is an example of use:
        override public async Task<DownstreamResponse> Aggregate(List<HttpContext> contexts, RequestDelegate next = null)
        {
            if (!sequential) 
            {
                await FireAll(contexts, next);
                var response1 = GetResponse(contexts[0]);
                var result1 = await GetResult<ExampleApiMessage>(response1);
                var response2 = GetResponse(contexts[1]);
                var result2 = await GetResult<ExampleData>(response2);

                var result = new AggregateData(result1, result2);
                return Return(result);
            }
            else 
            {
                await Fire(contexts[0], next);
                var response1 = GetResponse(contexts[0]);
                var result1 = await GetResult<ExampleApiMessage>(response1);

                SetQueryString(contexts[1], new QueryString("?id=4&parameter=" + result1.message));
                await Fire(contexts[1], next);
                var response2 = GetResponse(contexts[1]);
                var result2 = await GetResult<ExampleData>(response2);

                var result = new AggregateData(result1, result2);
                return Return(result);
            }            
        }

As soon as calls become sequential, it becomes interesting to allow POST-type requests on aggregators. So I also removed this limitation. Here is an example of using with an aggregator with POST and GET:

        override public async Task<DownstreamResponse> Aggregate(List<HttpContext> contexts, RequestDelegate next = null)
        {
            // Get request body
            // dynamic body = await GetBodyAsDynamic(contexts[0]);
            var body = await GetBodyAsDictionary(contexts[0]);

            SetQueryString(contexts[0], new QueryString("?test=" + body["paramForGet"]));
            await Fire(contexts[0], next, "GET");
            var response1 = GetResponse(contexts[0]);
            var result1 = await GetResult<ExampleApiMessage>(response1);

            // Refactor body and refresh request
            body.Remove("paramForGet");
            body.Add("param2", result1.message);
            SetBody(contexts[1], body);

            // Fire post request
            await Fire(contexts[1], next, "POST");
            var response2 = GetResponse(contexts[1]);
            var result2 = await GetResult<DefaultApiMessage>(response2);
            return Return(result2);
        }

My code is not very sexy I admit it because I made sure that there is the least code that differs from the original. I think that ideally there should be more automatic things via the configuration server.

Actual Behavior / Motivation for New Feature

Remove a very strong limitation of Ocelot

cfeltz34 avatar Apr 14 '22 06:04 cfeltz34

+1

codehunter13 avatar May 30 '22 08:05 codehunter13

Hi @cfeltz34 ! Thanks for your interest in Ocelot!

Will you contribute and develop this feature?

raman-m avatar Dec 25 '23 15:12 raman-m