Câu hỏi HTTP GET với phần thân yêu cầu


Tôi đang phát triển một webservice RESTful mới cho ứng dụng của chúng tôi.

Khi thực hiện GET trên các thực thể nhất định, các máy khách có thể yêu cầu nội dung của thực thể. Nếu họ muốn thêm một số tham số (ví dụ như sắp xếp danh sách), họ có thể thêm các tham số này vào chuỗi truy vấn.

Ngoài ra, tôi muốn mọi người có thể chỉ định các thông số này trong phần thân yêu cầu. HTTP / 1.1 dường như không cấm điều này một cách rõ ràng. Điều này sẽ cho phép họ chỉ định thêm thông tin, có thể giúp dễ dàng chỉ định các yêu cầu xml phức tạp hơn.

Những câu hỏi của tôi:

  • Đây có phải là một ý tưởng hay không?
  • Các máy khách HTTP có vấn đề với việc sử dụng các phần tử yêu cầu trong một yêu cầu GET không?

http://tools.ietf.org/html/rfc2616


1415
2018-06-10 20:47


gốc


Ưu điểm của việc đặt các tham số trong phần thân yêu cầu là gì? - Rich Apodaca
Ưu điểm là cho phép dễ dàng gửi các cơ quan yêu cầu XML hoặc JSON, nó không có giới hạn độ dài và dễ mã hóa hơn (UTF-8). - Evert
Nếu những gì bạn đang theo sau là một phương pháp an toàn và độc đáo cho phép các cơ quan yêu cầu, bạn có thể muốn xem TÌM KIẾM, TÌM KIẾM và BÁO CÁO. Tất nhiên không sử dụng GET và có một yêu cầu cơ thể đánh bại bộ nhớ đệm nhiều hơn hoặc ít hơn. - Julian Reschke
@fijiaaron: Đó là 3 năm sau đó, và kể từ đó tôi đã nhận được nhiều kinh nghiệm viết webservices. Đó là cơ bản tất cả những gì tôi đã làm trong vài năm qua. Tôi có thể nói một cách an toàn, nó thực sự là một ý tưởng rất xấu để thêm một cơ thể vào một yêu cầu GET. Hai câu trả lời hàng đầu đứng như một tảng đá. - Evert
@Ellesedil: Đơn giản chỉ cần đặt: Bất kỳ lợi thế nào tồn tại để sử dụng GET qua POST, tồn tại do cách HTTP được thiết kế. Những lợi thế đó không còn tồn tại, khi bạn vi phạm tiêu chuẩn theo cách này. Do đó, chỉ còn một lý do để sử dụng GET + phần thân yêu cầu thay vì POST: Thẩm mỹ. Đừng hy sinh thiết kế mạnh mẽ về tính thẩm mỹ. - Evert


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


Nhận xét của Roy Fielding về việc bao gồm một cơ thể có yêu cầu GET.

Vâng. Nói cách khác, bất kỳ thông báo yêu cầu HTTP nào cũng được phép chứa   một thông điệp, và do đó phải phân tích các thông điệp với ý nghĩ đó.   Tuy nhiên, ngữ nghĩa máy chủ cho GET bị hạn chế sao cho thân thể,   nếu có, không có ý nghĩa ngữ nghĩa đối với yêu cầu. Các yêu cầu   phân tích cú pháp tách biệt với các yêu cầu về ngữ nghĩa của phương thức.

Vì vậy, có, bạn có thể gửi một cơ thể với GET, và không, nó không bao giờ hữu ích   làm như vậy.

Đây là một phần của thiết kế lớp của HTTP / 1.1 sẽ trở thành   rõ ràng một lần nữa khi spec được phân đoạn (công việc đang tiến hành).

.... Roy

Có, bạn có thể gửi một yêu cầu cơ thể với GET nhưng nó không nên có bất kỳ ý nghĩa. Nếu bạn cho nó ý nghĩa bằng cách phân tích nó trên máy chủ và thay đổi phản hồi của bạn dựa trên nội dung của nó, sau đó bạn bỏ qua đề xuất này trong thông số HTTP / 1.1, phần 4.3:

