Обслуживание нескольких конечных точек прокси в Nginx

13

У меня есть пара конечных точек 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?

hamstar
источник
Что вы имеете в виду 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]) отрицает , что class (такой, что означает в примере (любой символ, кроме символов из az); аналогично, ^~отменяет любые потенциальные блоки местоположения регулярного выражения.
Doktor J
6

Хорошо, понял, я думал, что «not found» ошибка исходит от 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/;
  }
}
hamstar
источник