Tại sao HTTP không có chuyển hướng POST?


162

Chuyển hướng HTTP được thực hiện thông qua mã HTTP 301 và 302 (cũng có thể là các mã khác) và trường tiêu đề được gọi là "Vị trí" có địa chỉ của địa điểm mới sẽ đến. Tuy nhiên, các trình duyệt luôn gửi yêu cầu "NHẬN" tới URL đó.

Tuy nhiên, nhiều lần bạn cần chuyển hướng người dùng của mình sang tên miền khác thông qua POST (ví dụ thanh toán ngân hàng). Đây là một kịch bản phổ biến, và thực sự là một yêu cầu. Có ai biết tại sao một yêu cầu chung như vậy đã bị bỏ qua trong đặc tả HTTP không? Cách giải quyết là gửi một biểu mẫu (có tham số trong các trường ẩn) với hành động được đặt đến vị trí đích (giá trị của trường tiêu đề Vị trí ) và sử dụng setTimeoutđể gửi biểu mẫu đến vị trí đích.


1
Là mã trạng thái 307 những gì bạn đang tìm kiếm? Xem câu trả lời của tôi dưới đây.
David Ruttka

Câu trả lời:


180

Trong HTTP 1.1, thực sự có một mã trạng thái ( 307 ) cho biết rằng yêu cầu phải được lặp lại bằng cách sử dụng cùng một phương thức và dữ liệu đăng .

Như những người khác đã nói, có một khả năng sử dụng sai ở đây có thể là lý do tại sao nhiều khung công tác dính vào 301 và 302 trong bản tóm tắt của chúng. Tuy nhiên, với sự hiểu biết đúng đắn và cách sử dụng có trách nhiệm, bạn sẽ có thể hoàn thành những gì bạn đang tìm kiếm.

Lưu ý rằng theo thông số W3.org , khi METHODkhông HEADhoặc GET, các tác nhân người dùng nên nhắc người dùng trước khi thực hiện lại yêu cầu tại vị trí mới. Bạn cũng nên cung cấp một ghi chú và cơ chế dự phòng cho người dùng trong trường hợp tác nhân người dùng cũ không chắc chắn phải làm gì với 307.

Sử dụng mẫu này:

<form action="Test307.aspx" method="post">
    <input type="hidden" name="test" value="the test" />
    <input type="submit" value="test" />    
</form>

Và việc có Test307.aspx chỉ cần trả lại 307 với Vị trí: http://google.com , Chrome 13 và Fiddler xác nhận rằng "test = test" thực sự được đăng lên Google. Tất nhiên, phản hồi tiếp theo là 405 vì Google không cho phép POST, nhưng nó cho thấy cơ chế.

Để biết thêm thông tin, xem Danh sách mã trạng thái HTTP và thông số W3.org .

307 Chuyển hướng tạm thời (kể từ HTTP / 1.1) Trong dịp này, yêu cầu nên được lặp lại với một URI khác, nhưng các yêu cầu trong tương lai vẫn có thể sử dụng URI gốc. 2 Ngược lại với 303, không nên thay đổi phương thức yêu cầu khi phát hành lại yêu cầu ban đầu. Chẳng hạn, một yêu cầu POST phải được lặp lại bằng một yêu cầu POST khác.


2
@DavidRuttka, Trình duyệt hỗ trợ gì trong tự nhiên ?
Pacerier

5
@DavidRuttka bạn có thể muốn cập nhật câu trả lời của mình để đưa rfc7231 vào tài khoản (obsoletes rfc2616). Nhắc người dùng dựa trên yêu cầu trong rfc2616. Yêu cầu này được bỏ trong rfc7231 và rfc7231 cũng đưa ra yêu cầu 307 chuyển hướng không được thay đổi phương thức yêu cầu (mà bạn đề cập trong phần trích dẫn của bạn kết thúc câu trả lời của bạn).
nibarius