[...] nếu phương thức yêu cầu      không bao gồm ngữ nghĩa được xác định cho một thực thể, sau đó      thân thư NÊN được bỏ qua khi xử lý yêu cầu.

Và mô tả phương thức GET trong thông số HTTP / 1.1, phần 9.3:

Phương thức GET có nghĩa là truy xuất thông tin bất kỳ ([...]) được xác định bởi Yêu cầu-URI.

trong đó nói rằng phần thân yêu cầu không phải là một phần của việc xác định tài nguyên trong một yêu cầu GET, chỉ có URI yêu cầu.


1208
2018-06-11 20:27



Máy chủ nào sẽ bỏ qua nó? - fijiaaron
Caching / proxying là hai thứ bạn có nhiều khả năng phá vỡ nhất. "Ngữ nghĩa" chỉ là một cách khác để nói "cách mà những người tạo ra các thành phần khác sẽ mong đợi các thành phần khác hoạt động". Nếu bạn vi phạm ngữ nghĩa, bạn có nhiều khả năng thấy mọi thứ xảy ra ở những nơi mọi người viết những thứ mong đợi bạn tôn vinh những ngữ nghĩa đó. - Stuart P. Bentley
Elasticsearch là một sản phẩm khá lớn, sử dụng các thân yêu cầu HTTP trong GET. Theo hướng dẫn của họ cho dù một yêu cầu HTTP nên hỗ trợ có một cơ thể hay không là không xác định. Cá nhân tôi không thoải mái với việc điền vào một yêu cầu GET, nhưng dường như họ có một quan điểm khác và họ phải biết họ đang làm gì. elastic.co/guide/en/elasticsearch/guide/current/… - GordonM
@iwein cung cấp cho các cơ quan yêu cầu GET có nghĩa là trên thực tế không phải vi phạm thông số. HTTP / 1.1 xác định rằng các máy chủ NÊN nên bỏ qua cơ thể, nhưng RFC 2119 xác định rằng người triển khai được phép bỏ qua mệnh đề "NÊN" nếu họ có lý do chính đáng để làm như vậy. Thay vào đó, một khách hàng làm vi phạm spec nếu nó giả định rằng việc thay đổi thân GET sẽ không phải thay đổi phản hồi. - Emil Lundberg
RFC2616 được tham chiếu là "thông số HTTP / 1.1" hiện đã lỗi thời. Trong năm 2014 nó đã được thay thế bởi RFC 7230-7237. Trích dẫn "thư-cơ thể NÊN được bỏ qua khi xử lý yêu cầu"đã từng đã xóa. Nó bây giờ chỉ là "Yêu cầu khung tin nhắn độc lập với ngữ nghĩa của phương thức, ngay cả khi phương thức không xác định bất kỳ việc sử dụng nào cho nội dung thư"Trích dẫn thứ 2"Phương thức GET có nghĩa là truy xuất bất kỳ thông tin nào ... được xác định bởi Yêu cầu-URI"là đã xóa. Vì vậy, tôi đề nghị chỉnh sửa câu trả lời @Jarl - Artem Nakonechny


Trong khi bạn có thể làm điều đó, trong khi nó không bị loại trừ một cách rõ ràng bởi đặc điểm kỹ thuật HTTP, tôi sẽ đề nghị tránh nó đơn giản chỉ vì mọi người không mong đợi mọi thứ hoạt động theo cách đó. Có nhiều giai đoạn trong một chuỗi yêu cầu HTTP và trong khi chúng "chủ yếu" phù hợp với thông số HTTP, điều duy nhất bạn được đảm bảo là chúng sẽ hoạt động như truyền thống được sử dụng bởi các trình duyệt web. (Tôi đang nghĩ về những thứ như proxy trong suốt, máy gia tốc, bộ công cụ A / V, v.v.)

