mirror of
https://github.com/processwire/processwire.git
synced 2025-08-18 20:41:16 +02:00
Improvements to WireHttp::send() method and update to use CURL first when available (rather than fopen)
This commit is contained in:
@@ -409,6 +409,7 @@ class WireHttp extends Wire {
|
|||||||
return $this->status($url, $data, true, $options);
|
return $this->status($url, $data, true, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the given $data array to a URL using given method (i.e. POST, GET, PUT, DELETE, etc.)
|
* Send the given $data array to a URL using given method (i.e. POST, GET, PUT, DELETE, etc.)
|
||||||
*
|
*
|
||||||
@@ -420,77 +421,141 @@ class WireHttp extends Wire {
|
|||||||
* @param string $url URL to send to (including http:// or https://).
|
* @param string $url URL to send to (including http:// or https://).
|
||||||
* @param array $data Array of data to send (if not already set before).
|
* @param array $data Array of data to send (if not already set before).
|
||||||
* @param string $method Method to use (either POST, GET, PUT, DELETE or others as needed).
|
* @param string $method Method to use (either POST, GET, PUT, DELETE or others as needed).
|
||||||
* @param array|string $options Options to modify behavior (this argument added in 3.0.124):
|
* @param array|string $options Options to modify behavior. (This argument added in 3.0.124):
|
||||||
* - `use` (string): What handler to use, one of 'auto', 'fopen', 'curl' or 'socket' (default='auto')
|
* - `use` (string|array): What types(s) to use, one of 'fopen', 'curl', 'socket' to allow only
|
||||||
* If the 'auto' option is used, the method will first try fopen and then fallback to curl and sockets unless 'fallback' is disabled.
|
* that type. Or in 3.0.192+ this may be an array of types to attempt them in order.
|
||||||
* - `fallback` (bool|string): Allow fallback to other methods? Applies only if 'use' option is 'auto'. (default=true)
|
* Default in 3.0.192+ is [ 'curl', 'fopen', 'socket' ]. In prior versions default is 'auto'
|
||||||
* For a specific fallback method specify 'socket' or 'curl'
|
* which attempts: fopen, curl, then socket.
|
||||||
* @return bool|string False on failure or string of contents received on success.
|
* @return bool|string False on failure or string of contents received on success.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function ___send($url, $data = array(), $method = 'POST', array $options = array()) {
|
public function ___send($url, $data = array(), $method = 'POST', array $options = array()) {
|
||||||
|
|
||||||
$defaults = array(
|
$options = $this->sendOptions($url, $options);
|
||||||
'use' => 'auto',
|
|
||||||
'fallback' => 'auto', // false, 'auto', 'socket' or 'curl'
|
|
||||||
'proxy' => '',
|
|
||||||
'_url' => $url, // original unmodified URL
|
|
||||||
);
|
|
||||||
|
|
||||||
$options = array_merge($defaults, $options);
|
|
||||||
$url = $this->validateURL($url, false);
|
$url = $this->validateURL($url, false);
|
||||||
$allowFopen = $this->hasFopen;
|
|
||||||
$allowCURL = $this->hasCURL && (version_compare(PHP_VERSION, '5.5') >= 0 || $options['use'] === 'curl'); // #849
|
|
||||||
$result = false;
|
$result = false;
|
||||||
|
$error = array();
|
||||||
|
|
||||||
if(empty($url)) return false;
|
if(empty($url)) return false;
|
||||||
|
|
||||||
$this->resetResponse();
|
$this->resetResponse();
|
||||||
|
|
||||||
if(!empty($data)) $this->setData($data);
|
if(!empty($data)) $this->setData($data);
|
||||||
if(!isset($this->headers['user-agent'])) $this->setHeader('user-agent', $this->getUserAgent());
|
if(!isset($this->headers['user-agent'])) $this->setHeader('user-agent', $this->getUserAgent());
|
||||||
if(!in_array(strtoupper($method), $this->allowHttpMethods)) $method = 'POST';
|
if(!in_array(strtoupper($method), $this->allowHttpMethods)) $method = 'POST';
|
||||||
if($allowFopen && strpos($url, 'https://') === 0 && !extension_loaded('openssl')) $allowFopen = false;
|
|
||||||
|
|
||||||
if($options['use'] === 'socket') {
|
foreach($options['use'] as $use) {
|
||||||
// force socket
|
$use = strtolower($use);
|
||||||
return $this->sendSocket($url, $method);
|
if($use === 'curl' && !$options['allowCURL']) {
|
||||||
|
$error[] = 'CURL is not available';
|
||||||
} else if($options['use'] === 'curl') {
|
} else if($use === 'curl') {
|
||||||
// force curl
|
|
||||||
if(!$this->hasCURL) {
|
|
||||||
$this->error[] = 'CURL is not available';
|
|
||||||
return false;
|
|
||||||
} else if(!$allowCURL) {
|
|
||||||
$this->error[] = 'Using CURL requires PHP 5.5+';
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return $this->sendCURL($url, $method, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if($options['use'] === 'fopen' && !$allowFopen) {
|
|
||||||
$this->error[] = 'fopen is not available';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($allowFopen) {
|
|
||||||
$result = $this->sendFopen($url, $method, $options);
|
|
||||||
} else if($options['fallback'] === false) {
|
|
||||||
$this->error[] = 'fopen not available and fallback option is disabled';
|
|
||||||
}
|
|
||||||
|
|
||||||
if($result === false && $options['fallback'] !== false) {
|
|
||||||
// on fopen fail fallback to CURL then sockets
|
|
||||||
if($allowCURL && $options['fallback'] !== 'socket') {
|
|
||||||
$result = $this->sendCURL($url, $method, $options);
|
$result = $this->sendCURL($url, $method, $options);
|
||||||
}
|
} else if($use === 'fopen' && !$options['allowFopen']) {
|
||||||
if($result === false && $options['fallback'] !== 'curl') {
|
$error[] = 'fopen is not available';
|
||||||
|
} else if($use === 'fopen') {
|
||||||
|
$result = $this->sendFopen($url, $method, $options);
|
||||||
|
} else if($use === 'socket') {
|
||||||
$result = $this->sendSocket($options['_url'], $method);
|
$result = $this->sendSocket($options['_url'], $method);
|
||||||
|
} else {
|
||||||
|
$error[] = "unrecognized type: $use";
|
||||||
}
|
}
|
||||||
|
if($result !== false) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($result === false && count($error) && count($options['use']) < 3) {
|
||||||
|
// populate type errors only if request failed and specific options requested
|
||||||
|
$this->error = array_merge($this->error, $error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare options for send method(s)
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param array $options
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function sendOptions($url, array $options) {
|
||||||
|
|
||||||
|
$defaults = array(
|
||||||
|
'use' => array('curl', 'fopen', 'socket'),
|
||||||
|
'proxy' => '',
|
||||||
|
'_url' => $url, // original unmodified URL
|
||||||
|
'allowFopen' => true,
|
||||||
|
'allowCURL' => true,
|
||||||
|
|
||||||
|
// Options specific to fopen:
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
/*
|
||||||
|
'fopen' => array(
|
||||||
|
'http' => array(
|
||||||
|
'method' => '',
|
||||||
|
'timeout' => 0,
|
||||||
|
'content' => '',
|
||||||
|
'header' => '',
|
||||||
|
'proxy' => '',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Options specific to CURL:
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
/*
|
||||||
|
'curl' => array(
|
||||||
|
'http' => array(
|
||||||
|
'proxy' => '',
|
||||||
|
),
|
||||||
|
'setopt' => array(
|
||||||
|
CURLOPT_OPTION => 'option value',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'curl_setopt' => array(
|
||||||
|
// recognized alias of options[curl][setopt]
|
||||||
|
CURLOPT_OPTION => 'option value',
|
||||||
|
),
|
||||||
|
*/
|
||||||
|
|
||||||
|
// http option recognized by some types for legacy purposes
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
/*
|
||||||
|
'http' => array(
|
||||||
|
'proxy' => '',
|
||||||
|
),
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Legacy options that have been replaced
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// 'fallback' => true, // 'auto', 'socket' or 'curl'
|
||||||
|
// 'timeout' => 30,
|
||||||
|
);
|
||||||
|
|
||||||
|
// if legacy 'fallback' option used then migrate it to 'use' option
|
||||||
|
if(!empty($options['fallback']) && is_string($options['fallback'])) {
|
||||||
|
if(empty($options['use']) || $options['use'] === 'auto') {
|
||||||
|
// duplicate behavior in versions prior to 3.0.192
|
||||||
|
$options['use'] = array('fopen', $options['fallback']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = array_merge($defaults, $options);
|
||||||
|
|
||||||
|
if($options['use'] === 'auto') $options['use'] = $defaults['use']; // auto forces default
|
||||||
|
if(!is_array($options['use'])) $options['use'] = array($options['use']);
|
||||||
|
if(empty($options['use'])) $options['use'] = $defaults['use'];
|
||||||
|
|
||||||
|
$allowFopen = $this->hasFopen;
|
||||||
|
if($allowFopen && stripos($url, 'https://') === 0 && !extension_loaded('openssl')) $allowFopen = false;
|
||||||
|
$options['allowFopen'] = $allowFopen;
|
||||||
|
|
||||||
|
$allowCURL = $this->hasCURL && (version_compare(PHP_VERSION, '5.5') >= 0 || $options['use'] === 'curl'); // #849
|
||||||
|
$options['allowCURL'] = $allowCURL;
|
||||||
|
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send using fopen
|
* Send using fopen
|
||||||
*
|
*
|
||||||
@@ -808,6 +873,7 @@ class WireHttp extends Wire {
|
|||||||
* - `timeout` (float): Number of seconds till timeout.
|
* - `timeout` (float): Number of seconds till timeout.
|
||||||
* @return string Filename that was downloaded (including full path).
|
* @return string Filename that was downloaded (including full path).
|
||||||
* @throws WireException All error conditions throw exceptions.
|
* @throws WireException All error conditions throw exceptions.
|
||||||
|
* @todo update the use option to support array like the send() method
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function ___download($fromURL, $toFile, array $options = array()) {
|
public function ___download($fromURL, $toFile, array $options = array()) {
|
||||||
|
Reference in New Issue
Block a user