PHPでPOST送信。バックエンドから他システムへのPOST送信

通常であれば、HTMLの<form method=’POST’>でデータを送信したり、JavaScriptでAjax通信を実装して、主にフロントエンドから行う処理ですが、
今回は、PHPプログラム側で、POSTリクエストを送信し、結果(レスポンス)を受け取る処理を書いてみました。
PHPのcurl関数を使ってPOST送信するのが、速度的には早いらしいですが、
今回は、お手軽なfile_get_contents()関数を使って、実装してみました。

file_get_contents()関数をで、POSTリクエストを実現

まずはソースから

<?php

$url = 'https://adan.jp.com/plese_post_request.php';
$param = array(
  'id' => 478,
  'msg' => 'フリーランスプログラマーを積極的に募集しています♪'
);
$contents_array = post_request($url, $param);

/**
 * POST送信実行
 */
function post_request($url, $param)
{
  //リクエスト時のオプション指定
  $options = array(
    'http' => array(
    'method' => 'POST', //ここでPOSTを指定
    'header' => array(
      'Content-type: application/x-www-form-urlencoded',
      'User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/13.0.1'
      ),
    'content' => http_build_query($param),
    'ignore_errors' => true,
    'protocol_version' => '1.1'
    ),
    'ssl' => array(
      'verify_peer' => false,
      'verify_peer_name' => false
      )
    );

  //リクエスト実行
  $contents = @file_get_contents($url, false, stream_context_create($options));

  //ステータスコード抜粋
  preg_match('/HTTP\/1\.[0|1|x] ([0-9]{3})/', $http_response_header[0], $matches);
    $statusCode = (int)$matches[1];

    //配列で返すためにjsonのエンコード
    $contents_array = array();
    if($statusCode === 200){
      $contents_array = json_decode($contents);
    }
    return $contents_array;
}
Content-typeに関して

Content-type: application/x-www-form-urlencoded、実際のブラウザからのフォームの送信時に、Webサーバーに送信するヘッダー情報「Content-Type」名の一つで、つけないと受けっ取ってくれないWebサーバーもあるらしく、一応つけておいたほうが無難♪

verify_peerに関して

SSLサーバー証明書の検証を要求するかどうかのフラグで、今回は要求しない

verify_peer_nameに関して

ピア名の検証を要求するかどうか。。。ピア(・・?
通信相手から受け取った相手の証明書らしい。。。この値がtrueだとオレオレ証明書使ってるサーバーへはPOSTできないっぽいです。のでfalse

テストするのはちょっと手間で、
受け取り側のプログラムを用意して、そこでPOSTリクエストを受け付けた際に、ログを出力して、そのログを「tail -f」で眺めるという確認方法が一番良いかもです。

Content-typeのトラブル回避!http_build_queryの関係性

「Content-type: application/x-www-form-urlencoded」と指定してあげているのですが、
Contet-typeを指定しない場合でも動いちゃいます。また、値を指定する際にhttp_build_query関数を使ってエンコードしていますが、こちらもなくても動いちゃいます。どちらも使わなかった場合、「Content-type: multipart/form-data」がデフォルトで通信してしまう場合があります。「multipart/form-data」はファイル転送に使うプロトコルなので、オーバヘッドが大きく処理が遅くなったり、うまくPOSTできなくなる可能性が高いので。
ちなみに、エンコードしてあげない場合、「boundary=—————————-4b52323a872f」てきなかんじなります。
ちゃんと、Content-typeを指定し、http_build_query関数でちゃっとエンコードしてあげましょう。

curl関数を使ってPOSTリクエストを実現

こんどは、Linuxのcurlコマンドを扱えるcurl関数を使って、実装してみます。file_get_contents関数はcurlをラップして作られてるっぽいですね。おそらくこっちの方が速度的に早いです。のでおすすめ♪

<?php

$url = 'https://adan.jp.com/plese_post_request.php';
$param = array(
  'id' => 478,
  'msg' => 'フリーランスプログラマーを積極的に募集しています♪'
);
$contents_array = post_request($url, $param);

function post_request($url, $param)
{

  //curlおじさんを初期化
  $ch = curl_init();
  //配列をhttp_build_queryでエンコードしてあげること
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($param));

  //上記で述べたピア問題
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

  //相手側からのデータの返り値を文字列で取得
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  //TRUE を設定すると、ヘッダの内容も出力します。
  //curl_setopt($ch, CURLOPT_HEADER, 1);

  //Content-Typeとユーザエージェントを指定
  $headers = array(
    "Content-Type: application/x-www-form-urlencoded",
    "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
  );
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

  //送信先の指定
  curl_setopt($ch, CURLOPT_URL, $url);
  //curlおじさん実行
  $response_json = curl_exec($ch);
  $result = json_decode($response_json);
  //curlおじさんを閉じる
  curl_close($ch);

}

プロに聞いてみる
株式会社adanはエンジニアのキャリアに真剣に向き合っています。
企業の情報エンジニアとしてのキャリアアップの方法、現在の待遇(給料・報酬)未経験からのステップアップ方法などのご相談を受け付けています。
お気軽にお問合せください。