Lưu ý rằng theo tools.ietf.org/id/draft-hunt-http-rest-redirect-00.html "Mã chuyển hướng HTTP 301-306 KHÔNG NÊN sử dụng trừ khi nhà cung cấp dịch vụ biết khách hàng thực tế là người dùng- đại lý "Vì vậy, có vẻ như các dịch vụ ReSTful nên sử dụng 308 thay vì 301. Tuy nhiên đây chỉ là một bản nháp.
Bruce Adams

49

Tôi tìm thấy một lời giải thích tốt trên trang này ở đây .

Các tình huống đơn giản nhất trên WWW là các giao dịch "bình thường", tức là những giao dịch có thể lặp lại mà không gây ra bất kỳ tác hại nào. Đây thường là các giao dịch "GET", bởi vì chúng đang truy xuất các tham chiếu URL đơn giản (ví dụ: href = hoặc src = các thuộc tính trong HTML) hoặc bởi vì chúng là dạng đệ trình bằng cách sử dụng phương thức GET. Chuyển hướng một giao dịch loại đó rất đơn giản và không có câu hỏi nào: khách hàng nhận được phản hồi chuyển hướng, bao gồm tiêu đề Location: chỉ định URL mới và khách hàng phản ứng với nó bằng cách cấp lại giao dịch cho URL mới. Có một sự khác biệt giữa các mã trạng thái 30x khác nhau được liên kết với các chuyển hướng này trong khả năng lưu trữ ẩn của chúng, nhưng về cơ bản thì chúng tương tự nhau (301 và 302) khi đáp ứng các yêu cầu GET.

Các giao dịch POST là khác nhau, vì về nguyên tắc, chúng được xác định là không bình thường (chẳng hạn như đặt bánh pizza, bỏ phiếu hoặc bất cứ điều gì) và không được lặp lại một cách tùy tiện.

Các đặc tả giao thức HTTP được thiết kế để tính đến sự khác biệt này: phương thức GET được xác định là tạm thời vốn có, trong khi phương thức POST được xác định là, ít nhất là có khả năng, không phải là idempotent; các thông số kỹ thuật yêu cầu một số biện pháp phòng ngừa được thực hiện bởi các tác nhân khách hàng (chẳng hạn như trình duyệt) để bảo vệ người dùng khỏi việc vô tình (gửi lại) một giao dịch POST mà họ không có ý định hoặc gửi POST vào ngữ cảnh mà họ không muốn .

Mặc dù tôi không phải là người thích hạn chế người dùng về mặt kỹ thuật để ngăn chặn họ gây ra tình trạng lộn xộn không mong muốn hoặc gây hại không mong muốn cho các ứng dụng của họ, tôi có thể hiểu được vấn đề và nó có ý nghĩa.


phần lớn lý do diễn ra vào thời mà các intertubes chậm và không đáng tin cậy (mà chúng vẫn còn ở nhiều nơi trên thế giới). Tôi nhớ rõ khi tôi sử dụng quay số và ngẫu nhiên sẽ bị ngắt kết nối mỗi khi có người khác nhấc điện thoại. Tốt hơn là tải lại trang và xem máy chủ đang ở trạng thái nào hơn là gửi lại mọi thứ và có nguy cơ thực hiện cùng một hành động hai lần.
zzzzBov

@Falcon, việc tăng "bộ đếm khách truy cập" có được coi là không bình thường không? Nếu vậy, hầu như không có trang web nào trong những ngày này làm
NHIỀU NHẬN

@Pacerier: Thông thường idempotent được hiểu là "idempotent một cách có ý nghĩa", ví dụ, mua cùng một mặt hàng hai lần, không theo dõi hai lần truy cập. Nếu không, bạn sẽ hoàn toàn đúng. Nhưng thực sự, thông số kỹ thuật nên yêu cầu các máy chủ phải có ý nghĩa bình thường khi cần thiết, chẳng hạn như nhúng ID vào trang để tránh trùng lặp - không yêu cầu trình duyệt hỏi người dùng câu hỏi mà họ không có cách nào trả lời với độ chính xác. Bất kể, việc ngăn chặn chuyển hướng của POST không ảnh hưởng đến tính không ổn định; nó chỉ đơn giản là một thông báo nói rằng mục tiêu của yêu cầu thực sự ở đằng kia.
Lawrence Dol

