Nginx https переписати перетворює POST в GET


17

Мій проксі-сервер працює на ip A, і таким чином люди отримують доступ до моєї веб-служби. Конфігурація nginx перенаправить на віртуальну машину на ip B.

Для проксі-сервера в IP A я маю це на своїх доступних сайтах

server {
        listen 443;
        ssl on;
        ssl_certificate nginx.pem;
        ssl_certificate_key nginx.key;

        client_max_body_size 200M;
        server_name localhost 127.0.0.1;
        server_name_in_redirect off;

        location / {
                proxy_pass http://10.10.0.59:80;
                proxy_redirect http://10.10.0.59:80/ /;

                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

}

server {
        listen 80;
        rewrite     ^(.*)   https://$http_host$1 permanent;
        server_name localhost 127.0.0.1;
        server_name_in_redirect off;
        location / {
                proxy_pass http://10.10.0.59:80;
                proxy_redirect http://10.10.0.59:80/ /;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

Зображення proxy_redirectбуло взято з того, як я можу nginx пересилати HTTP POST-запити через перезапис?

Все, що потрапить у загальнодоступний IP, потрапить на 443 через перезапис. Внутрішньо ми пересилаємо до 80 на віртуальну машину.

Але коли я запускаю сценарій python, такий як наведений нижче, щоб перевірити нашу конфігурацію

import requests

data = {'username': '....', 'password': '.....'}
url = 'http://IP_A/api/service/signup'

res  = requests.post(url, data=data, verify=False)
print res
print res.json
print res.status_code
print res.headers

Я отримую 405 Method Not Allowed. У nginx ми з'ясували, що, потрапляючи на внутрішній сервер, внутрішній nginx отримував GETзапит, навіть якщо в початковому заголовку ми це зробили POST(це було показано в сценарії Python).

Тож, схоже, у переписування є проблема. Будь-яка ідея, як це виправити? Коли я прокоментував перезапис, він напевно набрав 80, і він пройшов. Оскільки перезапис зміг поговорити з нашим внутрішнім сервером, тому переписати себе не має жодних проблем. Це просто переписують впала POSTдо GET.

Дякую!

(Про це також запитають на форумі Nginx, оскільки це критичний блокатор ...)

Відповіді:


8

Це не Nginx, це ваш браузер.

Примітка від RFC2616:

RFC 1945 і RFC 2068 вказують, що клієнту заборонено змінювати метод на перенаправлений запит. Однак більшість існуючих реалізацій користувальницьких агентів трактують 302 так, ніби це відповідь 303, виконуючи GET на Location [..]

Це стосується всіх популярних браузерів, і ви нічого з цим не можете зробити.


@ c2h50h Я розумію, що специфікація HTTP заявила щось подібне. Але що я можу зробити в Nginx? Я маю в виду , що це тривіальна установка , де люди вперед 443 до внутрішнього 80 порту, але вони все ще можуть зробити PUT, POST, DELETE, GET. У попередньому налаштуванні у мене не було цього додаткового проксі на фронті, який обслуговував натовп. У мене була однакова конфігурація на тому ж внутрішньому сервері (нашому тестовому сервері). Це прекрасно працює.
CppLearner

Нічого. Це 100% клієнтська сторона. Якщо веб-сервер, будь-який веб-сервер, поверне переадресацію 301 або 302, тоді браузер на стороні клієнта замінить будь-який тип запиту на GET. Ні конфігурація на стороні сервера, ні повернені заголовки http не змінять це. Це так з історичних причин (ранні веб-переглядачі так поводилися через нерозуміння, і це стало фактичним стандартом).
c2h5oh

Ну для одного це насправді не браузер. Ну, ви можете сказати, що це браузер, тому що він використовує протокол HTTP ... добре ... це добре. Але знову ж таки, схоже, це відбувається лише в тому випадку, якщо я робив над цією двошаровою конфігурацією. Якщо я повинен був би поставити ту саму конфігурацію безпосередньо на внутрішній апарат і запустити тест там, він не поскаржиться. Але знову ж таки, як люди роблять це у своєму виробництві? Я б припустив, що деякі люди роблять подібну річ, перевернувши 443 на деякий VM, який може працювати лише 80. Якщо є краща практика, я хотів би вивчити її і почути про неї.
CppLearner

1
Під браузером я мав на увазі клієнт HTTP і з усіма популярними клієнтами POSTстану, GETякщо він переспрямований 301 або 302. POST залишатиметься POST на переадресації проксі, але не на перезаписі.
c2h5oh

1
Знову RFC2616: If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.Отже, у більшості браузерів з’явиться попереджувальне повідомлення, оскільки для інших клієнтів HTTP я навіть не здогадуюсь, якою буде їх поведінка.
c2h5oh

1

Я виявив, POST /api/brandщо перетворюється на те, GET /api/brandщо веб-додаток, який я використовував ( flask-restful), робив "недійсний" запит. Якщо я використовував POST /api/brand/(помічаю трейлінг /), це було успішно.


Я використовував Postman для тестування входу в django rest-auth, і я бачив те саме, що описано. Ключовим було те, що я знехтував останнім '/' у запиті POST.
Стів Л
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.