如何对 PHP curl (HTTPS) 使用 "fallback" 方法?
How to use "fallback" method for PHP curl (HTTPS)?
情况:我正在改进基于 PHP 的监控网络应用程序的一些代码,该应用程序检查其他网络 apps/services 的运行状况。
目标:我们使用 CURL 作为获取 headers 的主要方法,以确保可通过 HTTP [=81= 访问受监控的应用程序] 代码。 目前效果很好。但是,我们正在尝试构建一个 "fallback" 方法,如果来自受监控应用程序的 CURL HTTP 代码响应在我们定义的变量(即 http 代码 404)之外,PHP然后将使用 PING-like 函数来检查是否有 any 响应在同一地址(例如,网络服务器仍然是 "running" (占用给定端口)但是服务不正常 headers)。
问题:我们的回退方法 (stream_socket_client) 确实适用于 non-secure 站点,因为我们可以简单地定义 "hostname:port" 卷曲和stream_socket_client可以用。然而,如果我们想要监控一个安全站点 (HTTPS),curl 需要在主机之前定义 HTTPS 协议——这将使我们的回退方法 (stream_socket_client) 函数失败,因为它只使用 host:port 格式。
因此,例如:
$URL:https://example.com:443(这会变成 "GOOD" CURL 响应,但向下 stream_socket_client 响应)
$URL: example.com:443(这会 return 一个 "UP" stream_socket_client 响应,但是 "DOWN" CURL 回复)
因此,如果我们使用 https://example.com:443 作为我们的 URL,并且网络服务器变得无响应,但仍然在该端口上 运行,两者都会失败,因为定义了 HTTPs。
这是我们当前代码的简化版本:
<?php
$url = "example.com:80";
function curl($url) {
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle, CURLOPT_HEADER, true);
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($handle, CURLOPT_URL, $url);
$response = curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode >= 200 && $httpCode < 400 || $httpCode == 401 || $httpCode == 405) {
echo "CURL GOOD, $httpCode";
echo "STATUS: GREEN";
}
else {
$fp = stream_socket_client("$url", $errno, $errstr);
if (!$fp) {
echo "CURL BAD, PING DOWN";
echo "STATUS: RED";
}
else {
echo "CURL BAD PING UP";
echo "STATUS: YELLOW";
}
}
curl_close($handle);
};
?>
关于如何使用回退方法检查端口是否打开有什么想法吗?我不必坚持使用 PHP,可以使用一些 JS,但更喜欢 PHP。
编辑 1:
感谢@drew010,我知道我最终需要使用 fsockopen。但是,我需要使用 parse_url() 然后可以将 "sterile" URL 传递给 fsockopen 以进行回退 "ping" 检查。
但是,我不确定如何仅剥离协议并保留端口和子路径(如果已定义)。我也不确定如何将无菌 URL 传递给 fsockeopn 函数以用于检查。到目前为止,我有下面的代码,但我知道我遗漏了一些代码。
下面的代码将 http://example.com
解析为 example.com
。
function parseurl($url) {
$url = 'http://example.com:80';
$host = parse_url($url, PHP_URL_HOST);
//this works for stripping protocol and "wwww" but need to leave port and sub path if defined.
if (!$host)
$host = $url;
if (substr($host, 0, 4) == "www.")
$host = substr($host, 4);
if (strlen($host) > 50)
$host = substr($host, 0, 47) . '...';
return $host;
}
// How to pass steril URL to PING function??
function ping($host, $timeout = 1) {
if (!fsockopen($host, $port, $errno, $errstr, $timeout)) {
return false;
echo "OPEN";
}
else {
echo "CLOSED";
}
}
找到答案:
此脚本使用 CURL 检查给定的主机是否正在为网页提供服务。
如果不是,请使用 PING 功能检查给定端口上是否正在侦听任何内容。
<?php
* This script uses CURL to check if given HOST is serving a webpage.
* If NOT, use a PING function to check if anything is listening on given port.
//* URL MUST contain a PORT after HOST
//* URL CAN include any protocol or sub-path
// sanitizes URL to host:port:path ONLY. (if PORT, PATH don't exist, it is ignored):
function url_to_domain($url) {
$url = 'http://google.com:80';
echo "Input URL ..... $url<br />\n";
$host = parse_url($url, PHP_URL_HOST);
$port = parse_url($url, PHP_URL_PORT);
$path = parse_url($url, PHP_URL_PATH);
// If the URL can't be parsed, use the original URL
// Change to "return false" if you don't want that
if (!$host)
echo "fail";
// $host = $url;
// remove "http/s" and "www" :
if (substr($host, 0, 4) == "www.")
$host = substr($host, 4);
if (strlen($host) > 50)
$host = substr($host, 0, 47) . '...';
// contruct sanitized URL, add ":port/path" to HOST:
return $host . ":" . $port . $path;
}
// pings "sanitized" URL:
$url = (url_to_domain($url));
$fp = pfsockopen($url, $errno, $errstr, $timeout = 5);
if (!$fp) {
echo "Ping URL ...... $url <br />\n ";
echo "URL status ..... CLOSED <br />\n";
echo "Error ............... $errstr ($errno)<br />\n";
}
else {
// $out = "GET / HTTP/1.1\r\n";
// $out .= "$url\r\n";
// $out .= "Connection: Close\r\n\r\n";
//fwrite ($fp, $out);
//displays header:
/*
while (!feof($fp)) {
echo fgets($fp, 128);
}
*/
// fclose($fp);
echo "Ping URL ...... $url <br />\n ";
echo "URL status .... OPEN";
}
?>
情况:我正在改进基于 PHP 的监控网络应用程序的一些代码,该应用程序检查其他网络 apps/services 的运行状况。
目标:我们使用 CURL 作为获取 headers 的主要方法,以确保可通过 HTTP [=81= 访问受监控的应用程序] 代码。 目前效果很好。但是,我们正在尝试构建一个 "fallback" 方法,如果来自受监控应用程序的 CURL HTTP 代码响应在我们定义的变量(即 http 代码 404)之外,PHP然后将使用 PING-like 函数来检查是否有 any 响应在同一地址(例如,网络服务器仍然是 "running" (占用给定端口)但是服务不正常 headers)。
问题:我们的回退方法 (stream_socket_client) 确实适用于 non-secure 站点,因为我们可以简单地定义 "hostname:port" 卷曲和stream_socket_client可以用。然而,如果我们想要监控一个安全站点 (HTTPS),curl 需要在主机之前定义 HTTPS 协议——这将使我们的回退方法 (stream_socket_client) 函数失败,因为它只使用 host:port 格式。
因此,例如:
$URL:https://example.com:443(这会变成 "GOOD" CURL 响应,但向下 stream_socket_client 响应)
$URL: example.com:443(这会 return 一个 "UP" stream_socket_client 响应,但是 "DOWN" CURL 回复)
因此,如果我们使用 https://example.com:443 作为我们的 URL,并且网络服务器变得无响应,但仍然在该端口上 运行,两者都会失败,因为定义了 HTTPs。
这是我们当前代码的简化版本:
<?php
$url = "example.com:80";
function curl($url) {
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle, CURLOPT_HEADER, true);
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($handle, CURLOPT_URL, $url);
$response = curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode >= 200 && $httpCode < 400 || $httpCode == 401 || $httpCode == 405) {
echo "CURL GOOD, $httpCode";
echo "STATUS: GREEN";
}
else {
$fp = stream_socket_client("$url", $errno, $errstr);
if (!$fp) {
echo "CURL BAD, PING DOWN";
echo "STATUS: RED";
}
else {
echo "CURL BAD PING UP";
echo "STATUS: YELLOW";
}
}
curl_close($handle);
};
?>
关于如何使用回退方法检查端口是否打开有什么想法吗?我不必坚持使用 PHP,可以使用一些 JS,但更喜欢 PHP。
编辑 1:
感谢@drew010,我知道我最终需要使用 fsockopen。但是,我需要使用 parse_url() 然后可以将 "sterile" URL 传递给 fsockopen 以进行回退 "ping" 检查。
但是,我不确定如何仅剥离协议并保留端口和子路径(如果已定义)。我也不确定如何将无菌 URL 传递给 fsockeopn 函数以用于检查。到目前为止,我有下面的代码,但我知道我遗漏了一些代码。
下面的代码将 http://example.com
解析为 example.com
。
function parseurl($url) {
$url = 'http://example.com:80';
$host = parse_url($url, PHP_URL_HOST);
//this works for stripping protocol and "wwww" but need to leave port and sub path if defined.
if (!$host)
$host = $url;
if (substr($host, 0, 4) == "www.")
$host = substr($host, 4);
if (strlen($host) > 50)
$host = substr($host, 0, 47) . '...';
return $host;
}
// How to pass steril URL to PING function??
function ping($host, $timeout = 1) {
if (!fsockopen($host, $port, $errno, $errstr, $timeout)) {
return false;
echo "OPEN";
}
else {
echo "CLOSED";
}
}
找到答案:
此脚本使用 CURL 检查给定的主机是否正在为网页提供服务。 如果不是,请使用 PING 功能检查给定端口上是否正在侦听任何内容。
<?php
* This script uses CURL to check if given HOST is serving a webpage.
* If NOT, use a PING function to check if anything is listening on given port.
//* URL MUST contain a PORT after HOST
//* URL CAN include any protocol or sub-path
// sanitizes URL to host:port:path ONLY. (if PORT, PATH don't exist, it is ignored):
function url_to_domain($url) {
$url = 'http://google.com:80';
echo "Input URL ..... $url<br />\n";
$host = parse_url($url, PHP_URL_HOST);
$port = parse_url($url, PHP_URL_PORT);
$path = parse_url($url, PHP_URL_PATH);
// If the URL can't be parsed, use the original URL
// Change to "return false" if you don't want that
if (!$host)
echo "fail";
// $host = $url;
// remove "http/s" and "www" :
if (substr($host, 0, 4) == "www.")
$host = substr($host, 4);
if (strlen($host) > 50)
$host = substr($host, 0, 47) . '...';
// contruct sanitized URL, add ":port/path" to HOST:
return $host . ":" . $port . $path;
}
// pings "sanitized" URL:
$url = (url_to_domain($url));
$fp = pfsockopen($url, $errno, $errstr, $timeout = 5);
if (!$fp) {
echo "Ping URL ...... $url <br />\n ";
echo "URL status ..... CLOSED <br />\n";
echo "Error ............... $errstr ($errno)<br />\n";
}
else {
// $out = "GET / HTTP/1.1\r\n";
// $out .= "$url\r\n";
// $out .= "Connection: Close\r\n\r\n";
//fwrite ($fp, $out);
//displays header:
/*
while (!feof($fp)) {
echo fgets($fp, 128);
}
*/
// fclose($fp);
echo "Ping URL ...... $url <br />\n ";
echo "URL status .... OPEN";
}
?>