How to reverse proxy services using pathnames without changing the service code

I’m trying to set up a scenario where I have a single istio ingress gateway that routes to different pieces of my application. For example to access my GraphQL API I could use <gateway_url>/graphql and for my internal dashboard I could use <gateway_url>/internal/dashboard etc.

The problem I’m having is that when I add a virtual service with a routing rule like this

http:
    - match:
        - uri:
            prefix: /graphql
      route:
        - destination:
            host: my-graphql-api
            port:
              number: 80
            subset: v1

it routes to <my-graphql-api>/graphql rather than <my-graphql-api>/which would mean I’d have to go edit my service source code to nest all routes under /graphql.

Am I doing this incorrectly or is this the expected behavior? I’ve created these types of reverse proxies with nginx before but I’m having trouble getting the same type of behavior with istio gateway.

Thanks!

Sounds like you are looking for ‘rewrite’ functionality - See here https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPRewrite

1 Like

Yes! That’s exactly what I was looking for! Thanks @Haim_Helman!

hmm maybe I spoke too soon @Haim_Helman. My virtual service config looks like this.

http:
  - match:
    - uri:
        prefix: /graphql
    rewrite:
      uri: /

and the intention is that urls starting with <gateway-domain>/graphql would be routed to the graphql service that I have setup.

However, it seems like only the url <gateway-domain>/graphql is being routed correctly but if I do <gateway-domain>/graphql/query it sends back a 404 as If I haven’t set a route for that in the server.

I feel like I’m on the right track but just missing a config or not understanding the gateway correctly.

Ok looks like I’ve figured out how to do this using some info in this older post. Looks like you need two match rules one for the root route / and one for all the rest of the routes /*. So this seems to have fixed it…

http:
  - match:
    - uri:
        prefix: "/graphql/"
    rewrite:
      uri: /
    route:
      - destination:
          host: my-service
          port:
            number: 80
          subset: v1
  - match:
    - uri:
        prefix: "/graphql"
    rewrite:
      uri: /
    route:
      - destination:
          host: my-service
          port:
            number: 80
          subset: v1

Note you do have to edit the code internal to the app if you’re referencing relative urls. e.g. res.redirect("/404"); needs to change to redirect("/graphql/404");