ExpressJS routes not resolving

5/17/2018

I have a small microservice written in typescript running in a kubernetes cluster on AKS. I have ingress generated using Helm

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-service
  labels:
    app: test-service
    chart: test-service-0.1.0
    release: test-service
    heritage: Tiller
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
spec:
  tls:
    - hosts:
        - test.xyz
      secretName: default-tls
  rules:
    - host: test.xyz
      http:
        paths:
          - path: /payments
            backend:
              serviceName: test-service
              servicePort: 4040

And the service

apiVersion: v1
kind: Service
metadata:
  name: existing-bumblebee-payments-service
  labels:
    app: test-service
    chart: test-service-0.1.0
    release: existing-bumblebee
    heritage: Tiller
spec:
  type: ClusterIP
  ports:
    - port: 4040
      targetPort: 4040
      protocol: TCP
  selector:
    app: test-service
    release: existing-bumblebee

And in my microservice

export class Server {
private registerRoutes() {
        this.app.use("/cards", CardRouter);
        this.app.use("/wallets", WalletRouter);
        this.app.use("/preauth", PreauthRouter);
        this.app.use("/charge", ChargeRouter);
    }
}

The routers look like this;

    import { Router } from "express";
    // other imports
    import { checkSchema, check } from "express-validator/check";

    const router = Router();

    router.get("/", CardController.index);
    router.get("/:id", [
        check("id")
            .isUUID()
            .withMessage("Invalid UUID")
    ], CardController.get);
    router.delete("/:id", [
        check("id")
            .isUUID()
            .withMessage("Invalid UUID")
    ], CardController.remove);
    router.post("/", checkSchema(CardCreateRules), CardController.add);

export default router;

But accessing the service via https://test.xyz/payments/cards results in a 404 error from express

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Error</title>
    </head>
    <body>
        <pre>Cannot GET /payments/cards</pre>
    </body>
</html>

I can tell the response is from the express server cause it has custom response headers set by the server. I'm really confused as to what is wrong, any help will be appreciated.

-- MrFoh
express
javascript
kubernetes-helm
kubernetes-ingress
typescript

1 Answer

5/21/2018

It does not work for you because your ingress just redirects request https://test.xyz/payments/cards to test-service without rewriting the path. So test service still becomes request "/payments/cards" and obviously can not handle them.

You can either reconfigure express application to support /payments/cards or do the path rewrite via ingess 'nginx.ingress.kubernetes.io/rewrite-target' annotation:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-service
  labels:
    app: test-service
    chart: test-service-0.1.0
    release: test-service
    heritage: Tiller
  annotations:
    ingress.kubernetes.io/rewrite-target: /
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /payments
spec:
  tls:
    - hosts:
        - test.xyz
      secretName: default-tls
  rules:
    - host: test.xyz
      http:
        paths:
          - path: /
            backend:
              serviceName: test-service
              servicePort: 4040
-- abinet
Source: StackOverflow