Tôi không thấy làm thế nào điều này có ý nghĩa cho lý do này. Giả sử tôi đang ở trang web của ngân hàng Chase và tôi gửi một biểu mẫu. Tôi đã đồng ý / tin tưởng họ. Vì vậy, nếu họ phải chuyển hướng dữ liệu đó sang một trang khác, tại sao tôi phải đồng ý lại. Hoặc một ví dụ khác, giả sử tôi là người tắt JavaScript theo mặc định. Một ngày nọ tôi điền vào một ứng dụng thế chấp trực tuyến và khi tôi gửi biểu mẫu thì nó có lỗi. Sẽ thật tuyệt nếu ứng dụng có thể chuyển hướng (bằng POST) đến trang tôi vừa điền để điền trước dữ liệu.
b01

@Flacon, tôi cần bằng chứng cho thấy việc hạn chế chuyển hướng bằng POST có thể ngăn chặn tình trạng lộn xộn trong bất kỳ vấn đề nào. Vì trước tiên tôi phải tin tưởng ứng dụng với dữ liệu của mình, họ có thể làm những gì họ muốn với ứng dụng đó một khi họ có dữ liệu. Và tôi không nghĩ rằng các chuyển hướng dễ bị tổn thương hơn yêu cầu với POST.
b01

3

GET (và một vài phương thức khác) được định nghĩa là 'SAFE' trong thông số http ( RFC 2616 ):

9.1.1 Phương pháp an toàn

Các nhà triển khai nên lưu ý rằng phần mềm đại diện cho người dùng trong các tương tác của họ qua Internet và nên cẩn thận để cho phép người dùng nhận thức được bất kỳ hành động nào họ có thể có ý nghĩa bất ngờ đối với bản thân hoặc người khác.

Cụ thể, quy ước đã được thiết lập rằng các phương thức GET và HEAD KHÔNG NÊN có ý nghĩa của việc thực hiện một hành động nào khác ngoài truy xuất. Những phương pháp này nên được coi là "an toàn". Điều này cho phép các tác nhân người dùng đại diện cho các phương thức khác, chẳng hạn như POST, PUT và DELETE, theo một cách đặc biệt, để người dùng nhận thức được thực tế rằng một hành động có thể không an toàn đang được yêu cầu.

Đương nhiên, không thể đảm bảo rằng máy chủ không tạo ra các tác dụng phụ do thực hiện yêu cầu GET; trong thực tế, một số tài nguyên động coi đó là một tính năng. Sự khác biệt quan trọng ở đây là người dùng không yêu cầu các tác dụng phụ, do đó không thể chịu trách nhiệm cho họ.

Điều này có nghĩa là yêu cầu GET không bao giờ có bất kỳ hậu quả nghiêm trọng nào đối với người dùng, ngoài việc nhìn thấy thứ gì đó họ có thể không muốn xem, nhưng yêu cầu POST có thể thay đổi tài nguyên quan trọng đối với họ hoặc cho người khác.

Mặc dù điều này đã thay đổi với JavaScript, theo truyền thống, có các giao diện người dùng khác nhau - người dùng có thể kích hoạt các yêu cầu GET bằng cách nhấp vào liên kết, nhưng sẽ phải điền vào một biểu mẫu để kích hoạt yêu cầu POST. Tôi nghĩ rằng các nhà thiết kế của HTTP rất muốn duy trì sự khác biệt giữa các phương pháp an toàn và không an toàn.

Tôi cũng không nghĩ cần phải chuyển hướng đến POST. Bất kỳ hành động nào cần được thực hiện có thể được thực hiện bằng cách gọi một chức năng trong mã phía máy chủ hoặc nếu nó cần xảy ra trên một máy chủ khác thì thay vì gửi một chuyển hướng có chứa URL để trình duyệt gửi tới, máy chủ có thể thực hiện một yêu cầu đến chính máy chủ đó, hoạt động như một proxy cho người dùng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.