Câu hỏi Các tham số được gửi trong yêu cầu HTTP POST như thế nào?


Trong HTTP ĐƯỢC yêu cầu, thông số được gửi dưới dạng chuỗi truy vấn:

http://example.com/page? parameter = value & also = khác

Trong HTTP BÀI ĐĂNG yêu cầu, các tham số không được gửi cùng với URI.

Giá trị ở đâu? Trong tiêu đề yêu cầu? Trong cơ thể yêu cầu? Nó trông như thế nào?


1164
2018-01-27 19:19


gốc




Các câu trả lời:


Các giá trị được gửi trong phần thân yêu cầu, theo định dạng mà kiểu nội dung chỉ định.

Thông thường loại nội dung là application/x-www-form-urlencoded, do đó, thân yêu cầu sử dụng cùng một định dạng như chuỗi truy vấn:

parameter=value&also=another

Khi bạn sử dụng tệp tải lên trong biểu mẫu, bạn sử dụng multipart/form-data thay vào đó, mã hóa có định dạng khác. Nó phức tạp hơn, nhưng bạn thường không cần phải quan tâm nó trông như thế nào, vì vậy tôi sẽ không hiển thị một ví dụ, nhưng nó có thể là tốt để biết rằng nó tồn tại.


963
2018-01-27 19:32



Tôi đã quên mất các tệp tải lên khác nhau (+ 1 / được chấp nhận). Câu trả lời của bạn là đủ, trong khi nó sẽ được thêm tốt đẹp nếu nó có thêm thông tin về multipart/form-data. Đối với những người quan tâm, đây là một câu hỏi về nó. - Camilo Martin
CHÚ THÍCH: cơ thể được tách ra khỏi tiêu đề bởi chỉ một dòng trống. - Gab是好人
Bạn đã giải thích những gì chúng ta đặt trong HTTPBody, nhưng chúng ta đặt / ghi vào HTTPHeader là gì? Mục đích của nó là gì? - Honey
@Honey: Tiêu đề HTTP cho bài đăng trông giống như một bài đăng, nhưng với động từ POST thay vì GET và giá trị loại nội dung (và giá trị độ dài nội dung tùy chọn) khi yêu cầu có nội dung (nội dung). Mỗi loại yêu cầu đều có tiêu đề, một số loại cũng có phần thân. - Guffa
@KennethWorden Không, không phải các phương thức sẽ gửi JSON đúng cách. tuy nhiên, bạn có thể tải lên tệp json dưới dạng được mã hóa bằng multipart/form-data hoặc nếu bạn chịu trách nhiệm xây dựng yêu cầu, hãy thay đổi loại nội dung thành application/json và dán văn bản json trong cơ thể http trực tiếp - Cholthi Paul Ttiopic


Nội dung được đặt sau tiêu đề HTTP. Định dạng của một POST HTTP là có các tiêu đề HTTP, theo sau là một dòng trống, theo sau là phần thân yêu cầu. Các biến POST được lưu trữ dưới dạng cặp khóa-giá trị trong phần thân.

Bạn có thể thấy điều này trong nội dung thô của Bài đăng HTTP, được hiển thị bên dưới:

POST /path/script.cgi HTTP/1.0
From: frog@jmarshall.com
User-Agent: HTTPTool/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 32

home=Cosby&favorite+flavor=flies

Bạn có thể thấy điều này bằng cách sử dụng một công cụ như Fiddler, mà bạn có thể sử dụng để xem yêu cầu HTTP thô và tải trọng phản hồi được gửi qua dây.


350
2018-01-27 19:21



Chỉ khi loại nội dung là application/x-www-form-urlencoded, không phải lúc nào cũng vậy. - Guffa
@ Camilo Martin .... [+1] cho câu hỏi tuyệt vời & @ Joe Alfano .... [+1] cho câu trả lời tuyệt vời ....... tôi đã có một ý tưởng rõ ràng bây giờ về yêu cầu POST .... nhưng nếu một hình ảnh đi kèm với cặp khóa, giá trị của thông tin dữ liệu ..... Cấu trúc của POST trông như thế nào? - Devrath
@ Joe, Bây giờ tại sao bạn sẽ có một From tiêu đề ở đó? - Pacerier
@ Joe, tôi thích sự bao gồm ngẫu nhiên của From tiêu đề. IMO ở trên đó với mã trạng thái HTTP 404. - Tom Howard


