XMLHttpRequest リクエストボディについて
リクエストボディについて調べてみます。
AJAX通信時にPOSTリクエストする際、クライアント側からサーバ側への通信内容にリクエストボディが含まれます。
リクエストボティは次の種類があります。
フォームエンコード(HTMLフォーム) JSON XML ファイルアップロード multipart/form-data
実際にサンプルコードを用意しつつ、一つ一つ動きを見てみます。
リクエストボディ – フォームエンコード(HTMLフォーム) について
ここではPOST形式での送信時に、フォームエンコードがどのように通信されるのかをみてみます。
一般的なHTMLフォームでは、テキストボックスや、チェックボックス、セレクトボックス等が
設置され、そのフォームの内容をサーバへ送信することで、サーバ側の処理に値を渡すことができます。
AJAX通信時にも同様に、HTMLフォームの値を「キーと値」の組み合わせで、サーバ側に送信します。
また、リクエスト時のデータは文字列形式にエンコードしてサーバ側に送信します。
HTMLフォームの要素が複数の場合、例えば要素1、要素2、要素3がある場合、
要素1のフォームの値を「キーと値」のペアとして、次に要素2、要素3の「キーと値」を&で連結してサーバ側に送信されます。
また、送信時に「application/x-www-form-urlencoded」MIMEタイプを、POSTするときのContent-Typeのリクエストヘッダに設定します。
例えば、サーバ側に以下のデータを送信することを考えます。
{ test1: "aaaa", test2: "bbbb", test3: "cccc" }
上記の値をサーバ側に送信する際、encodeURIComponentしたうえで「キーと値」のセットにし、
それぞれの要素(ここではtest1、test2、test3の3つ)を&で連結します。
ここまでの内容を踏まえて、簡単なサンプルを書いてみます。
クライアント側からサーバ側へのフォーム内容の送信方法は3通りありますが、
ここでは原始的な方法を試してみます。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テストHTML</title> </head> <body> <input type="button" id="sampleXMLHttpRequest" value="レスポンスボディのテスト"> <div>通信時の処理内容</div> <div id="ajax_result"></div> <script type="text/javascript"> // ボタン要素のDOMを取得 let element_sampleXMLHttpRequest = document.getElementById('sampleXMLHttpRequest'); // イベントを付与 element_sampleXMLHttpRequest.addEventListener('click', SendXMLHttpRequest, false); // ボタン押下時の処理 function SendXMLHttpRequest() { // 今回のサンプル用の送信データを以下のように定義 // 実際の実装シーンでは、画面上にフォームを設置し、入力された値等を取得する let send_data = { test1: "123", test2: "aaa", test3: "テスト" } // 通信処理を画面に出力する為、DOM操作 let result = document.getElementById("ajax_result"); // 検証の為、画面出力とログ出力をする result.innerHTML += 'レスポンスボディのテスト start' + '<br />'; // ajax通信処理の開始 let req = new XMLHttpRequest(); // POST形式でサーバ側の「response.php」へデータ通信を行う req.open("POST", "./response.php"); // リクエストヘッダにMIMEタイプを設定する req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // サーバ側への送信用の配列を用意する let urlPairs = []; // デモ用のsend_dataオブジェクトを、キーと値のペアにし、 // 全ての要素を「+」で連結する for (key_in in send_data) { // キーと値をそれぞれエンコードをして取得する let p_key = encodeURIComponent(key_in); let p_value = encodeURIComponent(send_data[key_in]) // キーと値のペアを生成し、サーバ送信用の配列へ格納する urlPairs.push(p_key + '=' + p_value); } // サーバ送信用の配列を&区切りにして文字列にし、send_params 変数へ代入する let send_params = urlPairs.join('&'); result.innerHTML += 'サーバ送信用の配列を&区切りにして文字列にし、send_params 変数へ代入する' + '<br />'; result.innerHTML += 'send_params -> ' + send_params + '<br />'; result.innerHTML += '通信処理の開始' + '<br />'; // ここまでで整理した送信用データを、サーバ側へ送信する req.send(send_params); // 検証の為、画面出力とログ出力をする result.innerHTML += '通信処理の終了' + '<br />'; result.innerHTML += 'レスポンスボディのテスト end' + '<br />'; } </script> </body> </html>
また、サーバ側のphpはシンプルにリクエスト変数をログファイルに出力するだけの処理にしています。
(ここではjavascript側のレスポンスまでは考慮していません)
<?php file_put_contents('./response.log', print_r($_REQUEST, true)); ?>
画面にアクセスして「レスポンスボディのテスト」のボタンを押下すると、
出力結果は次のようになります。
通信時の処理内容 レスポンスボディのテスト start サーバ送信用の配列を&区切りにして文字列にし、send_params 変数へ代入する send_params -> test1=123&test2=aaa&test3=%E3%83%86%E3%82%B9%E3%83%88 通信処理の開始 通信処理の終了 レスポンスボディのテスト end
サーバ側へ送信する値は最初に
{ test1: "aaaa", test2: "bbbb", test3: "cccc" }
という形で用意していましたが、サーバへ通信する際には
send_params -> test1=123&test2=aaa&test3=%E3%83%86%E3%82%B9%E3%83%88
という形にエンコードしたうえで送信していることがわかります。
この時、半角英数時の「123」と「aaa」はエンコード処理されても形は変わらないですが、
日本語文字の「テスト」は
test3=%E3%83%86%E3%82%B9%E3%83%88
という値になっていることがわかります。
また、サーバ側のphpが出力したログファイルは以下のように出力されており、
問題なくデータが受信できていることがわかります。
Array ( [test1] => 123 [test2] => aaa [test3] => テスト )