Đây là tinh thần đằng sau Nguyên tắc mạnh mẽ gần như "được tự do trong những gì bạn chấp nhận, và bảo thủ trong những gì bạn gửi", bạn không muốn đẩy ranh giới của một đặc điểm kỹ thuật mà không có lý do chính đáng.

Tuy nhiên, nếu bạn có lý do chính đáng, hãy tìm nó.


234
2018-06-10 20:53



Nguyên tắc Robustness là thiếu sót. Nếu bạn được tự do trong những gì bạn chấp nhận, bạn sẽ nhận được crap, nếu bạn có bất kỳ thành công trong điều khoản của việc thông qua, chỉ vì bạn chấp nhận crap. Điều đó sẽ khiến bạn khó phát triển giao diện của mình hơn. Chỉ cần nhìn vào HTML. Đó là nguyên tắc lật đổ trong hành động. - Eugene Beresovsky
Tôi nghĩ rằng sự thành công và bề rộng của việc áp dụng (và lạm dụng) của các giao thức nói lên giá trị của nguyên tắc mạnh mẽ. - caskey
Bạn đã từng thử phân tích cú pháp HTML thực chưa? Bạn không thể tự thực hiện nó, đó là lý do tại sao hầu hết mọi người - bao gồm cả những người chơi thực sự lớn như Google (Chrome) và Apple (Safari), không làm điều đó nhưng dựa vào triển khai hiện có (cuối cùng họ đều dựa vào KHTML của KDE). Tái sử dụng đó là tất nhiên tốt đẹp, nhưng bạn đã thử hiển thị html trong một ứng dụng .net? Đó là một cơn ác mộng, vì bạn phải nhúng một thành phần không được quản lý - IE (hoặc tương tự), với các vấn đề và sự cố, hoặc bạn sử dụng thành phần có sẵn (trên codeplex) mà thậm chí không cho phép bạn chọn văn bản. - Eugene Beresovsky
Thông số HTTP không chỉ cho phép dữ liệu nội dung có yêu cầu GET, nhưng đây cũng là thực tiễn phổ biến: API tìm kiếm của công cụ tìm kiếm ElasticSearch phổ biến đề xuất các yêu cầu GET với truy vấn được đính kèm trong một cơ thể JSON. Là một sự nhượng bộ cho việc triển khai HTTP client chưa đầy đủ, nó cũng cho phép các yêu cầu POST ở đây. - Christian Pietsch
@ user437899 .NET Framework sẽ ném một ngoại lệ nếu bạn cố gắng gửi một cơ thể có yêu cầu GET. - Sam Harwell


Bạn có thể sẽ gặp phải vấn đề nếu bạn cố gắng tận dụng bộ nhớ đệm. Proxy sẽ không tìm trong cơ thể GET để xem các tham số có tác động đến phản hồi hay không.


116
2018-06-10 21:10



Sử dụng các trường tiêu đề ETAG / Last-Modified giúp đỡ theo cách này: khi một "GET có điều kiện" được sử dụng, proxy / cache có thể tác động lên thông tin này. - jldupont
@jldupont Caches sử dụng sự hiện diện của trình duyệt tính hợp lệ để biết liệu một phản hồi cũ có thể được xác nhận lại hay không, tuy nhiên, chúng không được sử dụng như một phần của khóa chính hoặc bộ nhớ đệm thứ cấp. - Darrel Miller


Cũng không nghỉ ngơi cũng không Bảng điều khiển REST hỗ trợ này nhưng curl nào.

Các Đặc tả HTTP nói trong phần 4.3

Một thông điệp-cơ thể PHẢI KHÔNG được bao gồm trong một yêu cầu nếu đặc tả của phương thức yêu cầu (phần 5.1.1) không cho phép gửi một thực thể-cơ thể trong các yêu cầu.

Mục 5.1.1 chuyển hướng chúng tôi đến phần 9.x cho các phương pháp khác nhau. Không ai trong số họ rõ ràng cấm sự bao gồm của một cơ thể tin nhắn. Tuy nhiên...

Phần 5.2 nói

Tài nguyên chính xác được xác định bởi yêu cầu Internet được xác định bằng cách kiểm tra cả trường Yêu cầu-URI và trường Tiêu đề máy chủ.

Phần 9.3 nói

Phương thức GET có nghĩa là truy xuất bất kỳ thông tin nào (dưới dạng một thực thể) được xác định bởi Yêu cầu-URI.

Cùng nhau gợi ý rằng khi xử lý yêu cầu GET, máy chủ không cần thiết để kiểm tra bất kỳ điều gì khác mà trường Yêu cầu-URI và Máy chủ lưu trữ.

Tóm lại, đặc tả HTTP không ngăn cản bạn gửi một thông điệp với GET nhưng có đủ sự mơ hồ rằng nó sẽ không làm tôi ngạc nhiên nếu nó không được hỗ trợ bởi tất cả các máy chủ.


60
2018-03-27 10:41



Paw cũng có tùy chọn để hỗ trợ các yêu cầu GET với các phần tử nhưng nó phải được kích hoạt trong các thiết lập. - s.Daniel
"Phương thức GET có nghĩa là truy xuất bất kỳ thông tin nào (dưới dạng một thực thể) được xác định bởi Yêu cầu-URI." Sau đó, về mặt kỹ thuật là sai trái / sai để có điểm cuối GET nhận được tất cả các thực thể? Ví dụ. GET /contacts/100/addresses trả về một tập hợp các địa chỉ cho người có id=100. - Josh M.
Thư viện Java yên tâm để kiểm tra các API REST không hỗ trợ yêu cầu GET với một phần thân. Apache HttpClient cũng không hỗ trợ nó. - Paulo Merson


Elasticsearch chấp nhận các yêu cầu GET với nội dung. Nó thậm chí có vẻ rằng đây là cách ưa thích: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/common-options.html#_request_body_in_query_string

Một số thư viện máy khách (như trình điều khiển Ruby) có thể đăng nhập lệnh cry để stdout trong chế độ phát triển và nó đang sử dụng cú pháp này rộng rãi.


37
2017-12-03 11:15



Đã tự hỏi tại sao Elasticsearch lại cho phép điều này. Điều đó có nghĩa là truy vấn này để đếm tất cả các tài liệu có tải trọng tới yêu cầu GET curl -XGET 'http://localhost:9200/_count?pretty' -d ' { "query": { "match_all": {} } }'  tương đương với việc bao gồm tải trọng source param: curl -XGET 'http://localhost:9200/_count?pretty&source=%7B%22query%22%3A%7B%22match_all%22%3A%7B%7D%7D%7D' - arun
Truy vấn phức tạp có thể đạt đến độ dài tối đa của tiêu đề http. - s.Daniel
Nó đã đọc tài liệu elasticsearch đưa tôi đến câu hỏi này vì tôi nghĩ rằng nó được coi là thực hành xấu để bao gồm một cơ thể - PatrickWalker
Nó thậm chí không cần phải là một truy vấn phức tạp. Ngay cả một cuộn đơn giản cũng có thể trả về một scroll_id rất dài (trong một cụm có nhiều phân đoạn), điều này sẽ dẫn đến việc tràn ngập chiều dài url tối đa nếu được thêm vào đó. - Brent Hronik
Elasticsearch hỗ trợ cùng một yêu cầu sử dụng POST. Họ chỉ chọn để cho phép một cơ thể trong một GET bởi vì họ cảm thấy một GET là ngữ nghĩa chính xác hơn so với một POST khi nói đến truy vấn dữ liệu. Vui của nó mà Elasticsearch được đề cập rất nhiều trong chủ đề này. Tôi sẽ không sử dụng một ví dụ (mặc dù từ một sản phẩm phổ biến) như là một lý do để thực hiện theo các thực hành. - DSO


Những gì bạn đang cố gắng đạt được đã được thực hiện trong một thời gian dài với một phương thức phổ biến hơn nhiều, và một phương thức không phụ thuộc vào việc sử dụng một tải trọng với GET.

Bạn có thể chỉ cần xây dựng trung tâm tìm kiếm cụ thể của mình hoặc nếu bạn muốn RESTful hơn, hãy sử dụng một cái gì đó như OpenSearch và POST yêu cầu tới URI mà máy chủ đã hướng dẫn, nói / tìm kiếm. Sau đó, máy chủ có thể tạo kết quả tìm kiếm hoặc tạo URI cuối cùng và chuyển hướng bằng cách sử dụng 303.

Điều này có lợi thế là tuân theo phương pháp PRG truyền thống, giúp các bộ đệm trung gian lưu vào bộ nhớ cache kết quả, v.v.

Điều đó nói rằng, URI được mã hóa cho bất cứ thứ gì không phải là ASCII, và do đó, ứng dụng / x-www-form-urlencoded và multipart / form-data. Tôi khuyên bạn nên sử dụng điều này thay vì tạo ra một định dạng json tùy chỉnh khác nếu ý định của bạn là hỗ trợ các kịch bản ReSTful.


25
2018-06-10 22:47



Bạn có thể chỉ cần xây dựng trung tâm tìm kiếm cụ thể của mình Bạn có thể xây dựng? - Piotr Dobrogost
Bằng cách đó, tôi đã nói rằng bạn có thể tạo một loại phương tiện được gọi là application / vnd.myCompany.search + json có chứa loại mẫu tìm kiếm bạn muốn khách hàng phát hành và sau đó khách hàng có thể gửi nó dưới dạng POST. Như tôi đã đánh dấu, đã có một loại phương tiện truyền thông cho điều đó và nó được gọi là OpenSearch, nên sử dụng lại loại phương tiện hiện có trên tuyến đường tùy chỉnh khi bạn có thể triển khai kịch bản của mình với các tiêu chuẩn hiện có. - SerialSeb
Đó là thông minh, nhưng quá phức tạp và không hiệu quả. Bây giờ bạn phải gửi một POST với tiêu chí tìm kiếm của bạn, nhận được một URI như một phản hồi từ POST của bạn, sau đó gửi một GET với URI tiêu chí tìm kiếm đến máy chủ cho nó để GET các tiêu chí và gửi kết quả lại cho bạn. (Ngoại trừ việc bao gồm URI trong URI về mặt kỹ thuật là không thể vì bạn không thể gửi thứ gì đó có thể lên tới 255 ký tự trong một cái gì đó có thể không quá 255 ký tự - vì vậy bạn phải sử dụng một phần định danh và máy chủ của bạn cần biết cách giải quyết URI cho tiêu chí tìm kiếm đã đăng của bạn.) - fijiaaron


Máy chủ nào sẽ bỏ qua nó? - fijiaaron 30 tháng 8 lúc 12 giờ 27 phút

Google ví dụ là làm tồi tệ hơn bỏ qua nó, nó sẽ xem xét nó một lỗi!

Hãy thử nó với một netcat đơn giản:

$ netcat www.google.com 80
GET / HTTP/1.1
Host: www.google.com
Content-length: 6

1234

(nội dung 1234 được theo sau bởi CR-LF, vì vậy tổng cộng là 6 byte)

và bạn sẽ nhận được:

HTTP/1.1 400 Bad Request
Server: GFE/2.0
(....)
Error 400 (Bad Request)
400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know.

Bạn cũng nhận được 400 yêu cầu không hợp lệ từ Bing, Apple, v.v ... được phục vụ bởi AkamaiGhost.

Vì vậy, tôi sẽ không khuyên bạn sử dụng các yêu cầu GET với một thực thể cơ thể.


23
2018-06-29 21:26



Ví dụ này là vô nghĩa vì thường khi mọi người sẽ thêm cơ thể vào GET yêu cầu, đó là vì máy chủ tùy chỉnh của riêng họ có thể xử lý nó. Câu hỏi như vậy là liệu các "bộ phận chuyển động" khác (trình duyệt, bộ nhớ cache, vv) sẽ hoạt động đúng. - Pacerier