web-dev-qa-db-ja.com

URLクエリパラメータを使用するHTTP POST - お勧めかどうか

私はHTTP上で動作するようにAPIを設計しています、そしてHTTP POSTコマンドを使用するかどうか疑問に思っています、しかしURL問い合わせパラメータだけでリクエストボディなしで、進むべき良い方法です。

考慮事項:

  • "良いWebデザイン"はPOSTを通して送られるべきではないべきでない行動を必要とします。これは冪等ではありません。
  • リクエストパラメータがURLに含まれていると、このアプリの開発とデバッグが簡単になります。
  • このAPIは、広く使用されることを意図していません。
  • 本文なしでPOSTリクエストを作成すると、もう少し作業がかかるようです。 Content-Length: 0ヘッダーを明示的に追加する必要があります。
  • 私には、本文なしのPOSTは、ほとんどの開発者およびHTTPフレームワークの期待に少し反するように思えます。

リクエストボディではなくURLクエリを介してPOSTリクエストでパラメータを送信することには、他に落とし穴や利点がありますか。

編集:これが考慮されている理由は、操作がべき等ではなく、検索以外の副作用があるためです。 HTTPの仕様 を参照してください。

特に、GETメソッドとHEADメソッドには、取得以外のアクションを実行する意義があるべきではないという規約が確立されています。これらの方法は「安全」と見なされるべきです。これにより、ユーザーエージェントはPOST、PUT、DELETEなどの他のメソッドを特別な方法で表現できるようになり、ユーザーはおそらく危険なアクションが要求されているという事実を認識することができます。

...

メソッドは、(エラーや有効期限の問題を除けば)N> 0の同一リクエストの副作用が単一リクエストの場合と同じであるという点で、「べき等性」の特性を持つこともできます。メソッドGET、HEAD、PUT、DELETEはこのプロパティを共有します。また、OPTIONSメソッドとTRACEメソッドには副作用がないはずであるため、本質的にはべき等です。

414
Steven Huwig

あなたの行動が冪等でない場合、あなたは必ずPOSTを使わなければなりません。そうでなければ、あなたはただ問題を解決するよう求めているだけです。 GETPUT、およびDELETEメソッドは、冪等性であるために必須です。クライアントがサービスに対するすべての可能なGETリクエストをプリフェッチしている場合、アプリケーションで何が起こるかを想像してみてください - これがクライアントに見える副作用を引き起こすならば、何かが間違っています。

私はPOSTをクエリ文字列付きでボディなしで送信することは奇妙に思えることに同意します、しかし私はそれが状況によっては適切かもしれないと思います。

現在のリクエストの範囲を制限するためのリソースへのコマンドとしてURLのクエリ部分を考えてください。通常、クエリ文字列は(?page=1&sort=titleのように)GETリクエストをソートまたはフィルタリングするために使用されますが、(おそらく?action=delete&id=5のように)スコープを制限することもPOSTで意味があると思います。

226
Don McCaughey

誰もが正しい:べき等でない要求にはPOSTを使い続ける。

URIクエリ文字列とリクエストコンテンツの両方を使用するのはどうですか?それは有効なHTTPです(注1を参照)。

また、完全に論理的です。クエリ文字列部分を含むURLは、locatingリソース用です。一方、HTTPメソッドの動詞(POST-およびオプションのリクエストコンテンツ)は、アクション、または何をするかリソースを指定するためのものです。それらは直交的な関心事であるべきです。 (ただし、ContentType = application/x-www-form-urlencodedの特殊なケースでは、これらは美しく直交する問題ではありません。以下の注2を参照してください。)

注1:HTTP仕様(1.1)では、POSTまたはPUT要求を受け入れるHTTPサーバーに対して、クエリパラメーターとコンテンツが相互に排他的であるとは規定されていません。したがって、どのサーバーでも両方を自由に受け入れることができます。つまりサーバーを記述する場合、両方を受け入れることを止めることは何もありません(柔軟性のないフレームワークを除く)。一般的に、サーバーは必要なルールに従ってクエリ文字列を解釈できます。 Content-Typeのような他のヘッダーも参照する条件ロジックでそれらを解釈することもできます。

