microsoft / reverse-proxy

A toolkit for developing high-performance HTTP reverse proxy applications.

Home Page:https://microsoft.github.io/reverse-proxy

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Enable scatter gather scenarios

danielmarbach opened this issue · comments

For context this is the scenario dotnet/aspnetcore#53565

@Tratcher pointed out we might only need the capability to create the HttpRequestMessage and run the transforms.

If we had this capability in place in Yarp we wouldn't have to copy the HttpContext for scatter gather scenarios.

Would be awesome to have some utility of some sort within the Yarp infrastructure.

For a scatter scenario, would you want to send anything other than GET requests?

If you want to create new scatter requests, all that is involved is along the lines of

async Task<HttpRequestMessage> CreateScatterRequestAsync(HttpContext context, string destinationPrefix, CancellationToken cancellationToken = default)
{
    if (context.Request.Method != HttpMethods.Get || context.WebSockets.IsWebSocketRequest)
    {
        throw new NotSupportedException("...");
    }

    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Get,
        Version = HttpVersion.Version20,
        VersionPolicy = HttpVersionPolicy.RequestVersionOrLower
    };

    await ScatterTransformer.Instance.TransformRequestAsync(context, request, destinationPrefix, cancellationToken);

    // If you're not setting it in your transformer already
    request.RequestUri ??= RequestUtilities.MakeDestinationAddress(destinationPrefix, context.Request.Path, context.Request.QueryString);

    return request;
}

Most of the YARP logic around creating requests is around handling things like WebSocket version upgrades/downgrades and dealing with a custom HttpContent for POST requests.

In practice the above example is just setting the Method & Version, then calling the transformer. I'm not sure that is all that helpful / generic enough to have in YARP.

Thanks for following up! Yes it would be Get only.

Yeah this code would work. We could then simply pass the request message to the HttpMessageInvoker.

I figured I raise it here since you might be want to consider a scatter gather like abstraction similar to the forwarder interface

We have a general issue to track traffic mirroring (#105), but that is mainly about duplicating outgoing requests and potentially performing validation on different responses. The forwarded response still comes from a single destination.

Splitting requests and then merging responses like in your scenario is bound to involve custom logic to specify how requests are generated, how merging should work, what policies to use for some failed/delayed responses, etc. I'm not aware of an established practice that one would follow here.
Given the highly custom nature of such scenarios (and limited examples of different users doing so), I don't think we should be trying to design an abstraction here, as it's not clear what benefits it would provide.

Closing this issue as wont-fix, but we can of course revisit the decision in the future if there's more user demand and we believe we can provide value.

Absolutely agree with the reasoning. Thanks for taking the time to reply