Writing Appropriately

職務経歴

PHP Webページと同様のPOST送信をする

概要

元々は少しずつ値を変えながらどこかのサイトに高速で連続でPOSTして何かをしようとしていた時に出来上がった

こいつが役に立つ場面を考えてみた

  • WebページからのPOSTリクエストをテストをするのにわざわざ画面から入力しなくてもテスト…できる
  • WebページからのPOSTリクエストの処理が既に出来上がっている既存のサイトへのデータ送信
    • データを転送するだけならデータ登録処理を新規作成する手間がかからない
      (POST形式のデータを処理するロジックがすでにあるのにJson形式のデータを処理するロジックを新規作成する手間など)

メソッド

メソッド 振る舞い
initialize 初期化
set_url 送信先セット
set_boundary POSTデータのbuundaryセット
set_timeout タイムアウト設定
add_header ヘッダー追加
add_text <input type="text" .../>のデータを追加
add_keyval_array <input type="text" .../>のデータを配列で追加
add_file 添付ファイル追加
submit 送信実行
errors エラー内容を返す

使用例

$ins = new HttpFormPost();

// 送信先のアドレス設定
$ins->set_url("送信先のURL");

// フォームのnameとvalueを設定
// <input name="uname" value="yamada taro" />
// <input name="age" value="20" />
// <input name="param[]" value="param1" />
// <input name="param[]" value="param2" />
$ins->add_text("uname", "yamada taro");
$ins->add_text("age", "20");
$ins->add_text("param[]", "param1");
$ins->add_text("param[]", "param2");

// 配列からnameとvalueを設定
// <input name="fileds[pref]" value="tokyo" />
// <input name="fileds[address1]" value="bunkyo" />
$keyval = array('pref' => 'tokyo', 'address1' => 'bunkyo');
$ins->add_keyval_array("fileds", $keyval);

// 添付ファイル
$ins->add_file("upload_file[]", "ファイルパス", "$_FILESへ入る名前", "text/plain");

// ヘッダーに追加
$ins->add_header("Referer: http://you-are-uma.com");
$ins->add_header("Cookie: session_id=ii4514A-SuGu19");

// POST実行
$response = $ins->submit();

if (FALSE === $response) {
    echo "###### POST ERROR\n";
    echo implode("\n", $ins->errors()) . "\n";
}
else {
    echo "###### POST SUCCESS\n";
    echo $response;
}

Githug

github.com

ソースコードそのまま

<?php

/**
 * @author naoyuki onishi
 * @version 1.0
 */
class HttpFormPost {

    /**
    *
    * @var string
    */
    protected $_url = "";

    /**
    *
    * @var string
    */
    protected $_boundary = "";

    /**
    *
    * @var float
    */
    protected $_default_socket_timeout = "";

    /**
    *
    * @var float
    */
    protected $_socket_timeout = "";

    /**
    *
    * @var array
    */
    protected $_header_list = array();

    /**
    *
    * @var array
    */
    protected $_file_list = array();

    /**
    *
    * @var array
    */
    protected $_text_list = array();

    /**
    *
    * @var array
    */
    protected $_errors = array();


    /**
    *
    */
    public function __construct() {
        $this->initialize();
    }


    /**
    */
    public function initialize() {

        $this->_url = "";
        $this->_boundary = "---------------------" . substr(md5(rand(0, 32000)), 0, 15);
        $this->_default_socket_timeout = ini_get('default_socket_timeout');
        $this->_socket_timeout = $this->_default_socket_timeout;
        $this->_header_list = array();
        $this->_file_list = array();
        $this->_text_list = array();
        $this->_errors = array();
    }


    /**
    * @param string $url
    */
    public function set_url($url) {
        //TODO validation
        $this->_url = $url;
    }


    /**
    *
    * @param string $boundary
    */
    public function set_boundary($boundary) {
        //TODO validation
        $this->_boundary = $boundary;
    }


    /**
    *
    * @param string $socket_timeout
    */
    public function set_timeout($socket_timeout) {
        //TODO validation
        $this->_socket_timeout = $socket_timeout;
    }


    /**
    *
    * @param string $header
    */
    public function add_header($header) {

        $this->_header_list[] = $header;
    }


    /**
    *
    * @param string $form_name
    * @param string $text
    */
    public function add_text($form_name, $text) {

        $text_dict = new HttpFormPostTextDictionary();

        $text_dict->form_name = $form_name;
        $text_dict->text = $text;

        $this->_text_list[] = $text_dict;
    }


    /**
    *
    * @param string $form_name
    * @param array $keyval
    */
    public function add_keyval_array($form_name, $keyval) {

        foreach ($keyval as $key => $text) {
            $this->add_text("{$form_name}[{$key}]", $text);
        }
    }


    /**
    *
    * @param string $form_name
    * @param string $file_path
    * @param string $file_name
    * @param string $file_type
    */
    public function add_file($form_name, $file_path, $file_name = "", $file_type = "") {

        if ("" == $file_name) {
            $file_name = basename($file_path);
        }

        if ("" == $file_type) {
            $file_type = "application/octet-stream";
        }

        $file_dict = new HttpFormPostFileDictionary();

        $file_dict->form_name = $form_name;
        $file_dict->file_path = $file_path;
        $file_dict->file_name = $file_name;
        $file_dict->file_type = $file_type;

        $this->_file_list[] = $file_dict;
    }


    /**
    *
    * @return boolean string
    */
    public function submit() {


        $content = $this->_make_content();
        if (! empty($this->_errors)) {
            return FALSE;
        }

        //
        // make request
        //
        $header = $this->_header_list;
        $header[] = "Content-Type: multipart/form-data; boundary={$this->_boundary}";
        $header[] = "Content-Length: " . strlen($content);

        $stream_context_options = array(
            "http" => array(
                "method" => "POST",
                "header" => implode("\r\n", $header),
                "content" => $content,
            )
        );

        $this->_ini_set($stream_context_options);

        $stream_context = stream_context_create($stream_context_options);

        $response = FALSE;

        $fp = @fopen($this->_url, "rb", false, $stream_context);
        if ($fp) {
            $response = @stream_get_contents($fp);
        }

        if (FALSE === $response) {
            $this->_errors[] = "Problem : {$php_errormsg}";
        }

        $this->_default_ini_set();
        return $response;
    }


    /**
    *
    * @param array $stream_context_options
    */
    protected function _ini_set(& $stream_context_options) {

        // socket_timeout
        if (version_compare(phpversion(), "5.2.1", "<")) {
            ini_set('default_socket_timeout', $this->_socket_timeout);
        }
        else {
            $stream_context_options["http"]["timeout"] = $this->_socket_timeout;
        }

        // track_errors
        $this->_trac_errors = ini_get('track_errors');
        ini_set('track_errors', 1);

    }


    /**
    *
    */
    protected function _default_ini_set() {

        // socket_timeout
        if (version_compare(phpversion(), "5.2.1", "<")) {
            ini_set('default_socket_timeout', $this->_default_socket_timeout);
        }

        // track_errors
        ini_set('track_errors', $this->_trac_errors);

    }


    /**
    *
    * @return string
    */
    protected function _make_content() {

        $content = array();

        foreach ($this->_text_list as $text_dict) {
            $this->_make_content_add_text($content, $text_dict);
        }

        foreach ($this->_file_list as $file_dict) {
            $this->_make_content_add_file($content, $file_dict);
        }

        $content[] = "--{$this->_boundary}--\r\n";

        $content = implode("", $content);

        return $content;
    }


    /**
    *
    * @param array $content
    * @param HttpFormPostTextDictionary $text_dict
    */
    protected function _make_content_add_text(& $content, HttpFormPostTextDictionary $text_dict) {

        $content[] = "--{$this->_boundary}\r\n";
        $content[] = "Content-Disposition: form-data; name=\"{$text_dict->form_name}\"\r\n\r\n{$text_dict->text}\r\n";
    }


    /**
    *
    * @param array $content
    * @param HttpFormPostFileDictionary $file_dict
    */
    protected function _make_content_add_file(& $content, HttpFormPostFileDictionary $file_dict) {

        if (! is_file($file_dict->file_path)) {
            $this->_errors[] = "Attachment not found: [{$file_dict->file_path}]";
            return ;
        }

        $content[] = "--{$this->_boundary}\r\n";
        $content[] = "Content-Disposition: form-data; name=\"{$file_dict->form_name}\"; filename=\"{$file_dict->file_name}\"\r\n";
        $content[] = "Content-Type: {$file_dict->file_type}\r\n";
        $content[] = "Content-Transfer-Encoding: binary\r\n\r\n";
        $content[] = file_get_contents($file_dict->file_path) . "\r\n";
    }


    /**
    * @return array
    */
    public function errors() {

        return $this->_errors;
    }
}

/**
 * @author naoyuki onishi
 */
class HttpFormPostTextDictionary {
    public $form_name = "";
    public $text = "";
}

/**
 * @author naoyuki onishi
 */
class HttpFormPostFileDictionary {
    public $form_name = "";
    public $file_path = "";
    public $file_name = "";
    public $file_type = "";
}