パラメータはHTTP POSTリクエストでどのように送信されますか?


1476

HTTP GETリクエストでは、パラメータはクエリ文字列として送信されます

http://example.com/page?parameter = value&also = another

HTTP POST要求では、パラメーターはURIと共に送信されません。

値はどこにありますか?リクエストヘッダーでは?リクエストボディに?それはどのように見えますか?

回答:


1254

値は、コンテンツタイプで指定されている形式で、リクエストの本文で送信されます。

通常、コンテンツタイプはapplication/x-www-form-urlencodedであるため、リクエストの本文ではクエリ文字列と同じ形式を使用します。

parameter=value&also=another

フォームでファイルのアップロードを使用する場合は、multipart/form-data代わりに、形式が異なるエンコーディングを使用します。より複雑ですが、通常はどのように見えるかを気にする必要がないため、例は示しませんが、存在することを知っておくとよいでしょう。


25
ファイルのアップロードが異なる(+ 1 /受け入れられる)ことを忘れていました。あなたの答えは十分ですが、にもっと情報があればもっといいでしょうmultipart/form-data。興味のある方のために、ここでそれについて質問します
Camilo Martin

73
:本文はヘッダーと1行の空白行で区切られています。
Gab是好人

2
HTTPBodyに何を配置するかを説明しましたが、HTTPHeaderには何を配置または書き込みますか?それはどのような目的に役立ちますか?
ハニー

4
@Honey:投稿のHTTPヘッダーはgetのヘッダーのように見えますが、GETではなくPOSTという動詞があり、リクエストにコンテンツ(本文)があるため、コンテンツタイプの値(およびオプションのコンテンツの長さの値)があります。すべてのタイプのリクエストにはヘッダーがあり、一部のタイプには本文もあります。
グッファ、2016年

4
@KennethWordenいいえ、どのメソッドも正しくJSONを送信しません。ただし、エンコードされた形式でjsonファイルをアップロードしmultipart/form-dataたり、リクエストの作成を担当している場合は、content-typeをに変更してapplication/jsonjsonテキストをhttp本文に直接貼り付けたりできます
Cholthi Paul Ttiopic

428

コンテンツはHTTPヘッダーの後に置かれます。HTTP POSTの形式は、HTTPヘッダー、空白行、リクエスト本文の順です。POST変数は、本体にキーと値のペアとして格納されます。

これは、以下に示すHTTP Postの未加工のコンテンツで確認できます。

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

これはFiddlerなどのツールを使用して確認できます。このツールを使用すると、回線を介して送信される未加工のHTTP要求と応答のペイロードを監視できます。


39
コンテンツタイプがapplication/x-www-form-urlencodedである場合のみ。これは常に当てはまるとは限りません。
グッファ2013年

@ Camilo Martin ....すばらしい質問には[+1]&@ Joe Alfano ....すばらしい答えには[+1] ....... POSTリクエストについて明確なアイデアが得られました....しかし、画像がデータ情報のキーと値のペアと一緒に来た場合、POSTの構造はどのように見えますか?
Devrath 2013年

9
@ジョー、さて、なぜFromそこにヘッダーがあるのですか?
Pacerier 2014

@Joe、Fromヘッダーをランダムに含めるのが好きです。IMO 418 HTTPステータスコードが表示されます。
トムハワード

ユーザーおよびパスワード認証をどのように追加しますか?
m4l490n

376

短い答え: POSTリクエストでは、値はリクエストの「本体」で送信されます。Webフォームでは、ほとんどのapplication/x-www-form-urlencoded場合、メディアタイプまたはで送信されmultipart/form-dataます。ハンドルのWeb要求に設計されているプログラミング言語やフレームワークは、通常、このような要求に「正しいこと™」を行うと、容易に復号値(のように簡単にアクセスを提供し$_REQUESTたり$_POST、PHPで、またはcgi.FieldStorage()flask.request.formPythonで)。


今少し違いを見てみましょう。違いを理解するのに役立ちます;)

GETPOSTリクエストの違いは主にセマンティックです。また、値の受け渡し方法の違いを説明するために、それらの使用方法も異なります。