Câu trả lời ngắn: trong yêu cầu POST, các giá trị được gửi trong phần "nội dung" của yêu cầu. Với các biểu mẫu web, chúng có nhiều khả năng được gửi cùng với loại phương tiện application/x-www-form-urlencoded hoặc là multipart/form-data. Ngôn ngữ lập trình hoặc khung công tác đã được thiết kế để xử lý yêu cầu web thường thực hiện "Điều đúng" với các yêu cầu như vậy và cung cấp cho bạn khả năng truy cập dễ dàng vào các giá trị được giải mã dễ dàng (như $_REQUEST hoặc là $_POST bằng PHP, hoặc cgi.FieldStorage(), flask.request.form bằng Python).


Bây giờ hãy phân tích một chút, điều này có thể giúp hiểu sự khác biệt;)

Sự khác biệt giữa GET và POST yêu cầu phần lớn là ngữ nghĩa. Chúng cũng được "sử dụng" khác nhau, điều này giải thích sự khác biệt về cách thức các giá trị được truyền đi.

ĐƯỢC (phần RFC có liên quan)

Khi thực hiện một GET yêu cầu, bạn yêu cầu máy chủ cho một hoặc một tập hợp các thực thể. Để cho phép khách hàng lọc kết quả, nó có thể sử dụng "chuỗi truy vấn" được gọi là URL. Chuỗi truy vấn là phần sau ?. Đây là một phần của Cú pháp URI.

Vì vậy, từ quan điểm của mã ứng dụng của bạn (phần mà nhận yêu cầu), bạn sẽ cần phải kiểm tra phần truy vấn URI để truy cập vào các giá trị này.

Lưu ý rằng các khóa và giá trị là một phần của URI. Trình duyệt có thể áp đặt một giới hạn về độ dài URI. Tiêu chuẩn HTTP nói rằng không có giới hạn. Nhưng tại thời điểm viết bài này, hầu hết các trình duyệt làm giới hạn các URI (Tôi không có giá trị cụ thể). GET yêu cầu nên không bao giờ được sử dụng để gửi thông tin mới đến máy chủ. Đặc biệt không phải tài liệu lớn hơn. Đó là nơi bạn nên sử dụng POST hoặc là PUT.

BÀI ĐĂNG (phần RFC có liên quan)

Khi thực hiện một POST yêu cầu, khách hàng thực sự đang gửi một tài liệu đến máy chủ từ xa. Vì vậy, một truy vấn chuỗi không (ngữ nghĩa) có ý nghĩa. Đó là lý do tại sao bạn không có quyền truy cập vào chúng trong mã ứng dụng của bạn.

POST phức tạp hơn một chút (và đường Linh hoạt hơn):

Khi nhận được yêu cầu POST, bạn luôn phải mong đợi "tải trọng" hoặc theo thuật ngữ HTTP: a nội dung tin nhắn. Cơ thể thông điệp trong chính nó là khá vô dụng, vì không có Tiêu chuẩn (theo như tôi có thể nói. Có thể ứng dụng / octet-stream?) định dạng. Định dạng cơ thể được xác định bởi Content-Type tiêu đề. Khi sử dụng HTML FORM yếu tố với method="POST", điều này thường application/x-www-form-urlencoded. Một loại rất phổ biến khác là multipart / form-data nếu bạn sử dụng tải lên tệp. Nhưng có thể là bất cứ điều gì, từ text/plain, kết thúc application/json hoặc thậm chí là một tùy chỉnh application/octet-stream.

Trong mọi trường hợp, nếu POST yêu cầu được thực hiện với một Content-Type mà ứng dụng không thể xử lý, nó sẽ trả về 415 mã trạng thái.

Hầu hết các ngôn ngữ lập trình (và / hoặc khung công tác trên web) cung cấp cách để de / mã hóa nội dung thư từ / thành các loại phổ biến nhất (như application/x-www-form-urlencoded, multipart/form-data hoặc là application/json). Rất dễ. Các loại tùy chỉnh yêu cầu khả năng hoạt động nhiều hơn một chút.

Sử dụng tài liệu mã hóa biểu mẫu HTML chuẩn làm ví dụ, ứng dụng sẽ thực hiện các bước sau:

  1. Đọc Content-Type cánh đồng
  2. Nếu giá trị không phải là một trong các loại phương tiện được hỗ trợ, sau đó trả về phản hồi với 415 mã trạng thái
  3. nếu không, hãy giải mã các giá trị từ nội dung thư.

