中小企業に勤めるITエンジニアの徒然日記

中小企業に勤めるITエンジニア(三十路女子)が日々のよしなしごとや、IT技術についての記事をつらつらと書いていきます。

PHP

httpsで用意されているAPIにアクセスしてJSON形式の情報を取得するプログラムをPHPで書いたのですが、file_get_contents($url)をすると

PHP Warning: file_get_contents(): SSL: Connection reset by peer

というエラーが出ました。


現象を調査したところ、
・curlで対象のAPIを呼び出すことはできる
・file_get_contents()で呼び出すことができるhttpsサイトと、エラーが出ないhttpsサイトがある
ことがわかりました。


サイトによって違う、ということは証明書関連か?と思い、呼び出せるサイトと呼び出せないサイトを比べて見ました。


・呼び出せるサイト

01

・エラーになるサイト
58


TLSのバージョンが違う、、、
51

犯人はこれか?と思いググるとありました。

PHP 5.6.x における OpenSSL 関連の変更


「Connection reset by peer」というエラーメッセージを見るに、おそらくここがヒットしているのではないでしょうか。」

ストリームラッパーが、SSL/TLS を使っている場合のピア証明書とホスト名の検証にデフォルトで対応

暗号化されたすべてのクライアントストリームで、ピア検証がデフォルトで有効になりました。 デフォルトでは、OpenSSL のデフォルト CA バンドルを使ってピア証明書を検証します。 たいていの場合は、正しい SSL 証明書を持つサーバーと通信するならこれを変更する必要はありません。 OpenSSL が、よく知られた CA バンドルを使うように設定されているからです。

デフォルトの CA バンドルを上書きすることもできます。 openssl.cafile あるいは openssl.capath を設定すればグローバルに変更でき、コンテキストオプション cafile あるいは capath を使えばリクエスト単位で変更できます。

一般的にはおすすめできませんが、 コンテキストオプション verify_peerFALSE にしてリクエストでのピア証明書の検証を無効化することもできます。 また同じく、ピア名の検証も、コンテキストオプション verify_peer_nameFALSE にすれば無効化できます。


上記のとおり、verify_peerを無効にしてればよいのかもしれませんが、以下のようにTLS1.0を使用する旨を設定してやれば正常に取得できるようになりました。
$ctx = stream_context_create([
    'ssl' => [
        'crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
    ],
]);
$html = file_get_contents('https://example.com/', false, $ctx);
このエントリーをはてなブックマークに追加

仕事でPHPで作られたあるWebのパッケージソフトウェアを使うことになりました。

一般的にパッケージって、汎用的に機能が作られていて、拡張しやすく、盛りだくさんに作られているので、専用のソフトウェアよりも遅いと思うのですが、このパッケージも同じく遅い。。


画面遷移をするのに毎回2〜3秒かかってしまいます。

いろいろと検証した結果、単純に処理量が多くてCPUがボトルネックになってる模様。


PHP5.6を使っていたので、処理速度が2倍以上になると言われているPHP7.0にアップグレードすることも考えたのですが、OPcacheを使うのが効果的という情報を見つけて早速試してみました。


PHPはインタプリタなので実行時に1行ずつ解析してオペコードに変換されますが、OPcacheはこのオペコードを最適化してキャッシュする代物です。


適用した結果、毎回2〜3秒かかっていた画面遷移が1秒弱でサクサク動くようになりました。


すごい!!

http://php.net/manual/ja/book.opcache.php

↑導入方法等

かなり効果があるので全体的に遅い場合は適用してはどうでしょうか。というかデフォルトでOPcacheを適用していてもいいと思う。

デメリットとしてはプログラムを修正した場合の反映にタイムラグができてしまう、というところでしょうか。

これもopcache_resetなどの関数を呼び出すプログラムを用意しておいて、プログラム修正後はそのプログラムを叩いて強制的に反映させる、という手もありますし、自動反映させる設定もphp.iniで変更できるのでキャッシュされることがわかっていればいくらでも何とでもなりそうです。

このエントリーをはてなブックマークに追加

動作環境:CentOS7.2, PHP7.0

PHP5.4から「ビルトインウェブサーバー」という機能が標準装備されています。


一言で表現すると、「開発支援用のしょぼいWebサーバ」です。

ポート8888で、/var/wwwをドキュメントルートとしてWebサーバを動作させたい場合は、以下のコマンドで起動させます。
[user@testserver]$ /usr/bin/php -S localhost:8888 -t /var/www
localhostだと外部にlistenされない

[user@testserver]$ ss -an | grep 8080
tcp    LISTEN     0      128    127.0.0.1:8080                  *:*            

自マシン以外からアクセスさせたい場合はlocalhostの部分はIPアドレスにする必要があります。

[user@testserver]$ /usr/bin/php -S {ipaddress}:8888 -t /var/www
外部にlistenされていることがわかります。
[user@testserver]$ ss -an | grep 8080
tcp    LISTEN     0      128    {ipaddress}:8080                  *:*            

このエントリーをはてなブックマークに追加

PHP7.0がリリースされてから10か月以上経ちました。
PHP5.5も2016年6月にサポート対象外となり、5.6もあと1年を切りました。

というわけでいま新規でPHP環境を構築するならPHP7.0です。

CentOS7.2にPHP7.0をインストールしてみました。

リポジトリの追加
sudo rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/7/x86_64/e/epel-release-7-8.noarch.rpm

sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

PHP7.0のインストール
sudo yum install --enablerepo=remi,remi-php70 php php-devel


以上、かんたんですね。
このエントリーをはてなブックマークに追加



HTMLのフォームから送られたパラメータをサーバ側のPHPで取得するときは、
$get_param = $_GET['param'];
echo $get_param;

$post_param = $_POST['param'];
echo $post_param

のように$_GET, $_POSTを使えば取得することができます。


ではHTTPリクエストをそのまま表示したい場合はどうなるか?

php://を使います。

$http_req_body = file_get_contents('php://input');

echo $http_req_body; // HTTPリクエストのボディ部が表示される



参考:http://php.net/manual/ja/wrappers.php.php


このエントリーをはてなブックマークに追加

↑このページのトップヘ