注2:web browserがユーザーがWebアプリケーションにアクセスする主な方法であり、application/x-www-form-urlencodedが投稿するContent-Typeである場合、そしてshouldそのContent-Typeのルールに従います。そして、application/x-www-form-urlencodedのルールは、より具体的です(率直に言って、珍しい):この場合、URIをリソースの場所ではなくパラメーターのセットとして解釈する必要があります。 [これは、Powerlordが提起した有用性と同じポイントです。サーバーへのPOSTコンテンツにWebフォームを使用するのは難しいかもしれません。説明が少し異なります。]

注3:クエリ文字列は元々何のためですか? RFC 3986は、リソースを特定する非階層的な方法として機能するURI部分としてHTTPクエリ文字列を定義しています。

この質問をしている読者が、良いRESTfulアーキテクチャとは何かを尋ねたい場合、RESTfulアーキテクチャパターンは、特定の方法で機能するURIスキームを必要としません。 RESTfulアーキテクチャは、リソースのキャッシュ可能性、リソース自体の設計(それらの動作、機能、表現)、およびべき等性が満たされるかどうかなど、システムの他のプロパティに関係します。または、言い換えると、HTTPプロトコルおよびそのHTTPメソッド動詞のセットと非常に互換性のある設計を実現します。 :-)(言い換えれば、RESTfulアーキテクチャは、リソースがlocatedであるかどうかに関してあまり予測的ではありません。)

最後の注意:クエリパラメーターは、リソースの検索やコンテンツのエンコードではない、さらに別のことに使用される場合があります。 「PUT = true」や「POST = true」などのクエリパラメータを見たことがありますか?これらは、PUTおよびPOSTメソッドの使用を許可しないブラウザーの回避策です。このようなパラメータは、URLクエリ文字列の一部として(ワイヤ上で)表示されますが、URLクエリの一部ではないことを主張しますin spirit

123

あなたは理由が欲しいですか?これが一つです:

Webフォームを使用して、GETとPOSTを組み合わせたページにリクエストを送信することはできません。フォームのメソッドをGETに設定した場合、すべてのパラメータはクエリ文字列内にあります。フォームのメソッドをPOSTに設定した場合、すべてのパラメータはリクエストボディにあります。

出典:HTML 4.01規格、section 17.13フォーム送信

61
Powerlord

プログラム的な観点からは、クライアントにとってはパラメータをパッケージ化してそれらをURLに追加し、POST対GETを実行します。サーバー側では、投稿されたバイトの代わりにクエリ文字列からの受信パラメータを評価します。基本的に、それは洗い物です。

利点/不利な点がある可能性があるのは、特定のクライアントプラットフォームがネットワークスタック内のPOSTおよびGETルーチンとどのように連携するか、およびWebサーバーがそれらの要求を処理する方法です。実装によっては、一方のアプローチの方が他方よりも効率的な場合があります。それを知っていることがここでの決断の指針となります。

それにもかかわらず、プログラマの観点からは、私はボディのすべてのパラメータを持つPOST、またはURLのすべてのパラメータを含むGETを許可し、POSTリクエストでは明示的にurlパラメータを無視します。混乱を避けます。

8
jro

コンテンツペイロードをPOST本体に限定しながら、URL上のリソースを識別するクエリ引数を持つことは、まだ非常にRESTfulである可能性があります。これは、「何を送っているのですか」という考慮事項とは切り離されているように見えます。対 "誰に送っているの?".

5
swizzcheez

REST キャンプには、HTTP動詞の使用方法を標準化するために使用できる基本原則がいくつかあります。あなたがしているようにRESTful APIを構築するとき、これは役に立ちます。

一言で言えば:GETは読み取り専用にする必要があります。つまり、サーバーの状態には影響しません。 POSTは、サーバー上にリソースを作成するために使用されます。 PUTはリソースを更新または作成するために使用されます。 DELETEはリソースを削除するために使用されます。

言い換えれば、あなたのAPIアクションがサーバーの状態を変更した場合、RESTはPOST/PUT/DELETEを使うように勧めますが、GETはしません。

POSTの目的はサーバーの状態を変更すること(たとえば、チェックアウト時に商品の代金を払うこと)であるため、ユーザーエージェントは通常複数のPOSTを実行するのは悪いことであり警告します二度やりなさい!

あなたが好きなようによくできるGETと比較してください(べき等)。

2
saille