Nginx https rewrite เปลี่ยน 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 ผ่านเขียน?

ทุกสิ่งที่เข้าถึงไอพีสาธารณะจะโดน 443 เพราะเขียนใหม่ ภายในเราจะส่งต่อไปยัง 80 บนเครื่องเสมือน

แต่เมื่อฉันเรียกใช้สคริปต์ไพ ธ อนเช่นสคริปต์ด้านล่างเพื่อทดสอบการกำหนดค่าของเรา

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 บนตำแหน่ง [.. ]

สิ่งนี้เป็นจริงสำหรับเบราว์เซอร์ยอดนิยมทั้งหมดและคุณไม่สามารถทำอะไรได้


@ 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/(สังเกตการตาม/) มันก็ประสบความสำเร็จ


ฉันใช้บุรุษไปรษณีย์เพื่อทดสอบการลงชื่อเข้าใช้ django rest-auth และเห็นปัญหาเดียวกันกับที่อธิบายไว้ กุญแจสำคัญคือฉันได้ละเลยการติดตาม '/' ในคำขอ POST
Steve L
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.