Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply pattern transform to the host destination address #399

Closed
murilocurti opened this issue Sep 6, 2020 · 3 comments
Closed

Apply pattern transform to the host destination address #399

murilocurti opened this issue Sep 6, 2020 · 3 comments
Labels
Type: Idea This issue is a high-level idea for discussion.

Comments

@murilocurti
Copy link

murilocurti commented Sep 6, 2020

With pattern matching support in the destination address the proxy will be very flexible and useful for API Versioning.

This way the reverse proxy will help a lot in cases where the api versions are published to different hosts like:

myapi-v1.azurewebsites.net
myapi-v2.azurewebsites.net

Examples:

path: "v{version}/{**catch-all}"
address: https://myapi-v{version}.azurewebsites.net"

https://proxy.azurewebsites.net/v1/test/1 -> https://myapi-v1.azurewebsites.net/test/1
https://proxy.azurewebsites.net/v2/test/2 -> https://myapi-v2.azurewebsites.net/test/2

                new ProxyRoute()
                {
                    RouteId = "route2",
                    ClusterId = "cluster2",

                    Match =
                    {
                        Path = "v{version}/{**catch-all}",
                    },
                    Transforms = new Dictionary<string, string>[]
                    {
                        new Dictionary<string, string>()
                        {
                            {  "HostPattern", null }  //ugly, I know
                        }
                    }
                }

                new Cluster()
                {
                    Id = "cluster2",
                    Destinations =
                    {
                        { "myVersionedApi", new Destination() { Address = "https://myapi-v{version}.azurewebsites.net" } }
                    }
                }

@murilocurti murilocurti added the Type: Idea This issue is a high-level idea for discussion. label Sep 6, 2020
@Tratcher
Copy link
Member

Tratcher commented Sep 7, 2020

Something like this is possible already, but only within the path:
https://microsoft.github.io/reverse-proxy/articles/transforms.html#pathpattern

Getting it into the destination host is trickier, that's not a field we currently support transforms for.
https://github.com/microsoft/reverse-proxy/blob/32b6174b3bcc299a5272ae8d11630049d3c74d2b/src/ReverseProxy/Service/RuntimeModel/Transforms/RequestParametersTransformContext.cs

That said, templated destinations seem at odds with some of the other parts of the stack. E.g. Counting the number of outstanding requests per destination for load balancing purposes, or sending health checks to the destinations.

From a higher level design, different versions of your site should be hosted in different logical Clusters, each with their own destinations. Then you'd have a route for each version that mapped to each cluster. The partitioning feature might also allow this to be done with a single route.

                new ProxyRoute()
                {
                    RouteId = "route1",
                    ClusterId = "cluster1",

                    Match =
                    {
                        Path = "v1/{**catch-all}",
                    }
                },
                new ProxyRoute()
                {
                    RouteId = "route2",
                    ClusterId = "cluster2",

                    Match =
                    {
                        Path = "v2/{**catch-all}",
                    }
                }

                new Cluster()
                {
                    Id = "cluster1",
                    Destinations =
                    {
                        { "myVersionedApi1", new Destination() { Address = "https://myapi-v1.azurewebsites.net" } }
                    }
                },
                new Cluster()
                {
                    Id = "cluster2",
                    Destinations =
                    {
                        { "myVersionedApi2", new Destination() { Address = "https://myapi-v2.azurewebsites.net" } }
                    }
                }

While slightly more verbose, it's much less complex to implement (it should already work today).

Edit: I forgot the transform to remove the version from the path.
https://microsoft.github.io/reverse-proxy/articles/transforms.html#pathremoveprefix

{ "PathRemovePrefix": "/v1" }

@murilocurti
Copy link
Author

@Tratcher Thank you for all thoughts!

I've already aware about those 'static' options. And I'm using 1 cluster per version. It's working fine.
This way we need to create a new entry for each new version. That can be automated.

Very good point about load balancing and health checks.
An extra storage layer/module will be necessary to keep all destination variations and health check then.

Maybe a DynamicDestination class can be an exception for the rule.
It would accept template transforming but don't have load balancing and/or health checks.

I'm not sure about it. But could be really useful.

I didn't get how partition will work.

Thanks!

@karelz
Copy link
Member

karelz commented Sep 8, 2020

Triage: It seems support of templated destination would bring bunch of complexities, which don't seem to justify the value.
Closing for now. If there are more customers, more demand and additional information in future, we can reconsider. Thanks!

@karelz karelz closed this as completed Sep 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Idea This issue is a high-level idea for discussion.
Projects
None yet
Development

No branches or pull requests

3 participants