如何使用"fallback"方法进行PHP curl (HTTPS)?



情况:我正在改进基于 PHP 的监控 Web 应用程序上的一些代码,该应用程序检查其他 Web 应用程序/服务的运行状况。

目标:我们使用 CURL 作为获取标头的主要方法,以确保可以通过 HTTP 返回代码访问受监视的应用。到目前为止,这很好用。 但是,我们正在尝试构建一个"回退"方法,其中如果来自受监控应用程序的 CURL HTTP 代码响应在我们定义的变量(即 http 代码 404)之外,PHP 将使用类似 PING 的函数来检查在同一地址是否有任何响应(例如,Web 服务器仍在"运行"(占用给定端口)但没有提供正确的标头)。

问题:我们的回退方法(stream_socket_client)确实适用于非安全站点,因为我们可以简单地定义curl和stream_socket_client都可以使用的"hostname:port"。 但是,如果我们想监视安全站点(HTTPS),curl 需要在主机之前定义 HTTPS 协议 - 这将使我们的回退方法 (stream_socket_client) 函数失败,因为它只使用 host:port 格式。

因此,例如:

$URL:https://example.com:443(这将变成"好"的 CURL 响应,但会变成向下stream_socket_client响应)

$URL:example.com:443(这将返回"UP"stream_socket_client响应,但返回"DOWN"卷曲响应)

因此,如果我们使用 https://example.com:443 作为我们的 URL,并且 Web 服务器变得无响应,但仍在该端口上运行,则两者都会失败,因为定义了 HTTP。

这是我们当前代码的简化版本:

<?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(),然后它可以将"无菌"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.1rn";
// $out .= "$urlrn";
// $out .= "Connection: Closernrn";
//fwrite ($fp, $out);
//displays header: 
/*    
while (!feof($fp)) {
echo fgets($fp, 128);
} 
*/
// fclose($fp);
echo "Ping URL ...... $url <br />n  ";
echo "URL status .... OPEN";
}

?> 

最新更新