URLクエリパラメータを使用したHTTP POST —良いアイデアかどうか?[閉まっている]


451

私は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には副作用がないため、本質的にべき等です。


11
本文にデータを提供しないのに、なぜPOSTを使用するのですか?
サニーミレノフ2009年

114
操作がべき等ではないため。
Steven Huwig

20
@Jared、「REST」という単語が2.5年前のこの質問に表示されていないことに注意してください。:)べき等に関するHTTP仕様は、Webサービスの月間アーキテクチャーに関係なく適用されます。幸い、このAPIがプロキシするように設計されたシステムは、とにかく時代遅れになっています。
Steven Huwig

5
サーバーログはPOSTパラメータを記録しませんが、クエリ文字列を記録します。一連のリクエストをブラウザーでインストルメント化せずに実行してからトレースバックを確認する方が、クリックするよりもはるかに簡単です。また、APIはブラウザからサーバーではなく、サーバーからサーバーへのアクセスでした。最も重要なのは、とにかく事件全体が缶詰になったことです。:)
Steven Huwig、2013

13
べき等の意味を知らない他の人のために:| restapitutorial.com/lessons/idempotency.html
Christopher Grigg

回答:


259

アクションがべき等でない場合は、を使用する必要がありますPOST。そうでない場合は、問題を解決する必要があります。 GETPUTおよびDELETE方法をされている必要冪等であることを。クライアントがGETサービスのすべての可能なリクエストをプリフェッチしていた場合にアプリケーションで何が起こるか想像してみてください。これがクライアントに見える副作用を引き起こす場合は、何かがおかしいです。

POSTクエリ文字列ありで本文なしでを送信するのは奇妙に思われることに同意しますが、状況によっては適切である可能性があると思います。

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


4
私はこの特定のケースに対してこの回答を選択しましたが、R。ベンローズの議論はパブリックAPIに対して説得力があると思います。
Steven Huwig、2009年

4
彼の答えは厳密には正しいとは思いません。HTMLページがクライアントに送信されるときにフォーム投稿のURLパラメーターがわかっている場合は、それらのURLパラメーターをフォームのaction属性に付加できます。そうでない場合、JavaScriptはフォームの送信時にURLパラメーターを設定できます。
Don McCaughey、

3
クエリパラメータを含むURLへのXMLファイルの投稿はどうですか?それは可能ですか?
OpenCoderX 2013

3
別の例:リクエストデータはhttpエンティティにあり、リクエストされたレスポンスのフォーマットはクエリパラメータ(/action?response_format=json)で渡される
rds

4
+1は今日何かを学びました。削除はべき等であることに対して技術的です。オブジェクトが実際に削除されると、not found 404が返されるため、サーバーは同じ状態になりますが、応答は異なります。牛の写真をご覧ください:restapitutorial.com/lessons/idempotency.html
JPK

131

誰もが正しい:非べき等のリクエストにはPOSTを使用します。

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

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

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

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

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

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

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


66

理由はありますか?ここに一つあります:

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

出典:HTML 4.01標準、セクション17.13フォームの送信


10
それはまともな議論ですが、私は現代のブラウザのJavascript実装が一種の議論の種になっていると思います。でも、私はそれについて考えます-将来を見据えた一種の方法で魅力的です。フォームを使用していないからといって、後で使用したくないという意味ではありません。
Steven Huwig、2009年

9
GETとPOSTを混在させることは非常に悪い考えです。HTTPをひどく壊し、正当な理由はありません。
aehlke 09

6
そのスニペットは、リンクしたページに表示されません
Gareth

40
そうですが、method属性は、リクエストに「フォームデータセット」を含める方法を定義するだけです。methodがPOSTの場合、フォームのでURIを変更することについての言及はありませんaction。もちろん、URIにはすでにクエリ文字列部分を含めることができます。
Gareth、

16
@Powerlordこれは間違っています。のアクションでフォームをPOSTに設定してみてください。/Books?bookCode=1234。ウェブサーバーはPOSTフォーム変数とクエリ文字列を取得します。
Jez、2013

9

