2665

アプリケーション用の新しいRESTfulWebサービスを開発しています。

特定のエンティティでGETを実行する場合、クライアントはエンティティのコンテンツを要求できます。一部のパラメータを追加する場合(たとえば、リストの並べ替え)、クエリ文字列にこれらのパラメータを追加できます。

または、リクエストの本文でこれらのパラメータを指定できるようにする必要があります。 HTTP / 1.1は、これを明示的に禁止していないようです。これにより、より多くの情報を指定できるようになり、複雑なXML要求を指定しやすくなる可能性があります。

私の質問:

  • これは完全に良い考えですか?
  • HTTPクライアントは、GETリクエスト内でのリクエストボディの使用に問題がありますか?

https://www.rfc-editor.org/rfc/rfc2616

4

21 に答える 21

2162

GET リクエストに body を含めることに関する Roy Fielding のコメント

はい。つまり、HTTP 要求メッセージにはメッセージ本文を含めることが許可されているため、そのことを念頭に置いてメッセージを解析する必要があります。ただし、GET のサーバー セマンティクスは制限されているため、ボディが存在する場合でも、リクエストに対してセマンティックな意味はありません。解析に関する要件は、メソッドのセマンティクスに関する要件とは別のものです。

したがって、はい、GET を使用して本文を送信できますが、いいえ、そうすることは決して役に立ちません。

これは HTTP/1.1 の階層化された設計の一部であり、仕様が分割されると再び明確になります (進行中の作業)。

....ロイ

はい、GET を使用してリクエスト本文を送信できますが、意味はありません。サーバー上で解析し、その内容に基づいて応答を変更することで意味を与える場合、HTTP/1.1 仕様のセクション 4.3 のこの推奨事項を無視していることになります。

...リクエストメソッドにエンティティボディの定義されたセマンティクスが含まれていない場合、リクエストを処理するときにメッセージボディを無視する必要があります。

また、 HTTP/1.1 仕様のセクション 9.3の GET メソッドの説明:

GET メソッドは、Request-URI によって識別される情報 ([...]) を取得することを意味します。

request-body は GET リクエストのリソースの識別の一部ではなく、リクエスト URI のみであると述べています。

アップデート

「HTTP/1.1 仕様」として参照されている RFC2616 は廃止されました。2014 年に RFC 7230-7237 に置き換えられました。「リクエストの処理時にメッセージ本文を無視する必要がある」という引用が削除されました。「メソッドがメッセージ本文の用途を定義していなくても、リクエストメッセージのフレーミングはメソッドのセマンティクスから独立しています」削除されました。- コメントより

HTTP 1.1 2014 仕様から:

GET 要求メッセージ内のペイロードには、セマンティクスが定義されていません。GET リクエストでペイロード ボディを送信すると、一部の既存の実装でリクエストが拒否される可能性があります。

于 2009-06-11T20:27:36.547 に答える
340

それを行うことはできますが、HTTP 仕様で明示的に禁止されていない限り、人々はそのように動作することを期待していないという理由だけで、それを避けることをお勧めします。HTTP リクエスト チェーンには多くのフェーズがあり、「ほぼ」HTTP 仕様に準拠していますが、Web ブラウザで従来どおりに動作することだけは保証されています。(透過プロキシ、アクセラレータ、A/V ツールキットなどを考えています。)

これがロバストネス原則の背後にある精神であり、「受け入れるものにはリベラルであり、送信するものには保守的である」ということです。正当な理由なしに仕様の境界を押し広げたくはありません。

ただし、正当な理由がある場合は、それを実行してください。

于 2009-06-10T20:53:43.317 に答える
200

キャッシングを利用しようとすると、問題が発生する可能性があります。プロキシはGET、パラメーターが応答に影響を与えるかどうかを確認するために本文を調べません。

于 2009-06-10T21:10:50.177 に答える
87

restclientもREST コンソールもこれをサポートしていませんが、curl はサポートしています。

HTTP仕様はセクション4.3で述べています

リクエスト メソッドの仕様 (セクション 5.1.1) でエンティティ ボディの送信が許可されていない場合、リクエストにメッセージ ボディを含めてはなりません (MUST NOT)。

