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

Multiple matching routes #212

Open
bkeroackdsc opened this issue Jun 3, 2015 · 4 comments
Open

Multiple matching routes #212

bkeroackdsc opened this issue Jun 3, 2015 · 4 comments

Comments

@bkeroackdsc
Copy link

After reading the documentation, I'm not clear on what would happen if an incoming request matches the routes associated with multiple frontends. Is it possible to set up some priority scheme among frontends?

The use case I'm thinking of is having one frontend with a set of path regexps and then having a second "fallback" frontend that matches everything else.

It's not clear from the docs how this might be accomplished.

@archisgore
Copy link

Yes, we had the same problem, and I made a small commit recently that allows you to set up a custom NotFound middleware upon startup.

My use-case was similar to yours, and I spent a lot of time thinking about specificity and priority. The problem for me was priorities change, are difficult to infer and difficult to manage. Specificity is worse still - looking at two regex's, it is very difficult, if not impossible, to define which one is more specific.

Since my use-case was WAY simpler, all I needed was a way to capture all unmatched requests and send them to one default route.

Here's a snippet we use - follow the middleware writing pattern:

func GetRegistry(nsqdendpoints []string, selfaddress string) (*plugin.Registry, error) {
r := plugin.NewRegistry()

specs := []*plugin.MiddlewareSpec{

    connlimit.GetSpec(),

    ratelimit.GetSpec(),

    rewrite.GetSpec(),

    cbreaker.GetSpec(),

    trace.GetSpec(),
}

if notFoundMiddleware, err := custommiddleware.New(); err == nil {
    r.AddNotFoundMiddleware(notFoundMiddleware)
}

for _, spec := range specs {
    if err := r.AddSpec(spec); err != nil {
        return nil, err
    }
}
return r, nil

}

@bkeroackdsc
Copy link
Author

@archisgore Thank you for that info. Looking at the source a bit, it's apparent that it simply executes the first matching route (stored in order of insertion). So we can prioritize (in a hackish way) by controlling the order of rule insertion.

It would be nice if this were documented somewhere ("Order of frontend insertion is significant"). It also would be great to have some additions to the routing language syntax: vulcand/route#8, vulcand/route#9.

@archisgore
Copy link

Yes, that's fair. Rather than add it to the routing language, I would prefer it if it were part of the frontend's structure that assigned each frontend a priority with an explicit contract that, two frontends with the same priority can be in arbitrary order.

Put concisely,

Each fronted struct will have:

type engine.Frontend struct {
//some stuff
priority int
}

And on any frontend modification (upsert/delete), we do:

unstableSort(frontends)

About routing library, I'm going to open a new issue to discuss other ideas I have around it.

@archisgore
Copy link

I'm making this request in route: vulcand/route#10

This is to allow us to rapidly run some trial-errors by plugging in variants of the routing library and test cases. Thanks to how go works, we can't easily fork vulcan/route/etc. and run it properly without replacing all import paths in thousands of files. By making it an interface, it'll allow me to work on various features like priorities, OR operator, and so forth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants