httpsで某サイトの情報を取得する必要があり、phpで単純なssl_clientを作成。
Githubのどこかを参考にしたのだが忘れてしまった。(誰か気がついたら教えて)
で、PHPがOpenSSLサポートが有効なようにコンパイルされていることが前提で、fsockopenでstreamを開き、stream_get_meta_dataで読み込む。
<?php
/**
* ssl_client.php
*/
class ssl_client
{
protected $options = [];
public function __construct()
{
ini_set("allow_url_fopen", 1);
$this->options = [
'http' => [
'method' => 'GET',
'timeout' => 10, //タイムアウト秒
'ignore_errors' => true, //ステータスコードが4xxや5xxなど失敗の場合でもコンテンツを取得
],
];
}
public function wget($url, $param = array())
{
$timeout = 30;
$method = count($param) ? 'POST' : 'GET'; // $param要素あればPOST
if (!$purl = parse_url($url)) {
return array('', '');
}
//print_r($purl);
// URL分解
if (empty($purl['port'])) {
$purl['port'] = 80;
}
$ssl = '';
if ($purl['scheme'] == 'https') {
$ssl = 'ssl://';
if ($purl['port'] == 80) {
$purl['port'] = 443;
}
}
// HTTPリクエスト
$fp = fsockopen($ssl . $purl['host'], $purl['port'], $errno, $errstr, $timeout);
if (!$fp) {
die("$errstr ($errno)<br />\n");
}
if (!empty($purl['query'])) {
$purl['path'] .= "?{$purl['query']}";
}
if (substr($purl['path'], 0, 1) !== '/') {
$purl['path'] = '/' . $purl['path'];
}
$data = $method === 'POST' ? http_build_query($param, '', '&') : '';
$cl = empty($data) ? '' : "Content-Length: " . strlen($data) . "\r\n";
$out = "$method {$purl['path']} HTTP/1.1\r\n"
. "Host: {$purl['host']}\r\n"
. "User-Agent: PHP-Script/1.0\r\n"
. "Content-Type: application/x-www-form-urlencoded\r\n"
. $cl
. "Connection: Close\r\n\r\n"
. $data;
fwrite($fp, $out);
// HTTPレスポンス取得
stream_set_timeout($fp, $timeout);
$header = $html = '';
$html_arr = [];
while (!feof($fp)) {
$info = stream_get_meta_data($fp);
if ($info['timed_out']) {
die("timeout!");
}
if (empty($html)
&& substr($header, -4) !== "\x0d\x0a\x0d\x0a"
&& $header .= fgets($fp)) {
continue;
}
$line = fgets($fp);
if (preg_match("/^0000[0-9A-F]{4}[\r\n]*$/", $line)) {
continue;
}
$html .= $line;
$html_arr[] = $line;
}
fclose($fp);
return array($header, $html, $html_arr);
}
}
ちょいちょい 0000ABCDのような行が紛れ込むのでそいつを削除してる、ってのと、HTML全文とは別に行ごとの配列も返してるあたりがいぢってあるところ。
別にたいしたことをしているわけでもなく、元があったのをいぢっただけなのだが、時々忘れてまた探すのが面倒なので書いておく。