You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
information-system/splunk/Splunk/Http.php

233 lines
8.1 KiB
PHP

<?php
/**
* Copyright 2013 Splunk, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"): you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* HTTP abstraction layer.
*
* @package Splunk
* @internal
*/
class Splunk_Http
{
/**
* @param array $params (optional) query parameters.
* @see request()
*/
public function get($url, $params=array(), $requestHeaders=array())
{
return $this->requestWithParams('get', $url, $params, $requestHeaders);
}
/**
* @param array $params (optional) form parameters to send in the request body.
* @see request()
*/
public function post($url, $params=array(), $requestHeaders=array())
{
$requestHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
return $this->request(
'post', $url, $requestHeaders, http_build_query($params));
}
/**
* @param array $params (optional) query parameters.
* @see request()
*/
public function delete($url, $params=array(), $requestHeaders=array())
{
return $this->requestWithParams('delete', $url, $params, $requestHeaders);
}
private function requestWithParams(
$method, $url, $params, $requestHeaders)
{
$fullUrl = ($params === NULL || count($params) == 0)
? $url
: $url . '?' . http_build_query($params);
return $this->request($method, $fullUrl, $requestHeaders);
}
/**
* Sends an HTTP request and returns the response.
*
* @param string $method HTTP request method (ex: 'get').
* @param string $url URL to fetch.
* @param array $requestHeaders (optional) dictionary of header names and values.
* @param string $requestBody (optional) content to send in the request.
* @return Splunk_HttpResponse
* @throws Splunk_IOException
*/
public function request(
$method, $url, $requestHeaders=array(), $requestBody='')
{
$isHttp = (substr($url, 0, strlen('http:')) === 'http:');
$isHttps = (substr($url, 0, strlen('https:')) === 'https:');
if (!$isHttp && !$isHttps)
{
throw new InvalidArgumentException(
'URL scheme must be either HTTP or HTTPS.');
}
// The HTTP stream wrapper in PHP < 5.3.7 has a bug which
// injects junk at the end of HTTP requests, which breaks
// SSL connections. Fallback to cURL-based requests.
if ($isHttps && (version_compare(PHP_VERSION, '5.3.7') < 0))
return $this->requestWithCurl(
$method, $url, $requestHeaders, $requestBody);
$requestHeaderLines = array();
foreach ($requestHeaders as $k => $v)
$requestHeaderLines[] = "{$k}: {$v}";
$fopenContext = stream_context_create(array(
'http' => array(
'method' => strtoupper($method),
'header' => $requestHeaderLines,
'content' => $requestBody,
'follow_location' => 0, // don't follow HTTP 3xx automatically
'max_redirects' => 0, // [PHP 5.2] don't follow HTTP 3xx automatically
'ignore_errors' => TRUE, // don't throw exceptions on bad status codes
),
// LMR FIX!!!!!!
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true,
'verify_peer_name' => false,
),
));
// NOTE: PHP does not perform certificate validation for HTTPS URLs.
// NOTE: fopen() magically sets the $http_response_header local variable.
$bodyStream = @fopen($url, 'rb', /*use_include_path=*/FALSE, $fopenContext);
if ($bodyStream === FALSE)
{
$errorInfo = error_get_last();
$errmsg = $errorInfo['message'];
$errno = $errorInfo['type'];
throw new Splunk_ConnectException($errmsg, $errno);
}
$headers = array();
$headerLines = $http_response_header;
$statusLine = array_shift($headerLines);
foreach ($headerLines as $line)
{
list($key, $value) = explode(':', $line, 2);
$headers[$key] = trim($value);
}
$statusLineComponents = explode(' ', $statusLine, 3);
$httpVersion = $statusLineComponents[0];
$status = intval($statusLineComponents[1]);
$reason = (count($statusLineComponents) == 3)
? $statusLineComponents[2]
: '';
$response = new Splunk_HttpResponse(array(
'status' => $status,
'reason' => $reason,
'headers' => $headers,
'bodyStream' => $bodyStream,
));
if ($status >= 400)
throw new Splunk_HttpException($response);
else
return $response;
}
private function requestWithCurl(
$method, $url, $requestHeaders=array(), $requestBody='')
{
$opts = array(
CURLOPT_URL => $url,
CURLOPT_TIMEOUT => 60, // secs
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_HEADER => TRUE,
// disable SSL certificate validation
CURLOPT_SSL_VERIFYPEER => FALSE,
// LMR FIX !!!!!!!
CURLOPT_SSL_VERIFYHOST => FALSE,
);
foreach ($requestHeaders as $k => $v)
$opts[CURLOPT_HTTPHEADER][] = "$k: $v";
switch ($method)
{
case 'get':
$opts[CURLOPT_HTTPGET] = TRUE;
break;
case 'post':
$opts[CURLOPT_POST] = TRUE;
$opts[CURLOPT_POSTFIELDS] = $requestBody;
break;
default:
$opts[CURLOPT_CUSTOMREQUEST] = strtoupper($method);
break;
}
if (!($curl = curl_init()))
throw new Splunk_ConnectException('Unable to initialize cURL.');
if (!(curl_setopt_array($curl, $opts)))
throw new Splunk_ConnectException(curl_error($curl));
// NOTE: The entire HTTP response is read into memory here,
// which could be very large. Unfortunately the cURL
// interface does not provide a streaming alternative.
// To avoid this problem, use PHP 5.3.7+, which doesn't
// need cURL to perform HTTP requests.
if (!($response = curl_exec($curl)))
throw new Splunk_ConnectException(curl_error($curl));
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$headerText = substr($response, 0, $headerSize);
$body = (strlen($response) == $headerSize)
? ''
: substr($response, $headerSize);
$headers = array();
$headerLines = explode("\r\n", trim($headerText));
$statusLine = array_shift($headerLines);
foreach ($headerLines as $line)
{
list($key, $value) = explode(':', $line, 2);
$headers[$key] = trim($value);
}
$statusLineComponents = explode(' ', $statusLine, 3);
$httpVersion = $statusLineComponents[0];
$reason = count($statusLineComponents) == 3 ? $statusLineComponents[2] : '';
$response = new Splunk_HttpResponse(array(
'status' => $status,
'reason' => $reason,
'headers' => $headers,
'body' => $body,
));
if ($status >= 400)
throw new Splunk_HttpException($response);
else
return $response;
}
}