Обслуговування декількох кінцевих точок проксі під розташуванням у 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.