2

I am building a multi-tenant application where the tenant name is contained within every url. For example, a route to retrieve all current users of the tenant "Test" would look like this: /ui/api/Test/users. The part of the application I am currently working on is a client that forwards the requests of any other application it supports to my DB service, allowing the client to act as a go-between.

You can probably see where this is going. I am using Zuul to forward my routes, but not ALL routes should be forwarded in this manner. Sometimes, the frontend will send requests that start with /ui/api/ that are not database requests. Let's say one of these looks like this: /ui/api/Test/Foo. I want to able to configure my Zuul routes in such a manner that I can forward any url that fits the pattern /ui/api/*/users (where * is any string) without forwarding any others.

I have of course attempted to simply use /ui/api/*/users, but this will not match any route. I haven't tried it, but I assume that it simply interprets * as an actual part of the url. My current workaround is to match /ui/api/** and then add **/Foo to the zuul.ignoredPatterns. This works, but is supoptimal, since any new endpoint that I require to not be forwarded will need to be added here. Since the client is meant to be used in various projects, the forwarded routes will not change, but the ones that should not be will. This is not configurable per project and thus not a viable solution.

This is what the relevant part of my application.properties looks like:

zuul.ignoredPatterns = /**/login,/**/executeJobUrl,/**/createExecuteJobUrl

zuul.routes.user-manager.path = /ui/api/**
zuul.routes.user-manager.url = http://localhost:0/eis-user-manager/ui/api
zuul.routes.user-manager.stripPrefix = true
Alex Eggers
  • 328
  • 3
  • 16
  • 2
    Wouldn't /ui/api/**/users work? – Norbert Bicsi Feb 12 '19 at 13:32
  • @NorbertBicsi You are absolutely right, that worked! I can't believe I didn't try that here...I seem to recall having a similar project a while back where I did try this, but it didn't work due to other factors. I must have simply blanked that out. Thanks a lot! If you post this as an answer, I'll accept it. – Alex Eggers Feb 12 '19 at 14:25
  • Ok, thanks. Last I configured zuul was like 2 years ago and wasn't 100% sure thats why I only commented. But now that you tested it I will make an answer. – Norbert Bicsi Feb 12 '19 at 14:27
  • Ok, so posted an answer, hope you like it. Also don't know how forced you are to use zuul, but if it is possible you can also look into Spring Cloud Gateway which I have used as an alternative. Plus there are many others out there. – Norbert Bicsi Feb 12 '19 at 14:37

2 Answers2

3

The working solution is to use ** in the pattern. So it would be

 /ui/api/**/users

I got the idea from here. Credit also to Alex Eggers for testing and suggesting to make an answer.

Norbert Bicsi
  • 1,562
  • 2
  • 19
  • 33
2

I have some routes working with partial wildcards, as a solution to a similar problem to what you describe. I could not get a path like /api/**/v1.1/user** to work, but /api/*admin/v1.1/user** works fine. I concluded that the wildcard alone was too greedy...

The only but is that you need to name your services something like "somecompanyadmin", "msadmin" and "someothercompanyadmin" instead of "somecompany", "ms" and "someothercompany"...

Here is a sample configuration that works for my case:

zuul:
  routes:
    mock:
      path: /v1.1/**
      url: https://myserver:6154/v1.1
    users:
      path: /api/*admin/v1.1/user**
      serviceId: user_server
      stripPrefix: true
    permission:
      path: /api/*admin/v1.1/permission/**
      serviceId: permission_server
      stripPrefix: true
JoSSte
  • 2,953
  • 6
  • 34
  • 54
  • Wow, I almost can't believe it. If this works, you'd assume that simply using * would as well! I don't think I can convince my boss to add a pre- or suffix to all our services ^^" – Alex Eggers Feb 12 '19 at 13:41
  • I had a question similar to yours up a year or so ago, and no-one had an answer. the alternative is to add all the routes for each company... you may be able to do it programatically - see the first comment here: https://stackoverflow.com/questions/43042463/spring-cloud-zuul-how-to-add-route-without-restart – JoSSte Feb 12 '19 at 13:45
  • Where is the prefix stripped in the above case? At /api/ ? – Alex Eggers Feb 12 '19 at 14:04
  • I thiink I understand your question, and if so, yes. so `/api/msadmin/v1.1/user/blablabla` is captured by `/api/*admin/v1.1/user**` – JoSSte Feb 12 '19 at 14:16
  • What I mean is, what part of the matched routed is added to the url? In the example you just gave, would that be /msadmin/v1.1/...? – Alex Eggers Feb 12 '19 at 14:22