Udostępnianie wielu punktów końcowych proxy w lokalizacji w Nginx


14

Mam kilka punktów końcowych interfejsu API, które chcę obsługiwać z jednego miejsca /apiz podścieżkami prowadzącymi do różnych punktów końcowych. W szczególności chcę, aby webdis był dostępny pod adresem /apii zastrzeżony interfejs API dostępny pod adresem /api/mypath.

Nie martwię się o kolizje z interfejsem API webdis, ponieważ używam ścieżek podrzędnych, które raczej nie kolidują z nazwami komend redis, a także mam pełną kontrolę nad projektem interfejsu API, aby uniknąć kolizji.

Oto plik konfiguracyjny z mojego serwera testowego, na którym hakowałem:

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/;
  #}
}

Jak mogę zmienić moje obejście, aby wszelkie żądania /api/mypath/*trafiały do ​​punktu końcowego w porcie 3936, a wszystko inne do portu 7379?


Co masz na myśli tried this to no avail? Co się stało po włączeniu tej dyrektywy lokalizacji? Czas połączenia minął? Lokalizacja niezgodna?
— masegaloeh

Ach, dziękuję za podpowiedź, daje błąd, który nie został znaleziony, przy dalszym badaniu wydaje się, że błąd pochodzi z mojego API, więc działa! : D Ale reguła przepisywania oczywiście nie jest, ponieważ muszę dodać v1 do adresu URL ( localhost / api / mypath / v1 / about ) ... :(
— hamstar

Odpowiedzi:


24

Nie potrzebujesz do tego przepisywania.

server {
  ...

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

Zgodnie z dokumentacją nginx

Lokalizację można zdefiniować za pomocą ciągu przedrostka lub wyrażenia regularnego. Wyrażenia regularne są określane za pomocą poprzedniego ~*modyfikatora (w przypadku rozróżniania wielkości liter) lub ~modyfikatora (w przypadku rozróżniania wielkości liter ). Aby znaleźć lokalizację pasującą do danego żądania, nginx najpierw sprawdza lokalizacje zdefiniowane za pomocą ciągów prefiksów (lokalizacje prefiksów). Spośród nich wybrano i zapamiętano lokalizację z najdłuższym pasującym prefiksem. Następnie sprawdzane są wyrażenia regularne w kolejności ich pojawienia się w pliku konfiguracyjnym. Wyszukiwanie wyrażeń regularnych kończy się przy pierwszym dopasowaniu i używana jest odpowiednia konfiguracja. Jeśli nie zostanie znalezione dopasowanie do wyrażenia regularnego, zostanie użyta konfiguracja zapamiętanej wcześniej lokalizacji prefiksu.

Jeśli najdłużej pasująca lokalizacja prefiksu ma ^~modyfikator, wówczas wyrażenia regularne nie są sprawdzane.

Dlatego każde żądanie, które zaczyna się od, /api/mypath/będzie zawsze obsługiwane przez drugi blok, ponieważ jest to najdłużej pasująca lokalizacja prefiksu.

Każde żądanie, które zaczyna się /api/od, po którym nie następuje natychmiast, mypath/będzie zawsze obsługiwane przez pierwszy blok, ponieważ drugi blok nie pasuje, dlatego pierwszy blok jest najdłuższą pasującą lokalizacją prefiksu.


2
Jeśli spojrzeć na modyfikatorów lokalizacyjnych ( =, ~*, ~, i ^~) może się to wydawać sprzeczne z intuicją, że ^~nie obejmuje wyrażenia regularne (ponieważ ~wskazuje Dopasowanie wyrażenia regularnego) ... Jednak jeśli pamiętamy, ^wewnątrz klasy znaków (np regex [^a-z]) neguje , że klasa (taka, że ​​przykład oznacza (dowolny znak z wyjątkiem z az); podobnie, ^~neguje wszelkie potencjalne bloki lokalizacji wyrażeń regularnych.
— Doktor J

6

OK się zorientowałem, myślałem, że błąd „nie znaleziono” pochodzi z nginx, ale tak naprawdę pochodzi z mojego API. To jest moje rozwiązanie, jeśli ktoś jest zainteresowany:

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/;
  }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.