Một lần nữa, các ngôn ngữ như PHP hoặc khung công tác web cho các ngôn ngữ phổ biến khác có thể sẽ xử lý điều này cho bạn. Ngoại lệ cho điều này là 415 lỗi. Không có khuôn khổ nào có thể dự đoán loại nội dung nào mà ứng dụng của bạn chọn để hỗ trợ và / hoặc không hỗ trợ. Đây là tùy thuộc vào bạn.

ĐẶT (phần RFC có liên quan)

A PUT yêu cầu được xử lý khá nhiều theo cách chính xác giống như POST yêu cầu. Sự khác biệt lớn là một POST yêu cầu được cho là để cho máy chủ quyết định cách (và nếu có) tạo một tài nguyên mới. Về mặt lịch sử (từ nay đã lỗi thời RFC2616 nó đã tạo ra một tài nguyên mới như là một "cấp dưới" (con) của URI, nơi yêu cầu được gửi đến).

A PUT yêu cầu ngược lại là nghĩa vụ "gửi tiền" một tài nguyên chính xác tại URI đó, và với chính xác nội dung đó. Không nhiều không ít. Ý tưởng là khách hàng có trách nhiệm làm thủ công hoàn thành trước khi "PUTting" nó. Máy chủ nên chấp nhận nó as-is trên URL đã cho.

Kết quả là, POST yêu cầu thường không được sử dụng để thay thế tài nguyên hiện có. A PUT yêu cầu có thể tạo cả hai  thay thế.

Side-Note

Cũng có "thông số đường dẫn"có thể được sử dụng để gửi dữ liệu bổ sung cho điều khiển từ xa, nhưng chúng quá phổ biến, rằng tôi sẽ không đi vào quá chi tiết ở đây. Nhưng, để tham khảo, đây là một đoạn trích từ RFC:

Ngoài phân đoạn chấm trong đường dẫn phân cấp, phân khúc đường dẫn được xem xét   mờ đục theo cú pháp chung. Các ứng dụng sản xuất URI thường sử dụng   các ký tự dành riêng được cho phép trong một phân đoạn để phân định sơ đồ cụ thể hoặc   các thành phần phụ cụ thể về xử lý riêng. Ví dụ: dấu chấm phẩy (";")   và bằng ("=") ký tự dành riêng thường được sử dụng để phân định các tham số và   các giá trị tham số có thể áp dụng cho phân đoạn đó. Dấu phẩy (",") được đặt trước   nhân vật thường được sử dụng cho các mục đích tương tự. Ví dụ: một nhà sản xuất URI   có thể sử dụng phân đoạn như "name; v = 1.1" để chỉ báo tham chiếu đến phiên bản   1,1 của "tên", trong khi người khác có thể sử dụng phân đoạn như "tên, 1.1" để   cho biết điều tương tự. Các loại tham số có thể được xác định theo lược đồ cụ thể   ngữ nghĩa, nhưng trong hầu hết các trường hợp, cú pháp của tham số là đặc trưng cho   triển khai thuật toán dereferencing của URI.


287
2017-11-03 15:54



Tôi có thể đã đi trên một tiếp tuyến hơi thực sự. Tôi đã thêm một "tl; dr" vào đầu câu trả lời nên làm cho nó rõ ràng hơn. - exhuma
Tôi cũng vừa chỉnh sửa nó để tham khảo RFC7231 thay vì RFC2616 (đã lỗi thời trong một thời gian). Sự khác biệt chính cho câu trả lời này ngoài các liên kết được cập nhật, nằm trong phần "PUT". - exhuma
Tôi nghĩ PUT đã được xử lý khác với POST vì nó được cho là không đáng tin cậy? stackoverflow.com/questions/611906/… - rogerdpack
@rogerdpack Bạn không sai. Nếu bạn đọc đoạn thứ hai trong PUT bạn sẽ thấy nó Là idempotent. POST ngược lại có thể - theo định nghĩa - không được. POST sẽ luôn tạo tài nguyên mới. PUTsẽ, nếu một tài nguyên giống hệt nhau tồn tại thay thế nó. Vì vậy, nếu bạn gọi POST 10 lần, bạn sẽ tạo 10 tài nguyên. Nếu bạn gọi PUT 10 lần, nó sẽ (có thể) chỉ tạo ra một. Câu trả lời đó có đáp ứng được câu hỏi của bạn không? - exhuma