GET(関連RFCセクション

GETリクエストを実行するとき、サーバーにエンティティまたはエンティティのセットを要求します。クライアントが結果をフィルタリングできるようにするために、URLのいわゆる「クエリ文字列」を使用できます。クエリ文字列は?。の後の部分です。これはURI構文の一部です。

したがって、アプリケーションコード(リクエストを受信する部分)の観点からは、URIクエリ部分を検査してこれらの値にアクセスする必要があります。

キーと値はURIの一部であることに注意してください。ブラウザによっては、URIの長さに制限課される場合があります。HTTP標準では、制限はありません。ただし、この記事の執筆時点では、ほとんどのブラウザーでURI 制限されています(特定の値はありません)。サーバーに新しい情報を送信するためにGETリクエストを使用しないでください。特に大きなドキュメントではありません。ここで、POSTまたはを使用する必要がありますPUT

POST(関連RFCセクション

POSTリクエストを実行するとき、クライアントは実際に新しいドキュメントをリモートホストに送信しています。したがって、クエリ文字列は(意味的に)意味がありません。これが、アプリケーションコードでそれらにアクセスできない理由です。

POSTもう少し複雑な(かつある方法より柔軟):

POSTリクエストを受信するときは、常に「ペイロード」、つまりHTTPの用語であるメッセージ本文が必要です。(私が知る限り、多分application / octet-stream?)標準形式がないため、メッセージ本文自体はほとんど役に立ちません。本文の形式はContent-Typeヘッダーによって定義されます。でHTML FORM要素を使用する場合method="POST"、これは通常application/x-www-form-urlencodedです。別の非常に一般的なタイプは、ファイルのアップロードを使用する場合のmultipart / form-dataです。しかし、それは可能性がに至るまで、text/plainオーバー、application/jsonあるいはカスタムapplication/octet-stream

いずれの場合でも、アプリケーションで処理できないを使用POSTしてリクエストが行われたContent-Type場合は、415status-codeを返す必要があります

ほとんどのプログラミング言語(および/またはウェブフレームワークが)/からの最も一般的なタイプ(のようにメッセージ本体デ/エンコードする方法を提供しapplication/x-www-form-urlencodedmultipart/form-dataまたはapplication/json)。簡単です。カスタム型は、潜在的にもう少し多くの作業を必要とします。

例として標準のHTMLフォームでエンコードされたドキュメントを使用して、アプリケーションは次の手順を実行する必要があります。

  1. Content-Typeフィールドを読む
  2. 値がサポートされているメディアタイプのいずれでもない場合は、415ステータスコードを含む応答を返します
  3. それ以外の場合は、メッセージ本文から値をデコードします。

繰り返しになりますが、PHPのような言語、または他の一般的な言語のWebフレームワークがおそらくこれを処理します。これの例外は415エラーです。フレームワークは、アプリケーションがサポートする、またはサポートしないことを選択するコンテンツタイプを予測できません。これはあなた次第です。

PUT(関連RFCセクション

PUT要求はかなりのとまったく同じ方法で処理されるPOST要求。大きな違いは、POSTリクエストはサーバーに新しいリソースを作成する方法(および、もしあれば)を決定させることです。歴史的に(現在は廃止されたRFC2616から、リクエストが送信されたURIの「下位」(子)として新しいリソースを作成することでした)。

PUT対照的に、要求が正確に「預金」のリソースになっている、そのURI、およびとまさにそのコンテンツ。それ以上でもそれ以下でもありません。アイデアは、クライアントが「PUT」する前に完全なリソースを作成する責任があるということです。サーバはそれを受け入れる必要があり、あるとして指定されたURLに。

その結果、POSTリクエストは通常、既存のリソースを置き換えるために使用されません。PUT要求は、両方やる作成することができますし、交換してください。

サイドノート

リモートに追加のデータを送信するために使用できる「パスパラメータ」もありますが、あまり一般的ではないので、ここではあまり詳しく説明しません。ただし、参考までに、RFCからの抜粋を以下に示します。

階層パスのドットセグメントは別として、パスセグメントは一般的な構文では不透明と見なされます。URI生成アプリケーションでは、多くの場合、セグメントで許可されている予約文字を使用して、スキーマ固有または逆参照ハンドラ固有のサブコンポーネントを区切ります。たとえば、セミコロン( ";")および等号( "=")の予約文字は、そのセグメントに適用可能なパラメーターとパラメーター値を区切るためによく使用されます。コンマ( "、")予約文字は、同様の目的でよく使用されます。たとえば、あるURIプロデューサーは「name; v = 1.1」などのセグメントを使用して「name」のバージョン1.1への参照を示し、別のURIプロデューサーは「name、1.1」などのセグメントを使用して同じことを示す場合があります。パラメータタイプは、スキーム固有のセマンティクスによって定義できます。


1
確かに少し接線を入れているかもしれません。明確にするために、回答の先頭に「tl; dr」を追加しました。
exhuma 2014年

また、RFC2616の代わりにRFC7231を参照するように編集しました(これはしばらくの間廃止されています)。更新されたリンクとは別に、この回答の主な違いは、「PUT」セクションにあります。
exhuma 14年

PUTはべき等であることになっているため、POSTとは異なる方法で処理されると思いましたか?stackoverflow.com/questions/611906/...
rogerdpack

1
@rogerdpackあなたは間違っていません。PUTセクションの2番目の段落を読むと、べき等であることわかります。POST対照的に-定義により-できません。POST常に新しいリソースを作成します。PUT同じリソースが存在する場合は、それを置き換えます。したがって、POST10回呼び出すと、10個のリソースが作成されます。PUT10回呼び出すと、(たぶん)1つだけ作成されます。それはあなたの質問に答えますか?
exhuma

60

ブラウザのURLバーに直接入力することはできません。

たとえば、ライブHTTPヘッダーを使用して、POSTデータがインターネット上でどのように送信されるかを確認できます。結果はそのようなものになります

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

それが言うところ

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

ポスト値になります。


2
明確化:ここにあるContent-Lengthはず29ですか?これが実際の文字列の長さですusername=zurfyx&pass=password
カバ

@カバはそこにあるはずの改行文字でしたか?
vikingsteve

@vikingsteve私はあなたの意味を理解しています。したがって、コンテンツの最後には常に改行があると思います。
カバ

2
ヘッダーは本文から改行で区切られます
–MáraToner 2018

24

POSTリクエストのデフォルトのメディアタイプはapplication/x-www-form-urlencodedです。これは、キーと値のペアをエンコードするための形式です。キーは重複する可能性があります。各キーと値のペアは&文字で区切られ、各キーはその値から文字で区切られます=

例えば:

Name: John Smith
Grade: 19

次のようにエンコードされます:

Name=John+Smith&Grade=19

これは、HTTPヘッダーの後のリクエスト本文に配置されます。


1
HTTPBodyに何を配置するかを説明しましたが、HTTPHeaderには何を配置または書き込みますか?
ハニー

キーが重複する可能性があるとおっしゃっていましたが、そのような重複の結果はどうなりますか?最後の値は以前の値を自動的に上書きしますか?ありがとう。
Jinghui Niu 2017

@JinghuiNiuキーが重複している場合は、配列として解析する必要があります。これは非常に遅いですが、誰かを助けるかもしれません。
Hanash Yaslem

18

HTTP POSTのフォーム値は、クエリ文字列と同じ形式でリクエストの本文で送信されます。

詳細については、仕様をご覧ください。


5
「同じフォーマット」は少しあいまいです。彼ら?は例えばから始まりますか?
Camilo Martin

7
@PeterWoosterはい、しかし例を提供しません。その点、「見て、あなたの質問に対する答えがアプリケーションのブログ(リンク)にあります」という答えのようなものです。
Camilo Martin

36
@PeterWooster必要ではありませんが、何かを忘れてググって、SOである最初のリンクに移動すると非常に良いです。非常に詳細な仕様であり、包括的であっても、復習には適さない場合があります。考えてみてください。このサイトのほとんどのQAは、「スペック/マニュアル/ API / etc (リンク)を読んでください」と要約できます。役に立ちますか?グーグル以上ではない。
Camilo Martin

2
コンテンツタイプがapplication/x-www-form-urlencodedである場合のみ。これは常に当てはまるとは限りません。
Guffa 2013年

3
GETクエリ文字列の形式は、application / x-www-form-urlencodedの形式とは異なります。たとえば、空白は別の方法でエンコードされます(%20と+)。この点に関して、答えは誤解を招くものです。
UnclickableCharacter

18

一部のWebサービスでは、リクエストデータメタデータを別々に配置する必要があります。たとえば、リモート関数は、署名されたメタデータ文字列がURIに含まれていることを予期している場合がありますが、データはHTTPボディに投稿されます。

POSTリクエストは、意味的には次のようになります。

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

このアプローチContent-Typeは、Webサーバー用の「解析命令」である単一を使用して、QueryStringとBody-Postを論理的に組み合わせます。

ご注意: HTTP / 1.1がされてラップ#32左にと付き(スペース)#10を右に(改行)。


違い/user/john/?user=john合理的に予想通り、私はこれを取るので、単にセマンティック1(HTTPは実際にクエリ文字列に特別な治療を与えるものではありません)です。しかし、「左側のスペースに包まれている」とはどういう意味ですか?HTTPメソッドの前にスペースはありません。投稿本文の空白行ですか?
Camilo Martin

上記のコードとコードの間にはスペース(ASCII#32)が...Ym04ありHTTP/1.1ます。したがって、QueryStringは動詞とプロトコルバージョンの間に存在します。
不明なインターフェイス

1
あなたのメモは、それが予期しないものでバージョン固有のものであるように聞こえるようにします。率直に言って、そこにスペースがあることは明らかです。そして、改行は、UNIXのすべてのものと同様に、他の行にも適用されます。
Camilo Martin

1
コードでマークアウトできなかったことを強調しました。それは明白に見えるかもしれませんが、時にはそれはそうではありません。
不明なインターフェイス

リクエストで?行うようにURIとパラメーターを分離することで、URLの一部としてクエリパラメーターを渡すことができるのは事実ですGET
asgs

8

まず、GETとを区別しましょうPOST

取得:これは、デフォルトでHTTPサーバーに作られており、後に来るサーバーおよびクエリ文字列からデータを取得するために使用され、要求?URIユニークなリソースを取得するために使用されます。

これはフォーマットです

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

ここでdata=value渡されたクエリ文字列値です。

POST:データをサーバーに安全に送信するために使用されるため、必要なものはすべてPOSTリクエストの形式です。

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

POST over GETを使用する理由

ではGET通常、クエリ文字列のベースURLに追加されているサーバーに送信された値が、今、このの2つの結果があります

  • GET要求は、パラメータを指定して、ブラウザの履歴に保存されています。したがって、パスワードは暗号化されずにブラウザの履歴に残ります。これは、当時のFacebookにとって本当の問題でした。
  • 通常、サーバーにはaの長さに制限URIがあります。送信されるパラメータが多すぎる場合、受け取る可能性があります414 Error - URI too long

投稿リクエストの場合、フィールドからのデータが代わりに本文に追加されます。要求パラメーターの長さが計算され、content-lengthのヘッダーに追加されます。重要なデータはURLに直接追加されません。

Googleデベロッパーツールのネットワークセクションを使用して、サーバーへのリクエストの作成方法に関する基本情報を確認できます。

あなたは常にあなたの中に複数の値を追加することができますRequest HeadersようにCache-ControlOriginAccept


4
セキュリティに関する仮定は、HTTPS接続のコンテキストでのみ当てはまりますHTTP。(クエリパラメータを含む)とのHTTPS両方を暗号化しURLます(どちらも暗号化/保護しないRequest Body場合)HTTP。説明されている問題は、多くのブラウザが(通常は暗号化されていない)履歴データベースに(URIsを含むURLs)を保存しているという事実から来ています。したがって、機密情報にはRequest Body+ のみを使用してくださいHTTPS
ペトルザハリア

@PetruZaharia私はあなたの説明に同意します。これを編集として提案することもできます。:)
Zeeshan Adil
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.