Назад | Перейти на главную страницу

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

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

Для этого не нужно переписывать.

server {
  ...

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

В соответствии с документация nginx

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

Если у самого длинного совпадающего префикса есть ^~ модификатор, то регулярные выражения не проверяются.

Поэтому любой запрос, который начинается с /api/mypath/ всегда будет обслуживаться вторым блоком, так как это самое длинное совпадение расположение префикса.

Любой запрос, который начинается с /api/ не сразу следует mypath/ всегда будет обслуживаться первым блоком, так как второй блок не совпадает, поэтому первый блок самое длинное совпадение расположение префикса.

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