1

I want to forward requests to the subdirectory v1 (subdomain.domain.com/v1) to my root in Nginx. Tried this and this answer (and more variations) with no success. I use the Slim API framework.

My nginx config looks like this:

    events {
}
http {
  include /etc/nginx/mime.types;
  server {
    listen 80;
    server_name subdomain.domain.com;
    root /var/www/html;
    index index.php;
    try_files $uri $uri/ /index.php?$query_string;
    location /healthcheck {
      auth_basic off;
      allow all;
      return 200;
    }
    location / {
      if (!-f $request_filename) {
        rewrite ^(.*)$ /index.php$1 last;
      }
    }
    #location ~ \.php {
    # only allow index.php to be proxied to FastCGI process (more secure than all php files!)
    location /index.php {
      proxy_pass http://127.0.0.1:9000;
    }
    location location ~ ^/v1/(.*) {
      return 301 $scheme://$http_host/$1$is_args$query_string;
    }
  }
}

My ingress yaml (Kubernetes) looks like this:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
 name: ingress-ENVIRONMENT_NAME_SHORT-NAME_OF_DEPLOYMENT
 namespace: NAME_OF_NAMESPACE
 annotations:
   kubernetes.io/ingress.class: gce
   kubernetes.io/ingress.global-static-ip-name: ip-ENVIRONMENT_NAME_SHORT-NAME_OF_DEPLOYMENT
   networking.gke.io/managed-certificates: cert-ENVIRONMENT_NAME_SHORT-NAME_OF_DEPLOYMENT
   kubernetes.io/ingress.allow-http: "false"
spec:
  rules:
    - host: NAME_OF_DOMAIN
      http:
        paths:
          - path: /v1/*
            backend:
              serviceName: svc-ENVIRONMENT_NAME_SHORT-NAME_OF_DEPLOYMENT
              servicePort: 443

I only get this thing to run without /v1 (just subdomain.domain.com). Any guidance appreciated.

UPDATE (Jun 2021): in SLIM 4 this is now as easy as it gets: $app->setBasePath("/index.php/v1");

chriscross
  • 413
  • 5
  • 18

1 Answers1

2

The best approach I believe is to have the redirect happen at the ingress level or even prior to hitting the ingress. However, GCE ingress doesn't support HTTP to HTTPS redirects yet, let alone any kind of redirect.

The way you have it, is basically this way: the ingress gets a /v1 request then it goes to Nginx and then it says redirect to / but that redirect request goes back to the ingress which says I don't know what to do with / request.

Another approach is just to have your backend serve on /v1 or use a two-layered approach which is pretty common. GCE LB (with no ingress controller) ➡️ Nginx ingress (which does the redirect and has a much richer feature set) ➡️ backend.

Rico
  • 58,485
  • 12
  • 111
  • 141
  • For many reasons I want to stick with the gce ingress controller. This ("Another approach is just to have your backend serve on /v1..") is interesting. I guess exactly what I am looking for. I only have the code for v1 on the php-fpm and nginx server, nothing else. For a potential v2 I would add that path in ingress and have a different backend (with another nginx running) – chriscross Jul 15 '20 at 10:05
  • How can I achieve this? I am flexible to bring my files into a subfolder v1 (which I tried) but failed with nginx config – chriscross Jul 15 '20 at 12:53
  • I didn't mean bring the files to `v1` folder. I meant basically have your service actually server under `v1`. Something like if you were to access it through localhost it would be like `http://127.0.0.1/v1/` – Rico Jul 15 '20 at 14:35
  • Probably I do not understand this. I managed to get it running with a normal php file, just phpinof() (but not with SLIM): location / { try_files $uri /index.php; } and location ~ \.php { proxy_pass http://127.0.0.1:9000; }. I can forward any request to index.php, since this is the only file needed under v1. Guess I am missing to give the path to Slim (I see it forwards any request with 301 to v1 then again to v1 returning 404). – chriscross Jul 15 '20 at 14:40
  • Sorry last part in bracket is wrong: directly 404, the 301 was in cache – chriscross Jul 15 '20 at 14:46
  • I'm not sure how it works with php when you want to serve under `/v1` by typically other frameworks you can set a path where you want to serve from. I may not be possible with php, in which case you'll have to find other alternatives. – Rico Jul 15 '20 at 14:59