Damien
Damien

Reputation: 11

Is there a way to retrieve the proxied destination of a request before the request is fulfilled? (YARP)

Using YARP as a reverse proxy in our API gateway, an authorisation header is applied to each request through a middleware. E.G.


private void SetProxyPipeline(IReverseProxyApplicationBuilder proxyPipeline)
        {
            proxyPipeline.Use((context, next) =>
            {
                var proxyFeature = context.GetReverseProxyFeature();
                // Add to authorisation header here before passing request to intended service
                
                return next();
            });
        }   

However, now I'm looking for a method of retrieving the intended destination path of this request before next() is called.

For example, a request to the gateway localhost:3000/service/example1 This request gets routed to localhost:3100/api/example1 or localhost:3200/api/example1 depending on which destination is chosen by YARP.

I've been trying to find a way to see which destination (and full path) YARP has chosen before it completes the request.

ProxyFeature offers a ProxiedDestination property, however this only seems to be filled after next() is called and the request has been routed.

Available destinations are also offered by ProxyFeature however this would only be useful by assuming that there will always be one destination for each route, and wouldn't take into consideration any transforms that are being applied to the request.

Upvotes: 1

Views: 630

Answers (1)

Chris
Chris

Reputation: 23

Quite an old question, but it came up when I searched for something similar.

I'm assuming the OP was using the load balancing feature to decide which endpoint to send the request to from the available destinations. So long as you run your custom middleware after the load balacing has run, the AvailableDestinations property will have been filtered to what was returned from the load balancer. Although you can return multiple destinations from the load balancing stage, I believe the recommendation by YARP is to only ever return one. If you return multiple, one is picked randomly I think.

So for most use cases, you should be able to use the AvailableDestinations property from IReverseProxyFeature in your custom middleware to see which destination the request will be sent to.

Code snippets that are working for me:

Cluster config:

 new ClusterConfig
 {
     ClusterId = "MyCluster",
     LoadBalancingPolicy = nameof(TestLoadBalancingPolicy),
     Destinations = new Dictionary<string, DestinationConfig>(StringComparer.OrdinalIgnoreCase)
     {
         { "MyDestination", new DestinationConfig { Address = "http://somewhere" } },
         { "SomeOtherDestination", new DestinationConfig { Address = "http://somewhereelse" } }
     }
 }

Load balancing logic (registered in DI):

public class TestLoadBalancingPolicy : ILoadBalancingPolicy
{
    public string Name => nameof(TestLoadBalancingPolicy);

    public DestinationState? PickDestination(HttpContext context, ClusterState cluster, IReadOnlyList<DestinationState> availableDestinations)
    {
        return availableDestinations.Single(d => d.DestinationId == "MyDestination");
    }
}

Middleware pipeline:

app.MapReverseProxy(proxyPipeline =>
{
    proxyPipeline.UseLoadBalancing();
    proxyPipeline.Use((context, next) =>
    {
        // returns a single destination with DestinationId of 'MyDestination'
        var destination = context.GetReverseProxyFeature().AvailableDestinations.Single();
        return next();
    });
});

Upvotes: 0

Related Questions