web-dev-qa-db-fra.com

Servir plusieurs points de terminaison proxy sous emplacement dans Nginx

J'ai quelques points de terminaison d'API que je souhaite servir à partir d'un emplacement unique de /api avec des sous-chemins allant vers différents points de terminaison. Plus précisément, je souhaite que les webdis soient disponibles sur /api et une API propriétaire disponible sur /api/mypath.

Je ne m'inquiète pas des conflits avec l'API webdis car j'utilise des sous-chemins qui ne risquent pas de se heurter aux noms de commandes redis, et j'ai également un contrôle total sur la conception de l'API pour éviter les conflits.

Voici le fichier de configuration de mon serveur de test sur lequel je pirate:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # temporary hardcoded workaround
  location = /api/mypath/about {
    proxy_pass http://localhost:3936/v1/about;
  }

  location /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }

  # tried this but it gives "not found" error
  #location ^~ /api/mypath/ {
  #  rewrite ^/api/mypath/(.*)$ /$1 break;
  #  proxy_pass http://localhost:3936/v1/;
  #}
  #
  #location ^~ /api {
  #  rewrite ^/api/(.*)$ /$1 break;
  #  proxy_pass http://localhost:7379/;
  #}
}

Comment puis-je modifier ma solution de contournement afin que toute demande à /api/mypath/* ira au point de terminaison au port 3936, et tout le reste au port 7379?

14
hamstar

Vous n'avez pas besoin de réécrire pour cela.

server {
  ...

  location ^~ /api/ {
    proxy_pass http://localhost:7379/;
  }
  location ^~ /api/mypath/ {
    proxy_pass http://localhost:3936/v1/;
  }
}

Selon la documentation nginx

Un emplacement peut être défini soit par une chaîne de préfixe, soit par une expression régulière. Les expressions régulières sont spécifiées avec le précédent ~* le modificateur (pour la correspondance insensible à la casse), ou le ~ modificateur (pour la correspondance sensible à la casse). Pour trouver un emplacement correspondant à une demande donnée, nginx vérifie d'abord les emplacements définis à l'aide des chaînes de préfixe (emplacements de préfixe). Parmi eux, l'emplacement avec le préfixe correspondant le plus long est sélectionné et mémorisé. Les expressions régulières sont ensuite vérifiées, dans l'ordre de leur apparition dans le fichier de configuration. La recherche d'expressions régulières se termine à la première correspondance et la configuration correspondante est utilisée. Si aucune correspondance avec une expression régulière n'est trouvée, la configuration de l'emplacement du préfixe mémorisé précédemment est utilisée.

Si l'emplacement du préfixe correspondant le plus long a le ^~ modificateur alors les expressions régulières ne sont pas vérifiées.

Par conséquent, toute demande commençant par /api/mypath/ sera toujours servi par le deuxième bloc car c'est l'emplacement du préfixe le plus long.

Toute demande commençant par /api/ pas immédiatement suivi de mypath/ sera toujours servi par le premier bloc, puisque le deuxième bloc ne correspond pas, faisant donc du premier bloc l'emplacement de préfixe le plus long.

24
Alexey Ten

OK compris, je pensais que l'erreur "introuvable" provenait de nginx, mais en fait, elle provenait de mon API. C'est ma solution si quelqu'un est intéressé:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # automatically go to v1 of the (grape) API
  location ^~ /api/mypath/ {
    rewrite ^/api/mypath/(.*)$ /v1/$1 break;
    proxy_pass http://localhost:3936/;
  }

  location ^~ /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }
}
6
hamstar