Metoda POST i przekierowania

09 Mar 2017

http  payload  post  redirects 

Share on:

Niedawno jednym z problemów, jaki miałem okazję rozwiązać, było umożliwienie przekazania całej zawartości ładunku HTTP kierowanego pod dany adres za pomocą metody POST, z którego miało nastąpić przekierowanie pod inny adres.

Nie dało się tego wykonać za pomocą standardowych przekierowań, tj. 301 i 302. Rozwiązaniem było wykorzystanie przekierowania o kodzie 307 lub 308 tylko dla metody POST, dzięki czemu pierwotna metoda nie była zamieniana na metodę GET w związku z „przejściem” pod inne miejsce docelowe.

Dlatego zaleca się stosowanie kodu 301 tylko w odpowiedzi na metody GET lub HEAD oraz zamiast tego stosowanie stałego przekierowania 308 dla metod POST, ponieważ zmiana metody jest wyraźnie zabroniona w tym stanie (źródło: Mozilla Web Docs - 301 Moved Permanently).

Opis wybranych przekierowań #

Protokół HTTP definiuje kilka typów przekierowań. Najczęściej wykorzystywane są te o kodach 301 oraz 302. Samo przekierowanie informuje przeglądarkę klienta o konieczności podążania za innym adresem w celu dostępu do danej treści.

Poniżej znajduje się krótki opis wybranych:

Porównanie #

Kod HTTP Opis Obsługa metod
301 Moved Permanently Metoda GET się nie zmienia; pozostałe mogą, ale nie muszą zostać zmienione na GET
302 Found Metoda GET się nie zmienia; pozostałe mogą, ale nie muszą zostać zmienione na GET
303 See Other Metoda GET się nie zmienia; pozostałe zamieniane na GET (utrata zawartość)
307 Temporary Redirect Metoda i zawartość się nie zmieniają
308 Permanent Redirect Metoda i zawartość się nie zmieniają

Przykład konfiguracji #

Oto wykorzystana konfiguracja na przykładzie serwera NGINX:

location / {

  proxy_pass http://localhost:80;
  client_max_body_size 10m;

}

location /api {

  # Przekierowanie 308 tylko dla metody POST:
  if ($request_method = POST) {

    return 308 https://api.example.com?request_uri;

  }

  # Dla pozostałych metod przekierowanie 301:
  return 301 https://api.example.com?request_uri;

  client_max_body_size 10m;

}