Bạn không thể nhập trực tiếp trên thanh URL của trình duyệt.

Bạn có thể xem cách dữ liệu POST được gửi trên Internet với Tiêu đề HTTP trực tiếp ví dụ. Kết quả sẽ giống như vậy

http://127.0.0.1/pass.php
POST /pass.php HTTP/1.1

Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://127.0.0.1/pass.php
Cookie: passx=87e8af376bc9d9bfec2c7c0193e6af70; PHPSESSID=l9hk7mfh0ppqecg8gialak6gt5
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
username=zurfyx&pass=password

Nó nói ở đâu

Content-Length: 30
    username=zurfyx&pass=password

sẽ là giá trị bài đăng.


49
2018-01-27 19:29



Ty để ghi nhớ trường Host. - Deanie
Làm rõ: là Content-Length đáng lẽ là 29 đây? Đó là độ dài thực tế của chuỗi username=zurfyx&pass=password. - Hippo
@ Hippo là một nhân vật mới có nghĩa là ở đó? - vikingsteve
@ vikingsteve Tôi hiểu ý của bạn là gì. Vì vậy, tôi đoán Nội dung luôn luôn có một dòng mới ở cuối của nó, sau đó. - Hippo


Loại phương tiện mặc định trong yêu cầu POST là application/x-www-form-urlencoded. Đây là định dạng để mã hóa các cặp khóa-giá trị. Các phím có thể trùng lặp. Mỗi cặp khóa-giá trị được phân cách bằng một & và mỗi khóa được tách biệt với giá trị của nó bằng một = tính cách.

Ví dụ:

Name: John Smith
Grade: 19

Được mã hóa dưới dạng:

Name=John+Smith&Grade=19

Điều này được đặt trong phần thân yêu cầu sau tiêu đề HTTP.


18
2018-06-16 05:33



Bạn đã giải thích những gì chúng ta đặt trong HTTPBody, nhưng chúng ta đặt / ghi vào HTTPHeader là gì? - Honey
Bạn đã đề cập tha chìa khóa có thể được lặp lại, sau đó kết quả của một bản sao như vậy là gì? Người cuối cùng sẽ tự động ghi đè (các) giá trị trước đó? Cảm ơn. - Jinghui Niu


Các giá trị biểu mẫu trong các POST HTTP được gửi trong phần thân yêu cầu, có cùng định dạng với chuỗi truy vấn.

Để biết thêm thông tin, hãy xem spec.


13
2018-01-27 19:20



"Cùng một định dạng" là một chút mơ hồ. Họ bắt đầu với một ? ví dụ? - Camilo Martin
@PeterWooster Có, nhưng không cung cấp một ví dụ. Về vấn đề đó, giống như một câu trả lời cho biết "nhìn xem, có một câu trả lời cho câu hỏi của bạn trong blog của ứng dụng (liên kết)". - Camilo Martin
Ví dụ này không cần thiết, bạn có thể tự tạo ra nó. Có rất ít khi cần phải cho trẻ ăn nhiều hơn một vài điểm. - Peter Wooster
@PeterWooster Nó không phải là cần thiết, nhưng nó rất tốt khi bạn quên một cái gì đó, google nó, đi đến liên kết đầu tiên đó là SO, và có một ví dụ rõ ràng, ngắn gọn cho bạn biết những gì bạn cần thay vì gửi cho bạn nhai trên thông số kỹ thuật chi tiết quá mức, ngay cả khi toàn diện, có thể không phù hợp cho người làm mới. Hãy suy nghĩ về nó: hầu hết các QA trên trang web này có thể đun sôi xuống để "đi đọc spec / manual / API / etc (liên kết)"Nó có hữu ích không? Không nhiều hơn Google. - Camilo Martin
Chỉ khi loại nội dung là application/x-www-form-urlencoded, không phải lúc nào cũng vậy. - Guffa


Một số dịch vụ web yêu cầu bạn đặt yêu cầu dữ liệu và metadata riêng biệt. Ví dụ, một chức năng từ xa có thể mong đợi rằng chuỗi siêu dữ liệu đã ký được bao gồm trong một URI, trong khi dữ liệu được đăng trong một HTTP-body.

Yêu cầu POST có thể trông giống như sau:

POST /?AuthId=YOURKEY&Action=WebServiceAction&Signature=rcLXfkPldrYm04 HTTP/1.1
Content-Type: text/tab-separated-values; charset=iso-8859-1
Content-Length: []
Host: webservices.domain.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: identity
User-Agent: Mozilla/3.0 (compatible; Indy Library)

