Обслуговування декількох кінцевих точок проксі під розташуванням у Nginx


14

У мене є кілька кінцевих точок API, які я хочу обслуговувати під одним місцем /apiіз підпутниками, що йдуть до різних кінцевих точок. Зокрема, я хочу, щоб webdis був доступний на веб-сайті, /apiа власний API був доступний на сайті /api/mypath.

Мене не турбують сутички з API webdis, тому що я використовую підпути, які навряд чи можуть зіткнутися з іменами команд redis, а також маю повний контроль над дизайном API, щоб уникнути сутичок.

Ось конфігураційний файл з мого тестового сервера, на який я взлом:

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

Як я можу змінити своє вирішення, щоб будь-які запити /api/mypath/*переходили до кінцевої точки в порту 3936, а все інше - до порту 7379?


Що ви маєте на увазі під tried this to no avail? Що сталося, коли ви включили цю директиву про місцезнаходження? Час очікування з'єднання? Місце не збігається?
— masegaloeh

Ах, дякую за підказку, вона дає не знайдену помилку, при подальшому розслідуванні виявляється, що помилка надходить від мого API, тому вона працює! : D Але правило переписати, очевидно, не тому, що я повинен додати v1 до URL ( localhost / api / mypath / v1 / about ) ... :(
— hamstar

Відповіді:


24

Для цього вам не потрібно переписувати.

server {
  ...

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

Відповідно до документації nginx

Місце розташування може бути визначене за допомогою рядка префікса або регулярним виразом. Регулярні вирази задаються за допомогою попереднього ~*модифікатора (для невідповідності регістру) або ~модифікатора (для відповідності регістру). Щоб знайти місце, яке відповідає заданому запиту, nginx спочатку перевіряє місця, визначені за допомогою рядків префікса (префікса місця). Серед них вибирається та запам'ятовується місцеположення з найдовшим відповідним префіксом. Потім перевіряються регулярні вирази в порядку їх появи у файлі конфігурації. Пошук регулярних виразів закінчується в першій відповідності, і використовується відповідна конфігурація. Якщо не знайдено збігу з регулярним виразом, тоді використовується конфігурація пам'яті, що запам'ятовувалася раніше.

Якщо місце найдовшого відповідного префікса має ^~модифікатор, регулярні вирази не перевіряються.

Тому будь-який запит, який починається з /api/mypath/, завжди буде поданий другим блоком, оскільки це найдовше місце узгодження префікса.

Будь-який запит, який починається з /api/не одразу після нього mypath/, завжди буде обслуговуватися першим блоком, оскільки другий блок не відповідає, тому перетворюючи перший блок на найдовше місце узгодження префікса.


2
Якщо подивитися на модифікатори розташування ( =, ~*, ~і ^~) може здатися нелогічним , що ^~виключає регулярні вирази (так як ~вказує на відповідність регулярному виразу) ... Однак, якщо ви пам'ятаєте, ^всередині класу символів регулярних виразів (наприклад [^a-z]) заперечує , що клас (так, що приклад означає (будь-який символ, за винятком символів az); аналогічно, ^~заперечує будь-які потенційні блоки розташування регулярних виразів
— Doktor J

6

Гаразд зрозумів це, я вважав, що помилка "не знайдено" надходить з nginx, але насправді вона надходить з мого API. Це моє рішення, якщо когось цікавить:

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/;
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.