プログラムの観点から見ると、クライアントの場合、パラメーターをパッケージ化してURLに追加し、POSTとGETを実行します。サーバー側では、ポストされたバイトではなく、クエリ文字列からのインバウンドパラメーターを評価します。基本的にはウォッシュです。

特定のクライアントプラットフォームがネットワークスタック内のPOSTおよびGETルーチンをどのように処理するか、およびWebサーバーがこれらの要求を処理する方法に利点/欠点があるかもしれません。実装によっては、1つのアプローチが他のアプローチより効率的である場合があります。それを知ることは、ここであなたの決定を導くでしょう。

それにもかかわらず、プログラマーの観点からは、本文にすべてのパラメーターを指定してPOSTを許可するか、URLにすべてのパラメーターを指定してGETを許可し、POST要求でURLパラメーターを明示的に無視することを好みます。それは混乱を避けます。


8

コンテンツペイロードをPOSTボディに制限したまま、URL上のリソースを特定するクエリ引数を持つことは、依然としてRESTfulであると思います。これにより、「何を送信するのか」の考慮事項が分離されているように見えます。対「私はそれを誰に送りますか?」。


5
問題はRESTに関するものではありませんでした。
Steven Huwig、2012年

3
@ user359996すべてのHTTP APIがRESTfulであるとは限りません。実際、そうではないと主張するほとんどのAPIは、実際にはそうではありません。また、おもしろいことに、RESTはHTTPだけではありません。
Alec Mev

4

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

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

言い換えると、APIアクションがサーバーの状態を変更する場合、RESTはPOST / PUT / DELETEを使用するようにアドバイスしますが、GETは使用しないでください。

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

好きなだけ頻繁に実行できるGET(べき等)と比較してください。


13
RESTキャンプは、HTTP仕様で定義されているHTTPを使用する必要があると述べています。つまり、RFC2616何もない、何もない。
ダレルミラー、

1
@Darrel参照ibm.com/developerworks/webservices/library/ws-restful:RESTは開発者に、プロトコル定義と整合性のある方法で明示的にHTTPメソッドを使用するように求めます。この基本的なREST設計原則は、作成、読み取り、更新、削除(CRUD)操作とHTTPメソッドの間の1対1のマッピングを確立します。このマッピングによると:サーバー上にリソースを作成するには、POSTを使用します。リソースを取得するには、GETを使用します。リソースの状態を変更または更新するには、PUTを使用します。リソースを削除または削除するには、DELETEを使用します。
セール:2011

5
申し訳ありませんが、それはまったく間違っています。RESTでは、統一されたインターフェースへの準拠が必要です。HTTPを使用している場合、その統一インターフェースは一部RFC 2616で定義されています。その仕様では、作成、読み取り、更新、削除とHTTPメソッドの間に1対1のマッピングはありません。
Darrel Miller

3
GETとDELETEはCRUDのReadとDeleteにかなりよく対応しますが、更新と作成にPUT / POSTを使用するのは簡単ではありません。stackoverflow.com/questions/630453/put-vs-post-in-rest
dcstrawを

5
この6年後を振り返ると、質問が10万回以上表示されていることを考えると、小さな更新を行う価値があると感じます。Darrelは、FieldingのRESTの定義(ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)に従って正しい-HTTP動詞をCRUDにマッピングすることについての言及はありません。IBMの開発者のアドバイス(上記のコメントのリンク)は、FieldingのRESTの定義ではなく、RESTful APIの実装における一般的な手法を反映しています。
2015

-13

同意します。本文ではなくURLでデータを渡す場合は、GETリクエストを使用する方が安全です。POST + GETの概念全体に関するいくつかの追加ビューについては、この同様の質問をご覧ください。


17
操作に副作用がある場合、ブラウザはすべてのGETがべき等であると想定するため、GETメソッドを使用することは確かに「安全」ではありません。
dcstraw

GoogleはGETリクエストですべてのリンクを安全に「クリック」しますが、その他はすべて除外するため、検索エンジンも悪夢の中でそれを変換します。罪のないクローラーが誤ってデータベースを消去してしまうほど、サービスを離れるのは安全ではありません。
アレハンドロ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.