name    id
John    G12N
Sarah   J87M
Bob     N33Y

Cách tiếp cận này kết hợp logic QueryString và Body-Post bằng cách sử dụng một Content-Type đó là "hướng dẫn phân tích cú pháp" cho máy chủ web.

Xin lưu ý: HTTP / 1.1 là bọc với #32 (không gian) bên trái và với #10 (Nguồn cấp dữ liệu dòng) ở bên phải.


13
2017-07-31 14:01



Sự khác biệt giữa /user/john và /?user=john chỉ đơn thuần là ngữ nghĩa ngữ nghĩa (HTTP thực sự không cung cấp điều trị đặc biệt cho các chuỗi truy vấn), vì vậy tôi thực hiện điều này như mong đợi một cách hợp lý. Nhưng bạn có ý gì bằng cách "bọc bởi không gian bên trái"? Không có dấu cách trước phương thức HTTP. Bạn có nghĩa là dòng trống cho nội dung bài đăng? - Camilo Martin
Có một không gian (ASCII # 32) giữa ...Ym04 và HTTP/1.1 trong đoạn mã trên. Vì vậy, một QueryString chỉ đơn giản là nằm giữa động từ và phiên bản giao thức. - Interface Unknown
Ghi chú của bạn làm cho nó nghe có vẻ như đó là điều bất ngờ và phiên bản cụ thể. Khá thẳng thắn có vẻ như rõ ràng có một không gian ở đó. Và dòng nguồn cấp dữ liệu cũng áp dụng cho các dòng khác, giống như tất cả mọi thứ unix. - Camilo Martin
Tôi chỉ nhấn mạnh những gì tôi không thể đánh dấu trong mã. Nó có vẻ hiển nhiên nhưng đôi khi nó không phải là. - Interface Unknown
Đúng là chúng tôi có thể chuyển các tham số truy vấn như một phần của URL bằng cách tách URI và các tham số bằng ? như chúng ta làm với GET yêu cầu. - asgs


Trước hết, hãy phân biệt giữa GET và POST 

Được: Đây là mặc định HTTP yêu cầu được thực hiện cho máy chủ và được sử dụng để truy xuất dữ liệu từ máy chủ và chuỗi truy vấn xuất hiện sau ? trong một URI được sử dụng để truy xuất tài nguyên duy nhất.

đây là định dạng

GET /someweb.asp?data=value HTTP/1.0

đây data=value là giá trị chuỗi truy vấn được chuyển.

BÀI ĐĂNG: Nó được sử dụng để gửi dữ liệu đến máy chủ một cách an toàn vì vậy bất cứ điều gì cần thiết, đây là định dạng của một POST yêu cầu

POST /somweb.aspHTTP/1.0
Host: localhost
Content-Type: application/x-www-form-urlencoded //you can put any format here
Content-Length: 11 //it depends
Name= somename

Tại sao POST trên GET?

Trong GET giá trị được gửi đến các máy chủ thường được nối vào URL cơ sở trong chuỗi truy vấn, Điều này làm cho dữ liệu của bạn có thể bị tấn công (đây là một vấn đề tồn tại trong ngày cho Facebook nơi thông tin đăng nhập của bạn bị lộ). POSTđược sử dụng để gửi dữ liệu đến máy chủ được sử dụng Request Body để gửi dữ liệu của bạn đến máy chủ an toàn hơn vì nó ẩn dữ liệu của bạn cộng với dữ liệu của bạn từ các trường tính toán độ dài của chúng và thêm chúng vào header cho content-length và không có dữ liệu quan trọng nào được nối trực tiếp vào URL

bây giờ yêu cầu của bạn được thực hiện an toàn, mọi giá trị được gửi tới máy chủ đều có thể được gửi trong Request Body như tên ngụ ý nó sẽ chứa người dùng dữ liệu muốn gửi (và nó được gửi trong URL Encoded định dạng) và Request Headers sẽ giữ Yêu cầu an toàn bằng cách so sánh các giá trị trong Request Body với Request Headers

Bạn có thể sử dụng phần mạng của Công cụ nhà phát triển Google để xem thông tin cơ bản về cách yêu cầu được thực hiện cho máy chủ.

và bạn luôn có thể thêm nhiều giá trị hơn vào Request Headers như Cache-Control , Origin , Accept.


0
2017-07-19 07:04