Проксі-сервер Nginx методом запиту


17

Чи можливо / як я можу налаштувати блок розташування Nginx для проксі-сервісу для різних програм, залежно від методу запиту (тобто GET / POST)?

Причина полягає в тому, що я зараз обробляю 2 методи за двома різними URL-адресами (один через http проксі, а другий через fcgi) і намагаюся зробити його більш "REST" повно, так що в ідеалі хотілося б, щоб GETting ресурс повернув список , тоді як POSTing на той самий ресурс слід додати до списку.

Відповіді:


27

Я не використовую цю конфігурацію, але виходячи з прикладів тут :

location /service  {
  if ($request_method = POST ) {
    fastcgi_pass 127.0.0.1:1234;
  }

  if ($request_method = GET ) {
     alias /path/to/files;
  }
}

Якщо ви пишете власну заявку, ви також можете розглянути можливість перевірки GET / POST у ній та надіслати заголовки X-Accel-Redirect для передачі файлів до nginx.


Блок GET - це proxy_pass в моєму випадку, але в іншому випадку це працює. На даний момент я не використовую другий блок, якщо nginx, як видається, припиняє "обробляти", коли буде досягнуто директиви fastcgi_pass (тобто не пропускається і не проходить пропускний проксі), тому що я хочу, щоб все, окрім POST, поверталося до проксі.
Брентон Алкер

2
Зауважте, що, ifяк правило, відлякує документація Nginx: nginx.com/resources/wiki/start/topics/depth/ifisevil
vog

1
Отже, яка альтернатива?
WM

1
@WM Дивіться мою відповідь: serverfault.com/a/823053/175421
vog

@vog, Цікаво. Досить розумний спосіб це зробити. Дякую, що поділились.
WM

23

Хоча ви могли б досягти цього за допомогою if, це, як правило, відлякує документацію Nginx , тому ifщо не добре поєднується з іншими директивами. Наприклад, припустимо, що GET має бути відкритим для всіх, тоді як POST призначений лише для автентифікованих користувачів, які використовують HTTP Basic Auth. Це вимагатиме ifпоєднання auth_basic, яке не працює належним чином.

Ось альтернатива, яка працює без if. Трюк полягає у використанні "GET" та "POST" як частини імен висхідного потоку, тому їх можна вирішити за допомогою змінної підстановки:

http {
  upstream other_GET {
    server ...;
  }
  upstream other_POST {
    server ...;
  }
  server {
    location /service {
      proxy_pass http://other_$request_method;
    }
  }
}

Щоб поєднати це з HTTP Basic Auth для всього, крім GET, просто додайте limit_exceptблок:

  ...
    location /service {
      proxy_pass http://other_$request_method;
      limit_except GET {
        auth_basic ...;
      }
    }
  ...

Проблема з таким підходом полягає в тому, що ми повернемося 502 gateway errorчерез no resolver defined to resolve other_HEAD(або все, що у вас немає у потоці). Семантичніше буде повернути щось подібне 405 method not allowed. Чи є спосіб досягти цього?
Джеймс

1
@James: Це, можливо, можна охарактеризувати як нове запитання, посилаючись на це. У мене немає відповіді на цю деталь, але, можливо, інші.
vog

0

Це те, що я зробив для того, щоб справи працювали на мене

add_header Allow "GET, POST, HEAD" always;
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
    proxy_pass http://back-end;
}

Отож, що саме переходить між двома кінцевими точками на основі методу запиту?
Основні

0

Трохи зміни у відповіді vog, щоб включити обробник за замовчуванням для інших методів, таких як OPTIONS, PUT тощо.

    upstream webdav_default {
            server example.com;
    }
    upstream webdav_upload {
            server example.com:8081;
    }
    upstream webdav_download {
            server example.com:8082;
    }
    server {
            map upstream_location $request_method {
                    GET     webdav_download;
                    HEAD    webdav_download;
                    PUT     webdav_upload;
                    LOCK    webdav_upload;
                    default webdav_default;
            }
            location / {
                    proxy_pass https://$upstream_location;
            }
    }

0

Я не зміг отримати відповідь від @timmmmmy для роботи, але це вказало мені на документацію на карту, і це працювало для мене:

map $request_method $upstream_location {
   PUT     example.com:8081;
   POST    example.com:8081;
   PATCH   example.com:8081;
   default example.com:8082;
}
server {
   location / {
      proxy_pass https://$upstream_location;
   }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.