Piwik\Http::sendHttpRequestBy PHP Method

sendHttpRequestBy() public static method

Sends an HTTP request using the specified transport method.
public static sendHttpRequestBy ( string $method = 'socket', string $aUrl, integer $timeout, string $userAgent = null, string $destinationPath = null, resource $file = null, integer $followDepth, boolean | string $acceptLanguage = false, boolean $acceptInvalidSslCertificate = false, array | boolean $byteRange = false, boolean $getExtendedInfo = false, string $httpMethod = 'GET', string $httpUsername = null, string $httpPassword = null, array | string $requestBody = null ) : boolean
$method string
$aUrl string
$timeout integer in seconds
$userAgent string
$destinationPath string
$file resource
$followDepth integer
$acceptLanguage boolean | string Accept-language header
$acceptInvalidSslCertificate boolean Only used with $method == 'curl'. If set to true (NOT recommended!) the SSL certificate will not be checked
$byteRange array | boolean For Range: header. Should be two element array of bytes, eg, array(0, 1024) Doesn't work w/ fopen method.
$getExtendedInfo boolean True to return status code, headers & response, false if just response.
$httpMethod string The HTTP method to use. Defaults to `'GET'`.
$httpUsername string HTTP Auth username
$httpPassword string HTTP Auth password
$requestBody array | string If $httpMethod is 'POST' this may accept an array of variables or a string that needs to be posted
return boolean true (or string/array) on success; false on HTTP response error code (1xx or 4xx)
    public static function sendHttpRequestBy($method = 'socket', $aUrl, $timeout, $userAgent = null, $destinationPath = null, $file = null, $followDepth = 0, $acceptLanguage = false, $acceptInvalidSslCertificate = false, $byteRange = false, $getExtendedInfo = false, $httpMethod = 'GET', $httpUsername = null, $httpPassword = null, $requestBody = null)
    {
        if ($followDepth > 5) {
            throw new Exception('Too many redirects (' . $followDepth . ')');
        }
        $contentLength = 0;
        $fileLength = 0;
        if (!empty($requestBody) && is_array($requestBody)) {
            $requestBody = http_build_query($requestBody);
        }
        // Piwik services behave like a proxy, so we should act like one.
        $xff = 'X-Forwarded-For: ' . (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] . ',' : '') . IP::getIpFromHeader();
        if (empty($userAgent)) {
            $userAgent = self::getUserAgent();
        }
        $via = 'Via: ' . (isset($_SERVER['HTTP_VIA']) && !empty($_SERVER['HTTP_VIA']) ? $_SERVER['HTTP_VIA'] . ', ' : '') . Version::VERSION . ' ' . ($userAgent ? " ({$userAgent})" : '');
        // range header
        $rangeHeader = '';
        if (!empty($byteRange)) {
            $rangeHeader = 'Range: bytes=' . $byteRange[0] . '-' . $byteRange[1] . "\r\n";
        }
        list($proxyHost, $proxyPort, $proxyUser, $proxyPassword) = self::getProxyConfiguration($aUrl);
        $aUrl = trim($aUrl);
        // other result data
        $status = null;
        $headers = array();
        $httpAuthIsUsed = !empty($httpUsername) || !empty($httpPassword);
        if ($method == 'socket') {
            if (!self::isSocketEnabled()) {
                // can be triggered in tests
                throw new Exception("HTTP socket support is not enabled (php function fsockopen is not available) ");
            }
            // initialization
            $url = @parse_url($aUrl);
            if ($url === false || !isset($url['scheme'])) {
                throw new Exception('Malformed URL: ' . $aUrl);
            }
            if ($url['scheme'] != 'http' && $url['scheme'] != 'https') {
                throw new Exception('Invalid protocol/scheme: ' . $url['scheme']);
            }
            $host = $url['host'];
            $port = isset($url['port']) ? $url['port'] : 80;
            $path = isset($url['path']) ? $url['path'] : '/';
            if (isset($url['query'])) {
                $path .= '?' . $url['query'];
            }
            $errno = null;
            $errstr = null;
            if (!empty($proxyHost) && !empty($proxyPort) || !empty($byteRange)) {
                $httpVer = '1.1';
            } else {
                $httpVer = '1.0';
            }
            $proxyAuth = null;
            if (!empty($proxyHost) && !empty($proxyPort)) {
                $connectHost = $proxyHost;
                $connectPort = $proxyPort;
                if (!empty($proxyUser) && !empty($proxyPassword)) {
                    $proxyAuth = 'Proxy-Authorization: Basic ' . base64_encode("{$proxyUser}:{$proxyPassword}") . "\r\n";
                }
                $requestHeader = "{$httpMethod} {$aUrl} HTTP/{$httpVer}\r\n";
            } else {
                $connectHost = $host;
                $connectPort = $port;
                $requestHeader = "{$httpMethod} {$path} HTTP/{$httpVer}\r\n";
            }
            // connection attempt
            if (($fsock = @fsockopen($connectHost, $connectPort, $errno, $errstr, $timeout)) === false || !is_resource($fsock)) {
                if (is_resource($file)) {
                    @fclose($file);
                }
                throw new Exception("Error while connecting to: {$host}. Please try again later. {$errstr}");
            }
            $httpAuth = '';
            if ($httpAuthIsUsed) {
                $httpAuth = 'Authorization: Basic ' . base64_encode($httpUsername . ':' . $httpPassword) . "\r\n";
            }
            // send HTTP request header
            $requestHeader .= "Host: {$host}" . ($port != 80 ? ':' . $port : '') . "\r\n" . ($httpAuth ? $httpAuth : '') . ($proxyAuth ? $proxyAuth : '') . 'User-Agent: ' . $userAgent . "\r\n" . ($acceptLanguage ? $acceptLanguage . "\r\n" : '') . $xff . "\r\n" . $via . "\r\n" . $rangeHeader . "Connection: close\r\n";
            fwrite($fsock, $requestHeader);
            if (strtolower($httpMethod) === 'post' && !empty($requestBody)) {
                fwrite($fsock, self::buildHeadersForPost($requestBody));
                fwrite($fsock, "\r\n");
                fwrite($fsock, $requestBody);
            } else {
                fwrite($fsock, "\r\n");
            }
            $streamMetaData = array('timed_out' => false);
            @stream_set_blocking($fsock, true);
            if (function_exists('stream_set_timeout')) {
                @stream_set_timeout($fsock, $timeout);
            } elseif (function_exists('socket_set_timeout')) {
                @socket_set_timeout($fsock, $timeout);
            }
            // process header
            $status = null;
            while (!feof($fsock)) {
                $line = fgets($fsock, 4096);
                $streamMetaData = @stream_get_meta_data($fsock);
                if ($streamMetaData['timed_out']) {
                    if (is_resource($file)) {
                        @fclose($file);
                    }
                    @fclose($fsock);
                    throw new Exception('Timed out waiting for server response');
                }
                // a blank line marks the end of the server response header
                if (rtrim($line, "\r\n") == '') {
                    break;
                }
                // parse first line of server response header
                if (!$status) {
                    // expect first line to be HTTP response status line, e.g., HTTP/1.1 200 OK
                    if (!preg_match('~^HTTP/(\\d\\.\\d)\\s+(\\d+)(\\s*.*)?~', $line, $m)) {
                        if (is_resource($file)) {
                            @fclose($file);
                        }
                        @fclose($fsock);
                        throw new Exception('Expected server response code.  Got ' . rtrim($line, "\r\n"));
                    }
                    $status = (int) $m[2];
                    // Informational 1xx or Client Error 4xx
                    if ($status < 200 || $status >= 400) {
                        if (is_resource($file)) {
                            @fclose($file);
                        }
                        @fclose($fsock);
                        if (!$getExtendedInfo) {
                            return false;
                        } else {
                            return array('status' => $status);
                        }
                    }
                    continue;
                }
                // handle redirect
                if (preg_match('/^Location:\\s*(.+)/', rtrim($line, "\r\n"), $m)) {
                    if (is_resource($file)) {
                        @fclose($file);
                    }
                    @fclose($fsock);
                    // Successful 2xx vs Redirect 3xx
                    if ($status < 300) {
                        throw new Exception('Unexpected redirect to Location: ' . rtrim($line) . ' for status code ' . $status);
                    }
                    return self::sendHttpRequestBy($method, trim($m[1]), $timeout, $userAgent, $destinationPath, $file, $followDepth + 1, $acceptLanguage, $acceptInvalidSslCertificate = false, $byteRange, $getExtendedInfo, $httpMethod, $httpUsername, $httpPassword);
                }
                // save expected content length for later verification
                if (preg_match('/^Content-Length:\\s*(\\d+)/', $line, $m)) {
                    $contentLength = (int) $m[1];
                }
                self::parseHeaderLine($headers, $line);
            }
            if (feof($fsock) && $httpMethod != 'HEAD') {
                throw new Exception('Unexpected end of transmission');
            }
            // process content/body
            $response = '';
            while (!feof($fsock)) {
                $line = fread($fsock, 8192);
                $streamMetaData = @stream_get_meta_data($fsock);
                if ($streamMetaData['timed_out']) {
                    if (is_resource($file)) {
                        @fclose($file);
                    }
                    @fclose($fsock);
                    throw new Exception('Timed out waiting for server response');
                }
                $fileLength += strlen($line);
                if (is_resource($file)) {
                    // save to file
                    fwrite($file, $line);
                } else {
                    // concatenate to response string
                    $response .= $line;
                }
            }
            // determine success or failure
            @fclose(@$fsock);
        } elseif ($method == 'fopen') {
            $response = false;
            // we make sure the request takes less than a few seconds to fail
            // we create a stream_context (works in php >= 5.2.1)
            // we also set the socket_timeout (for php < 5.2.1)
            $default_socket_timeout = @ini_get('default_socket_timeout');
            @ini_set('default_socket_timeout', $timeout);
            $httpAuth = '';
            if ($httpAuthIsUsed) {
                $httpAuth = 'Authorization: Basic ' . base64_encode($httpUsername . ':' . $httpPassword) . "\r\n";
            }
            $ctx = null;
            if (function_exists('stream_context_create')) {
                $stream_options = array('http' => array('header' => 'User-Agent: ' . $userAgent . "\r\n" . ($httpAuth ? $httpAuth : '') . ($acceptLanguage ? $acceptLanguage . "\r\n" : '') . $xff . "\r\n" . $via . "\r\n" . $rangeHeader, 'max_redirects' => 5, 'timeout' => $timeout));
                if (!empty($proxyHost) && !empty($proxyPort)) {
                    $stream_options['http']['proxy'] = 'tcp://' . $proxyHost . ':' . $proxyPort;
                    $stream_options['http']['request_fulluri'] = true;
                    // required by squid proxy
                    if (!empty($proxyUser) && !empty($proxyPassword)) {
                        $stream_options['http']['header'] .= 'Proxy-Authorization: Basic ' . base64_encode("{$proxyUser}:{$proxyPassword}") . "\r\n";
                    }
                }
                if (strtolower($httpMethod) === 'post' && !empty($requestBody)) {
                    $postHeader = self::buildHeadersForPost($requestBody);
                    $postHeader .= "\r\n";
                    $stream_options['http']['method'] = 'POST';
                    $stream_options['http']['header'] .= $postHeader;
                    $stream_options['http']['content'] = $requestBody;
                }
                $ctx = stream_context_create($stream_options);
            }
            // save to file
            if (is_resource($file)) {
                if (!($handle = fopen($aUrl, 'rb', false, $ctx))) {
                    throw new Exception("Unable to open {$aUrl}");
                }
                while (!feof($handle)) {
                    $response = fread($handle, 8192);
                    $fileLength += strlen($response);
                    fwrite($file, $response);
                }
                fclose($handle);
            } else {
                $response = @file_get_contents($aUrl, 0, $ctx);
                // try to get http status code from response headers
                if (isset($http_response_header) && preg_match('~^HTTP/(\\d\\.\\d)\\s+(\\d+)(\\s*.*)?~', implode("\n", $http_response_header), $m)) {
                    $status = (int) $m[2];
                }
                if (!$status && $response === false) {
                    $error = error_get_last();
                    throw new \Exception($error['message']);
                }
                $fileLength = strlen($response);
            }
            // restore the socket_timeout value
            if (!empty($default_socket_timeout)) {
                @ini_set('default_socket_timeout', $default_socket_timeout);
            }
        } elseif ($method == 'curl') {
            if (!self::isCurlEnabled()) {
                // can be triggered in tests
                throw new Exception("CURL is not enabled in php.ini, but is being used.");
            }
            $ch = @curl_init();
            if (!empty($proxyHost) && !empty($proxyPort)) {
                @curl_setopt($ch, CURLOPT_PROXY, $proxyHost . ':' . $proxyPort);
                if (!empty($proxyUser) && !empty($proxyPassword)) {
                    // PROXYAUTH defaults to BASIC
                    @curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyUser . ':' . $proxyPassword);
                }
            }
            $curl_options = array(CURLOPT_BINARYTRANSFER => is_resource($file), CURLOPT_URL => $aUrl, CURLOPT_USERAGENT => $userAgent, CURLOPT_HTTPHEADER => array($xff, $via, $rangeHeader, $acceptLanguage), CURLOPT_HEADER => is_resource($file) ? false : true, CURLOPT_CONNECTTIMEOUT => $timeout, CURLOPT_TIMEOUT => $timeout);
            // Case core:archive command is triggering archiving on https:// and the certificate is not valid
            if ($acceptInvalidSslCertificate) {
                $curl_options += array(CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false);
            }
            @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $httpMethod);
            if ($httpMethod == 'HEAD') {
                @curl_setopt($ch, CURLOPT_NOBODY, true);
            }
            if (strtolower($httpMethod) === 'post' && !empty($requestBody)) {
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
            }
            if (!empty($httpUsername) && !empty($httpPassword)) {
                $curl_options += array(CURLOPT_USERPWD => $httpUsername . ':' . $httpPassword);
            }
            @curl_setopt_array($ch, $curl_options);
            self::configCurlCertificate($ch);
            /*
             * as of php 5.2.0, CURLOPT_FOLLOWLOCATION can't be set if
             * in safe_mode or open_basedir is set
             */
            if ((string) ini_get('safe_mode') == '' && ini_get('open_basedir') == '') {
                $curl_options = array(CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 5);
                @curl_setopt_array($ch, $curl_options);
            }
            if (is_resource($file)) {
                // write output directly to file
                @curl_setopt($ch, CURLOPT_FILE, $file);
            } else {
                // internal to ext/curl
                @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            }
            ob_start();
            $response = @curl_exec($ch);
            ob_end_clean();
            if ($response === true) {
                $response = '';
            } elseif ($response === false) {
                $errstr = curl_error($ch);
                if ($errstr != '') {
                    throw new Exception('curl_exec: ' . $errstr . '. Hostname requested was: ' . UrlHelper::getHostFromUrl($aUrl));
                }
                $response = '';
            } else {
                $header = '';
                // redirects are included in the output html, so we look for the last line that starts w/ HTTP/...
                // to split the response
                while (substr($response, 0, 5) == "HTTP/") {
                    $split = explode("\r\n\r\n", $response, 2);
                    if (count($split) == 2) {
                        list($header, $response) = $split;
                    } else {
                        $response = '';
                        $header = $split;
                    }
                }
                foreach (explode("\r\n", $header) as $line) {
                    self::parseHeaderLine($headers, $line);
                }
            }
            $contentLength = @curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
            $fileLength = is_resource($file) ? @curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD) : strlen($response);
            $status = @curl_getinfo($ch, CURLINFO_HTTP_CODE);
            @curl_close($ch);
            unset($ch);
        } else {
            throw new Exception('Invalid request method: ' . $method);
        }
        if (is_resource($file)) {
            fflush($file);
            @fclose($file);
            $fileSize = filesize($destinationPath);
            if ($contentLength > 0 && $fileLength != $contentLength || $fileSize != $fileLength) {
                throw new Exception('File size error: ' . $destinationPath . '; expected ' . $contentLength . ' bytes; received ' . $fileLength . ' bytes; saved ' . $fileSize . ' bytes to file');
            }
            return true;
        }
        if (!$getExtendedInfo) {
            return trim($response);
        } else {
            return array('status' => $status, 'headers' => $headers, 'data' => $response);
        }
    }

Usage Example

 public function sendSMS($apiKey, $smsText, $phoneNumber, $from)
 {
     $account = explode(" ", $apiKey);
     $parameters = array('user' => $account[0], 'pass' => $account[1], 'msg' => $smsText);
     $url = self::API_URL . '?' . http_build_query($parameters, '', '&');
     $timeout = self::SOCKET_TIMEOUT;
     $result = Http::sendHttpRequestBy(Http::getTransportMethod(), $url, $timeout, $getExtendedInfo = true);
 }
All Usage Examples Of Piwik\Http::sendHttpRequestBy