curlでCURLINFOについてHEADER_SIZEのBUG位置決めと修復
curl公式ダウンロードページ
CentOS 7のデフォルトでインストールされているcurlバージョンは低すぎて、最新版にアップグレードする必要があります.
1.問題の説明
PDFファイルをダウンロードするためのインタフェースが接続されています.curlを使用してダウンロードすると、ファイルは常にエラーを報告して開くことができません.インタフェースプロバイダが直接返すPDFバイナリ・ファイル・ストリームは、フィールドに入れたりbase 64でエンコードされたりしません.
ダウンロードを担当するコードの一部は以下の通りです.
インタフェースはメッセージを返します.
要求の返信メッセージをFiddlerでシミュレートします.
2.問題の根源を探す
検索すると、PHPに記録されているこのBUGが見つかりました.エージェントを使用すると、
そして次の返事を見て、curlの質問です.問題はとっくに解決されていますが、curlを7.4以降にアップグレードする必要があります.
私の新聞は代理店を使っていません.1行も多くありませんが、curlをアップグレードしておきましょう.CentOS 7で使用されているバージョンを確認します.
CLIからprint_を呼び出すrメソッドcurlのバージョンを印刷し、PHPがこのバージョンのcurlを使用していることを確認します:
3.curlのアップグレード
curlを7.4以降にアップグレードします.ここでダウンロード:curl公式ダウンロードページ.
yumやソースコードでインストールできますが、yumを使うことをお勧めします.簡単で頼りになります.
yumによるインストール
1 yum倉庫ソースの追加
新規ファイル:
次の内容をこのファイルにコピーします.
2 yumキャッシュのクリア
キャッシュ・ディレクトリの下にあるパッケージと古いheadersをクリアします.
3インストール
4確認
5 curlに依存するすべてのソフトウェアを再起動する
ここでPHP-FPMは再起動する必要があります.
ソースコードでインストール(私は成功しませんでした)
1ダウンロード
2解凍
3上書きインストール
4.根本原因
PHPでcurlを使用する場合、このオプションがあります.
curl実行結果を取得すると、メッセージ体になります.ヘッダーとbodyを分離する必要はありません.直接使用すればいいです.コードの変更は次のとおりです.
または
とにかく、ヘッダーを必要としない場合は、 headerが必要な場合は、
CentOS 7のデフォルトでインストールされているcurlバージョンは低すぎて、最新版にアップグレードする必要があります.
1.問題の説明
PDFファイルをダウンロードするためのインタフェースが接続されています.curlを使用してダウンロードすると、ファイルは常にエラーを報告して開くことができません.インタフェースプロバイダが直接返すPDFバイナリ・ファイル・ストリームは、フィールドに入れたりbase 64でエンコードされたりしません.
ダウンロードを担当するコードの一部は以下の通りです.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->get_service_url('General'));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // (Raw)
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type:application/xml"));
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_xml);
$response = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); // ,curl BUG, 7.4 7.5
$body = substr($response, $headerSize);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
...
}
インタフェースはメッセージを返します.
HTTP/1.1 200 OK
Date: Mon, 14 May 2018 02:57:40 GMT
Server: Apache/2.4.33 (Win64) OpenSSL/1.1.0g
Content-Type: application/pdf
X-Powered-By: Servlet/2.5 JSP/2.1
Set-Cookie: JSESSIONID=HrNclQWb5KqehhTfsHl6tMAXRkdXHCuodVA3IWLnA8MbnYC2bQlJ!-2087621404; path=/; HttpOnly
Transfer-Encoding: chunked
要求の返信メッセージをFiddlerでシミュレートします.
HTTP/1.1 200 OK
Date: Mon, 14 May 2018 01:31:12 GMT
Server: Apache/2.4.33 (Win64) OpenSSL/1.1.0g
Content-Type: application/pdf
X-Powered-By: Servlet/2.5 JSP/2.1
Set-Cookie: JSESSIONID=DGRcRdwrflVjDkUKAW-kCz6JnXKuVWFhEGXk9eNtDnfd-NNfH4jO!-2087621404; path=/; HttpOnly
Content-Length: 955521
%PDF-1.4
%
2 0 obj
<3857/Filter[/ASCII85Decode/FlateDecode]>>stream
Gb!Sn9<0VQ&`-m)s'aK0)=.6O&Eq/V+M3`I$XP-a8Vd]C-@\6[V(/J@1#mTh_)NG2FAGOZI4EcO
...
2.問題の根源を探す
検索すると、PHPに記録されているこのBUGが見つかりました.エージェントを使用すると、
CURLINFO_HEADER_SIZE
フィールドに誤ったヘッダ長が得られます.エージェントを使用している場合、返されるHTTPヘッダの1行分のレコードが多くなり、ヘッダ長の計算エラーが発生します.HTTP/1.0 200 Connection established
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Date: Thu, 03 Jan 2013 15:54:35 GMT
Server: Apache/2.2.22 (Amazon)
X-Powered-By: PHP/5.3.19
Content-Length: 15
Connection: Keep-alive
そして次の返事を見て、curlの質問です.問題はとっくに解決されていますが、curlを7.4以降にアップグレードする必要があります.
私の新聞は代理店を使っていません.1行も多くありませんが、curlをアップグレードしておきましょう.CentOS 7で使用されているバージョンを確認します.
[root@VM_120_242_centos curl-7.59.0]# curl --version
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.19.1 Basic ECC zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz
CLIからprint_を呼び出すrメソッドcurlのバージョンを印刷し、PHPがこのバージョンのcurlを使用していることを確認します:
[root@VM_200_22_centos 1300_al]# php -r 'print_r( curl_version());'
Array
(
[version_number] => 466176
[age] => 3
[features] => 34493
[ssl_version_number] => 0
[version] => 7.29.0
[host] => x86_64-redhat-linux-gnu
[ssl_version] => NSS/3.19.1 Basic ECC
[libz_version] => 1.2.7
[protocols] => Array
(
[0] => dict
...
)
)
3.curlのアップグレード
curlを7.4以降にアップグレードします.ここでダウンロード:curl公式ダウンロードページ.
yumやソースコードでインストールできますが、yumを使うことをお勧めします.簡単で頼りになります.
yumによるインストール
1 yum倉庫ソースの追加
新規ファイル:
vim /etc/yum.repos.d/city-fan.repo
次の内容をこのファイルにコピーします.
[CityFan]
name=City Fan Repo
baseurl=http://www.city-fan.org/ftp/contrib/yum-repo/rhel$releasever/$basearch/
enabled=1
gpgcheck=0
2 yumキャッシュのクリア
キャッシュ・ディレクトリの下にあるパッケージと古いheadersをクリアします.
yum clean all
3インストール
yum install curl
4確認
curl --version
を再実行して、更新に成功したかどうかを確認します.[root@VM_120_242_centos soft]# curl --version
curl 7.59.0 (x86_64-redhat-linux-gnu) libcurl/7.59.0 NSS/3.28.4 zlib/1.2.7 libpsl/0.7.0 (+libicu/50.1.2) libssh2/1.8.0 nghttp2/1.31.1
Release-Date: 2018-03-14
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy PSL Metalink
5 curlに依存するすべてのソフトウェアを再起動する
ここでPHP-FPMは再起動する必要があります.
systemctl restart php-fpm
ソースコードでインストール(私は成功しませんでした)
1ダウンロード
wget https://curl.haxx.se/download/curl-7.59.0.tar.gz
2解凍
tar -xzvf curl-7.59.0.tar.gz
3上書きインストール
cd curl-7.59.0
./configure
make
make install
4.根本原因
PHPでcurlを使用する場合、このオプションがあります.
curl_setopt($ch, CURLOPT_HEADER, 1); // 。
CURLOPT_HEADER
というオプションがオンになっていない場合は、$response = curl_exec($ch);
curl実行結果を取得すると、メッセージ体になります.ヘッダーとbodyを分離する必要はありません.直接使用すればいいです.コードの変更は次のとおりです.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->get_service_url('General'));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // (Raw) 。
curl_setopt($ch, CURLOPT_HEADER, 1); // 。
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type:application/xml"));
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_xml);
$response = curl_exec($ch);
// header body
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); // size,curl 7.4 7.5
$header = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
または
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->get_service_url('General'));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // (Raw) 。
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type:application/xml"));
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_xml);
$response = curl_exec($ch);
//$response , header body
$body = $response;
とにかく、
CURLOPT_HEADER
オプションをオンにしてcurlの応答情報を直接読む必要はありません.CURLOPT_HEADER
オプションをオンにします.headerとbodyを分離する必要があります.