Search code examples
angularnginxproxyinternationalizationreverse-proxy

Nginx reverse proxy with dynamic basehref?


I have built an i18n app with Angular 9. My api is proxied with the /api/ url. But since i added i18n, proxy doesnt work anymore. Rq: (Angular add /fr/ or /en/ to the url because i add --baseHref flag on compilation)

I want to know how can i tell to my proxy to add the dynamic basehref of my app to the proxy url ? Exemple : How to transform GET myapp.com/fr/api/jobs to GET myapp.com/api/jobs ?

So i have this nginx configuration :

location /fr/ { 
      autoindex on;
      try_files $uri$args $uri$args/ /fr/index.html;
  }

  location /en/ {
      autoindex on;
      try_files $uri$args $uri$args/ /en/index.html;
  }

  # Default to FR
  location / {
      # Autoindex is disabled here + the $uri$args/ is missing from try_files
      try_files $uri$args /fr/index.html;
  }

# Proxy to API call
  location */api/ {
    proxy_pass http://rest-api:9000;
  }

I'm trying to listen everythin before /api/ but this doesnt work...


Solution

  • Consider this location:

      location ~ .*/api/(.*) {
        proxy_pass http://rest-api:9000/api/$1;
      }
    

    This is a regex location that match any URI with /api/ anywhere in it. For example it will work on:

    example.com/api/foo/bar
    example.com/api/
    example.com/something/api/foo/bar
    

    There is a capture group (.*) to record whatever was after /api/. It is saved as a positional variable $1 (because it's the first and only capture group in the expression). Using it you can build an exact path to your API backend:

    proxy_pass http://rest-api:9000/api/$1;
    

    It will turn the examples above into:

    proxy_pass http://rest-api:9000/api/foo/bar
    proxy_pass http://rest-api:9000/api/
    proxy_pass http://rest-api:9000/api/foo/bar
    

    Update: When you use a regex variable $1 in proxy_pass you have to build full URL manually. If your URL can contain arguments (like ?foo=bar) you need to add $is_args$args. '$is_args' is responsible for adding ? if there are any arguments and '$args' are the actual arguments. The full path will be like this:

    proxy_pass http://rest-api:9000/api/$1$is_args$args
    

    Bonus: you can use this simple server to see how NGINX will interpret the configuration:

    server {
      listen 8080;
      location ~ .*/api/(.*) {
        add_header Content-Type text/plain;
        return 200 http://api-server:9000/api/$1;
      }
    }
    

    Access any path with /api/ in it and you will see in your browser how your current location is interpreted.