セクション 5.1.1は、さまざまな方法についてセクション 9.x にリダイレクトします。メッセージ本文を含めることを明示的に禁止するものはありません。でも...

セクション5.2は言う

インターネット要求によって識別される正確なリソースは、Request-URI と Host ヘッダー フィールドの両方を調べることによって決定されます。

そしてセクション9.3は言う

GET メソッドは、Request-URI によって識別される情報 (エンティティの形式) を取得することを意味します。

これらは、GET 要求を処理するときに、サーバーがRequest-URI および Host ヘッダー フィールド以外を調べる必要がないことを示唆しています。

要約すると、HTTP 仕様は、GET を使用してメッセージ本文を送信することを妨げませんが、すべてのサーバーでサポートされていなくても驚かないほどのあいまいさがあります。

于 2013-03-27T10:41:38.490 に答える
40

本文を付けてGETを送信するか、POSTを送信して、RESTishの宗教を放棄することができます(それほど悪くはありません。5年前、その信仰のメンバーは1人だけでした。彼のコメントは上にリンクされています)。

どちらも優れた決定ではありませんが、GET本文を送信すると、一部のクライアント(および一部のサーバー)の問題を防ぐことができます。

POSTを実行すると、一部のRESTishフレームワークで障害が発生する可能性があります。

Julian Reschkeは、「SEARCH」のような非標準のHTTPヘッダーを使用することを提案しました。これは、サポートされる可能性がさらに低いことを除けば、洗練されたソリューションになる可能性があります。

上記のそれぞれを実行できるクライアントと実行できないクライアントをリストするのが最も生産的かもしれません。

(私が知っている)bodyでGETを送信できないクライアント:

  • XmlHTTPRequestフィドラー

bodyを使用してGETを送信できるクライアント:

  • ほとんどのブラウザ

GETから本体を取得できるサーバーとライブラリ:

  • Apache
  • PHP

GETから本体を取り除くサーバー(およびプロキシ):

于 2012-08-30T21:41:59.230 に答える
38

あなたが達成しようとしていることは、はるかに一般的な方法で長い間行われており、GET でペイロードを使用することに依存していません。

特定の検索メディアタイプを単純に構築するか、より RESTful にしたい場合は、OpenSearch などを使用して、サーバーが指示した URI (/search など) にリクエストを POST します。その後、サーバーは検索結果を生成するか、最終的な URI を作成して 303 を使用してリダイレクトできます。

これには、従来の PRG メソッドに従うという利点があり、キャッシュ仲介者が結果をキャッシュするのに役立ちます。

とはいえ、URI は ASCII 以外のすべてに対してエンコードされます。また、application/x-www-form-urlencoded と multipart/form-data もエンコードされます。ReSTful シナリオをサポートすることを意図している場合は、さらに別のカスタム json 形式を作成するのではなく、これを使用することをお勧めします。

于 2009-06-10T22:47:04.303 に答える
33

この質問を IETF HTTP WG に提出しました。Roy Fielding (1998 年に http/1.1 ドキュメントの作成者) からのコメントは、

「...実装は、受信した場合にその本文を解析して破棄する以外のことを行うと壊れます」

RFC 7213 (HTTPbis) は次のように述べています。

「GET 要求メッセージ内のペイロードには定義されたセマンティクスがありません。」

GET リクエスト ボディのセマンティックな意味が禁止されていることが意図されていることは明らかです。つまり、リクエスト ボディを使用して結果に影響を与えることはできません。

GET に body を含めると、さまざまな方法でリクエストを確実に中断するプロキシが存在します。

要約すると、それをしないでください。

于 2016-07-28T01:06:25.980 に答える
23

どのサーバーがそれを無視しますか? — フィジアロン

たとえば、Googleはそれを無視するよりも悪いことをしています。エラーと見なします。

シンプルな netcat で試してみてください:

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

1234

(1234 の内容の後に CR-LF が続くため、合計 6 バイトになります)

そしてあなたは得るでしょう:

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.

また、AkamaiGhost が提供する Bing、Apple などから 400 Bad Request も取得します。

