如何对 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";

    }


 ?>