したがって、本体エンティティで GET リクエストを使用することはお勧めしません。

于 2013-06-29T21:26:20.443 に答える
21

RFC 2616、セクション 4.3、「メッセージ本文」から:

サーバーは、任意の要求でメッセージ本文を読み取って転送する必要があります。リクエストメソッドにエンティティボディの定義されたセマンティクスが含まれていない場合、リクエストを処理するときにメッセージボディを無視する必要があります。

つまり、サーバーは常にネットワークから提供された要求本文を読み取る必要があります (Content-Length を確認するか、チャンクされた本文を読み取るなど)。また、プロキシは、受信したそのようなリクエスト ボディを転送する必要があります。次に、RFC が特定のメソッドの本文のセマンティクスを定義している場合、サーバーは実際に要求本文を使用して応答を生成できます。ただし、RFCで本文のセマンティクスが定義されていない場合、サーバーはそれを無視する必要があります。

これは、上記のフィールディングからの引用と一致しています。

セクション 9.3の「GET」では、GET メソッドのセマンティクスについて説明していますが、リクエストの本文については触れていません。したがって、サーバーは、GET 要求で受信した要求本文をすべて無視する必要があります。

于 2014-03-06T21:44:45.233 に答える
14

XMLHttpRequest によると、有効ではありません。標準から:

4.5.6send()メソッド

client . send([body = null])

リクエストを開始します。オプションの引数は、リクエストの本文を提供します。GETリクエストメソッドがまたはの場合、引数は無視されHEADます。

InvalidStateErrorいずれかの状態が 開かれていないか、send()フラグが設定されている場合、例外をスローします。

メソッドは次の手順を実行する必要があります。send(body)

  1. 状態が open でない場合は例外をスローしInvalidStateErrorます。
  2. フラグが設定されている場合はsend()、例外をスローしInvalidStateErrorます。
  3. リクエスト メソッドがGETまたはの場合、ボディを nullHEADに設定します。
  4. bodyが null の場合は、次のステップに進みます。

ただし、GET リクエストには大きな本文コンテンツが必要になる可能性があるため、そうすべきではないと思います。

そのため、ブラウザーの XMLHttpRequest に依存すると、おそらく機能しません。

于 2016-05-04T20:07:07.830 に答える
7

私はこれをお勧めしません。それは標準的な慣行に反するものであり、見返りはあまりありません。オプションではなく、コンテンツの本文を保持する必要があります。

于 2009-06-10T20:56:09.193 に答える
6

プロトコルとしての REST が OOP をサポートしておらず、Getメソッドが証明されていることに腹を立てています。解決策として、DTO を JSON にシリアル化し、クエリ文字列を作成できます。サーバー側では、クエリ文字列を DTO に逆シリアル化できます。

見てみましょう:

メッセージ ベースのアプローチは、Get メソッドの制限を解決するのに役立ちます。リクエスト本文と同様に、任意の DTO を送信できます

Nelibur Web サービス フレームワークは、使用できる機能を提供します

var client = new JsonServiceClient(Settings.Default.ServiceAddress);
var request = new GetClientRequest
    {
        Id = new Guid("2217239b0e-b35b-4d32-95c7-5db43e2bd573")
    };
var response = client.Get<GetClientRequest, ClientResponse>(request);

as you can see, the GetClientRequest was encoded to the following query string

http://localhost/clients/GetWithResponse?type=GetClientRequest&data=%7B%22Id%22:%2217239b0e-b35b-4d32-95c7-5db43e2bd573%22%7D
于 2014-02-09T23:04:22.243 に答える
5

不適合なbase64でエンコードされたヘッダーはどうですか? "SOMETHINGAPP-PARAMS:sdfSD45fdg45/aS"

長さ制限うーん。POST 処理で意味を区別することはできませんか? 並べ替えのような単純なパラメーターが必要な場合、これが問題になる理由がわかりません。あなたが心配しているのは確かだと思います。

于 2011-02-15T21:34:57.707 に答える
4

私見では、エンコードさJSONれた(つまりencodeURIComponent、.URLHTTPJSON

于 2013-02-26T19:04:27.287 に答える