1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-17 20:11:46 +02:00

Update WireHttp::sendFile() method to support partial downloads or ranges via HTTP_RANGE headers. Browsers use this particularly with media files (audio/video), especially Safari and iOS devices. But this also enables partial and pause/resume of any kind of downloads.

This commit is contained in:
Ryan Cramer
2019-05-03 11:40:29 -04:00
parent f2dbdb118e
commit 12f6253af6

View File

@@ -26,6 +26,8 @@
* https://processwire.com
*
* @method bool|string send($url, $data = array(), $method = 'POST', array $options = array())
* @method int sendFile($filename, array $options = array(), array $headers = array())
* @method string download($fromURL, $toFile, array $options = array())
*
*
*/
@@ -51,12 +53,12 @@ class WireHttp extends Wire {
const defaultDownloadTimeout = 50;
/**
* Default value for $headers, when reset
* Default value for request $headers, when reset
*
*/
protected $defaultHeaders = array(
'charset' => 'utf-8',
);
);
/**
* Schemes we are allowed to use
@@ -77,7 +79,7 @@ class WireHttp extends Wire {
protected $headers = array();
/**
* HTTP error codes
* HTTP codes
*
* @var array
*
@@ -162,7 +164,7 @@ class WireHttp extends Wire {
524 => 'A timeout occurred (Cloudflare)',
598 => 'Network read timeout error (Unknown)',
599 => 'Network connect timeout error (Unknown)',
);
);
/**
* Seconds till timing out on a connection
@@ -293,6 +295,8 @@ class WireHttp extends Wire {
* echo "HTTP request failed: " . $http->getError();
* }
* ~~~~~
*
* #pw-group-HTTP-requests
*
* @param string $url URL to post to (including http:// or https://)
* @param mixed $data Associative array of data to send (if not already set before), or raw data to send.
@@ -320,6 +324,8 @@ class WireHttp extends Wire {
* echo "HTTP request failed: " . $http->getError();
* }
* ~~~~~
*
* #pw-group-HTTP-requests
*
* @param string $url URL to send request to (including http:// or https://)
* @param mixed $data Array of data to send (if not already set before) or raw data to send.
@@ -334,6 +340,8 @@ class WireHttp extends Wire {
/**
* Send to a URL that responds with JSON (using GET request) and return the resulting array or object.
*
* #pw-group-HTTP-requests
*
* @param string $url URL to send request to (including http:// or https://)
* @param bool $assoc Default is to return an array (specified by TRUE). If you want an object instead, specify FALSE.
@@ -349,6 +357,8 @@ class WireHttp extends Wire {
/**
* Send to a URL using a HEAD request
*
* #pw-group-HTTP-requests
*
* @param string $url URL to request (including http:// or https://)
* @param mixed $data Array of data to send (if not already set before) or raw data to send
@@ -365,6 +375,8 @@ class WireHttp extends Wire {
/**
* Send to a URL using a HEAD request and return the status code
*
* #pw-group-HTTP-requests
*
* @param string $url URL to request (including http:// or https://)
* @param mixed $data Array of data to send (if not already set before) or raw data
@@ -381,6 +393,8 @@ class WireHttp extends Wire {
/**
* Send to a URL using HEAD and return the status code and text like "200 OK"
*
* #pw-group-HTTP-requests
*
* @param string $url URL to request (including http:// or https://)
* @param mixed $data Array of data to send (if not already set before) or raw data
@@ -394,84 +408,13 @@ class WireHttp extends Wire {
return $this->status($url, $data, true, $options);
}
/**
* Set an array of headers, removes any existing headers
*
* @param array $headers Associative array of headers to set
* @return $this
*
*/
public function setHeaders(array $headers) {
foreach($headers as $key => $value) {
$this->setHeader($key, $value);
}
return $this;
}
/**
* Send an individual header to send
*
* @param string $key Header name
* @param string $value Header value
* @return $this
*
*/
public function setHeader($key, $value) {
$key = strtolower($key);
$this->headers[$key] = $value;
return $this;
}
/**
* Set an array of data, removes any existing data
*
* @param array $data Associative array of data
* @return $this
*
*/
public function setData($data) {
if(is_array($data)) $this->data = $data;
else $this->rawData = $data;
return $this;
}
/**
* Set a variable to be included in the POST/GET request
*
* @param string $key
* @param string|int $value
* @return $this
*
*/
public function set($key, $value) {
$this->data[$key] = $value;
return $this;
}
/**
* Allows setting to $data via $http->key = $value
*
* @param string $key
* @param mixed $value
*
*/
public function __set($key, $value) {
$this->set($key, $value);
}
/**
* Enables getting from $data via $http->key
*
* @param string $key
* @return mixed
*
*/
public function __get($key) {
return array_key_exists($key, $this->data) ? $this->data[$key] : null;
}
/**
* Send the given $data array to a URL using given method (i.e. POST, GET, PUT, DELETE, etc.)
*
* This method handles the implementation for the get/post/head/etc. methods. It is preferable to use one
* of those dedicated request methods rather than this one.
*
* #pw-group-HTTP-requests
*
* @param string $url URL to send to (including http:// or https://).
* @param array $data Array of data to send (if not already set before).
@@ -489,6 +432,7 @@ class WireHttp extends Wire {
$defaults = array(
'use' => 'auto',
'fallback' => 'auto', // false, 'auto', 'socket' or 'curl'
'proxy' => '',
'_url' => $url, // original unmodified URL
);
@@ -551,14 +495,12 @@ class WireHttp extends Wire {
*
* @param string $url
* @param string $method
* @param array $options
* @param array $options Options specific to fopen should be specified in [ 'fopen' => [ ... ] ]
*
* @return bool|string
*
*/
protected function sendFopen($url, $method = 'POST', array $options = array()) {
if($options) { /* ignore */ }
$this->resetResponse();
$this->lastSendType = 'fopen';
@@ -583,18 +525,28 @@ class WireHttp extends Wire {
}
$header .= "Connection: close\r\n";
$options = array(
'http' => array(
'method' => $method,
'timeout' => $this->getTimeout(),
'content' => $content,
'header' => $header,
)
$http = array(
'method' => $method,
'timeout' => $this->getTimeout(),
'content' => $content,
'header' => $header,
);
if(!empty($options['proxy'])) $http['proxy'] = $options['proxy'];
// merge fopen http options array if present, as well as any other options specified to fopen stream_context_create
if(isset($options['fopen']) && !empty($options['fopen']['http'])) {
// allow adding on to http option
$http = array_merge($options['fopen']['http'], $http);
} else if(!empty($options['http']) && is_array($options['http'])) {
// if http array specified outside fopen index
$http = array_merge($options['http'], $http);
}
$fopenOptions = array('http' => $http);
if(isset($options['fopen'])) $fopenOptions = array_merge($options['fopen'], $fopenOptions);
set_error_handler(array($this, '_errorHandler'));
$context = stream_context_create($options);
$context = stream_context_create($fopenOptions);
$fp = fopen($url, 'rb', false, $context);
restore_error_handler();
@@ -633,6 +585,12 @@ class WireHttp extends Wire {
$this->resetResponse();
$this->lastSendType = 'curl';
$timeout = isset($options['timeout']) ? (float) $options['timeout'] : $this->getTimeout();
$proxy = '';
if(!empty($options['proxy'])) $proxy = $options['proxy'];
else if(isset($options['curl']) && !empty($options['curl']['http']['proxy'])) $proxy = $options['curl']['http']['proxy'];
else if(isset($options['http']) && !empty($options['http']['proxy'])) $proxy = $options['http']['proxy'];
$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
@@ -663,11 +621,8 @@ class WireHttp extends Wire {
} else {
curl_setopt($curl, CURLOPT_HTTPGET, true);
}
// @felixwahner #1027
if(isset($options['http']) && isset($options['http']['proxy']) && !is_null($options['http']['proxy'])) {
curl_setopt($curl, CURLOPT_PROXY, $options['http']['proxy']);
}
if($proxy) curl_setopt($curl, CURLOPT_PROXY, $options['http']['proxy']);
if(!empty($this->data)) {
if($method === 'POST') {
@@ -812,7 +767,9 @@ class WireHttp extends Wire {
* Download a file from a URL and save it locally
*
* First it will attempt to use CURL. If that fails, it will try `fopen()`,
* unless you specify a `useMethod` in `$options`.
* unless you specify the `use` option in `$options`.
*
* #pw-group-files
*
* @param string $fromURL URL of file you want to download.
* @param string $toFile Filename you want to save it to (including full path).
@@ -823,7 +780,7 @@ class WireHttp extends Wire {
* @throws WireException All error conditions throw exceptions.
*
*/
public function download($fromURL, $toFile, array $options = array()) {
public function ___download($fromURL, $toFile, array $options = array()) {
$fromURL = $this->validateURL($fromURL, true);
$http = stripos($fromURL, 'http://') === 0;
@@ -921,6 +878,11 @@ class WireHttp extends Wire {
$this->resetResponse();
$fromURL = str_replace(' ', '%20', $fromURL);
$proxy = '';
if(!empty($options['proxy'])) $proxy = $options['proxy'];
else if(isset($options['curl']) && !empty($options['curl']['http']['proxy'])) $proxy = $options['curl']['http']['proxy'];
else if(isset($options['http']) && !empty($options['http']['proxy'])) $proxy = $options['http']['proxy'];
$curl = curl_init($fromURL);
@@ -930,11 +892,7 @@ class WireHttp extends Wire {
}
curl_setopt($curl, CURLOPT_FILE, $fp); // write curl response to file
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
// @felixwahner #1027
if(isset($options['http']) && isset($options['http']['proxy']) && !is_null($options['http']['proxy'])) {
curl_setopt($curl, CURLOPT_PROXY, $options['http']['proxy']);
}
if($proxy) curl_setopt($curl, CURLOPT_PROXY, $proxy);
$result = curl_exec($curl);
if($result) $this->httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
@@ -964,7 +922,11 @@ class WireHttp extends Wire {
);
$options = array_merge($defaultOptions, $options);
$context = stream_context_create(array('http' => $options));
$context = stream_context_create(
array(
'http' => $options
)
);
// download the file
set_error_handler(array($this, '_errorHandler'));
@@ -1002,11 +964,135 @@ class WireHttp extends Wire {
if(empty($content) && !count($this->error)) $this->error[] = 'no data received';
return count($this->error) ? false : true;
}
/**
* Set an array of request headers to send with GET/POST/etc. request
*
* Merges with existing headers unless you specify true for the $reset option (since 3.0.131).
* If you specify null for any header value, it removes the header (since 3.0.131).
*
* #pw-group-request-headers
*
* @param array $headers Associative array of headers to set
* @param array $options Options to modify default behavior (since 3.0.131):
* - `reset` (bool): Reset/clear all existing headers first? (default=false)
* - `replacements` (array): Associative array of [ find => replace ] values to replace in header values (default=[])
* @return $this
*
*/
public function setHeaders(array $headers, array $options = array()) {
$defaults = array(
'reset' => false,
'replacements' => array()
);
$options = array_merge($defaults, $options);
if($options['reset']) $this->headers = array();
$replacements = count($options['replacements']) ? $options['replacements'] : false;
foreach($headers as $key => $value) {
if(is_array($replacements)) $value = str_replace(array_keys($replacements), array_values($replacements), $value);
$this->setHeader($key, $value);
}
return $this;
}
/**
* Send an individual request header to send with GET/POST/etc. request
*
* #pw-group-request-headers
*
* @param string $key Header name
* @param string $value Header value to set (or specify null to remove header, since 3.0.131)
* @return $this
*
*/
public function setHeader($key, $value) {
$key = strtolower($key);
if($value === null) {
unset($this->headers[$key]);
} else {
$this->headers[$key] = "$value";
}
return $this;
}
/**
* Get all currently set request headers in an associative array
*
* Note: To get response headers from a previously sent request, use `WireHttp::getResponseHeaders()` instead.
*
* #pw-group-request-headers
*
* @return array
* @since 3.0.131
*
*/
public function getHeaders() {
return $this->headers;
}
/**
* Set an array of data, or string of raw data to send with next GET/POST/etc. request (overwriting the existing data or rawData)
*
* #pw-advanced
*
* @param array|string $data Associative array of data or string of raw data
* @return $this
*
*/
public function setData($data) {
if(is_array($data)) {
$this->data = $data;
} else {
$this->rawData = $data;
}
return $this;
}
/**
* Set a variable to be included in the next GET/POST/etc. request
*
* #pw-internal
*
* @param string $key
* @param string|int $value
* @return $this
*
*/
public function set($key, $value) {
$this->data[$key] = $value;
return $this;
}
/**
* Directly set a variable to be included in the next GET/POST/etc. request
*
* #pw-internal
*
* @param string $key
* @param mixed $value
*
*/
public function __set($key, $value) {
$this->set($key, $value);
}
/**
* Directly get a variable to be included in the next GET/POST/etc. request or NULL if not present
*
* #pw-internal
*
* @param string $key
* @return mixed
*
*/
public function __get($key) {
return array_key_exists($key, $this->data) ? $this->data[$key] : null;
}
/**
* Get the last HTTP response headers (normal array).
*
* #pw-internal
* #pw-group-response-headers
*
* Useful to examine for errors if your request returned false
* However, the `WireHttp::getResponseHeaders()` (plural) method may be better
@@ -1030,7 +1116,9 @@ class WireHttp extends Wire {
* instead, which returns multi-value headers as arrays.
*
* This method always returns an associative array of strings, unless you specify the
* `$key` option in which case it will return a string, or NULL if the header is not present.
* `$key` option in which case it will return a string, or NULL if the header is not present.
*
* #pw-group-response-headers
*
* @param string $key Optional header name you want to get (if you only need one)
* @return array|string|null
@@ -1053,7 +1141,9 @@ class WireHttp extends Wire {
* an array.
*
* This method always returns an associative array of strings and arrays, unless you specify the
* `$key` option in which case it can return an array, string, or NULL if the header is not present.
* `$key` option in which case it can return an array, string, or NULL if the header is not present.
*
* #pw-group-response-headers
*
* @param string $key Optional header name you want to get (if you only need a specific header)
* @param bool $forceArrays If even single-value headers should be arrays, specify true (default=false).
@@ -1173,12 +1263,16 @@ class WireHttp extends Wire {
* to content type headers and force-download state.
*
* This function throws a `WireException` if the file can't be sent for some reason.
*
* #pw-group-files
*
* @param string $filename Filename to send
* @param array $options Options that you may pass in:
* - `exit` (bool): Halt program executation after file send (default=true).
* - `exit` (bool): Halt program executation after file send (default=true).
* - `partial` (bool): Allow use of partial downloads via HTTP_RANGE requests? Since 3.0.131 (default=true)
* - `forceDownload` (bool|null): Whether file should force download (default=null, i.e. let content-type header decide).
* - `downloadFilename` (string): Filename you want the download to show on user's computer, or omit to use existing.
* - `headers` (array): The $headers argument to this method can also be provided as an option right here, since 3.0.131 (default=[])
* @param array $headers Headers that are sent. These are the defaults:
* - `pragma`: public
* - `expires`: 0
@@ -1187,21 +1281,26 @@ class WireHttp extends Wire {
* - `content-transfer-encoding`: binary
* - `content-length`: {filesize} (replaced with actual filesize)
* - To remove a header completely, make its value NULL and it won't be sent.
* @return int Returns value only if `exit` option is false (value is quantity of bytes sent)
* @throws WireException
*
*/
public function sendFile($filename, array $options = array(), array $headers = array()) {
public function ___sendFile($filename, array $options = array(), array $headers = array()) {
$_options = array(
$defaultOptions = array(
// boolean: halt program execution after file send
'exit' => true,
// allow use of partial downloads with HTTP_RANGE headers?
'partial' => true,
// boolean|null: whether file should force download (null=let content-type header decide)
'forceDownload' => null,
// string: filename you want the download to show on the user's computer, or blank to use existing.
'downloadFilename' => '',
// optionally specify headers here rather than as 3rd argument
'headers' => array(),
);
$_headers = array(
$defaultHeaders = array(
"pragma" => "public",
"expires" => "0",
"cache-control" => "must-revalidate, post-check=0, pre-check=0",
@@ -1210,39 +1309,205 @@ class WireHttp extends Wire {
"content-length" => "{filesize}",
);
$this->wire('session')->close();
$options = array_merge($_options, $options);
$headers = array_merge($_headers, $headers);
if(!is_file($filename)) throw new WireException("File does not exist");
$options = array_merge($defaultOptions, $options);
$headers = array_merge($defaultHeaders, $options['headers'], $headers);
$info = pathinfo($filename);
$ext = strtolower($info['extension']);
$filesize = filesize($filename);
$contentTypes = $this->wire('config')->fileContentTypes;
$contentType = isset($contentTypes[$ext]) ? $contentTypes[$ext] : $contentTypes['?'];
$forceDownload = $options['forceDownload'];
$bytesSent = 0;
if($options['exit']) $this->wire('session')->close();
if(is_null($forceDownload)) $forceDownload = substr($contentType, 0, 1) === '+';
$contentType = ltrim($contentType, '+');
if(ini_get('zlib.output_compression')) ini_set('zlib.output_compression', 'Off');
$tags = array('{content-type}' => $contentType, '{filesize}' => filesize($filename));
foreach($headers as $key => $value) {
if(is_null($value)) continue;
if(strpos($value, '{') !== false) $value = str_replace(array_keys($tags), array_values($tags), $value);
header("$key: $value");
}
$contentType = ltrim($contentType, '+');
if($forceDownload) {
$downloadFilename = empty($options['downloadFilename']) ? $info['basename'] : $options['downloadFilename'];
header("content-disposition: attachment; filename=\"$downloadFilename\"");
$headers['content-disposition'] = "attachment; filename=\"$downloadFilename\"";
}
$this->setHeaders($headers, array('replacements' => array(
'{content-type}' => $contentType,
'{filesize}' => $filesize
)));
if($options['partial']) {
//$this->setHeader('accept-ranges', "0-$filesize");
$this->setHeader('accept-ranges', 'bytes');
if(isset($_SERVER['HTTP_RANGE'])) {
$result = $this->sendFileRange($filename, $_SERVER['HTTP_RANGE']);
if(is_int($result)) {
if($options['exit']) exit();
return $result; // success
}
if($result === null) { // fail
$this->setHeader('httpcode', 416); // range cannot be satisfied
$this->setHeader('content-range', 'bytes 0-' . ($filesize - 1) . "/$filesize");
if($options['exit']) exit;
return 0;
} else if($result === false) {
// continue with regular send
}
}
}
$this->sendHeaders();
@ob_end_clean();
@flush();
readfile($filename);
if($options['exit']) exit;
return $bytesSent;
}
/**
* Handle an HTTP_RANGE request for sending of partial file (called by sendFile method)
*
* @param string $filename
* @param string $rangeStr Range string (i.e. `bytes=0-1234`) or omit to pull from `$_SERVER['HTTP_RANGE']`
* @return bool|int Returns bytes sent, null if error in request or range, or false if request should be handled by sendFile() instead
*
*/
protected function sendFileRange($filename, $rangeStr = '') {
if(empty($rangeStr)) $rangeStr = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : '';
if(empty($rangeStr)) return false;
$filesize = filesize($filename);
$rangeEnd = $filesize - 1;
// client has provided an HTTP_RANGE header containing a byte range
list($rangeType, $rangeBytes) = explode('=', $rangeStr, 2);
if(strtolower($rangeType) !== 'bytes') return null; // unrecognized range type prefix
if(strpos($rangeBytes, ',') !== false) return null; // unsupported multibyte range
if(strpos($rangeBytes, '-') === false) return null; // unrecognized range bytes string
if(strpos($rangeBytes, '-') === 0) {
// no rangeStart: rangeBytes was "-123" or just "-"
$rangeStart = $filesize - ((int) ltrim($rangeBytes, '-'));
} else {
// rangeBytes was '0-1234' or '1234-5678' or '1234-'
$rangeArray = explode('-', $rangeBytes, 2); // 0=start, 1=end
$rangeStart = (int) $rangeArray[0];
if(isset($rangeArray[1]) && ctype_digit($rangeArray[1])) {
$rangeEnd = (int) $rangeArray[1];
if($rangeEnd >= $filesize) $rangeEnd = $filesize-1; // rangeEnd must be under filesize
} else {
// keep existing rangeEnd at EOF
}
}
if($rangeStart > $rangeEnd) return null; // do not allow start greater than end
$this->setHeader('httpcode', 206); // 206=Partial Content
$this->setHeader('content-range', "bytes $rangeStart-$rangeEnd/$filesize");
$this->setHeader('content-length', $rangeEnd - $rangeStart + 1);
$this->sendHeaders();
@ob_end_clean();
@flush();
$fp = fopen($filename, 'rb');
$chunkSize = 1024 * 32;
$bytesSent = 0;
fseek($fp, $rangeStart);
while(!feof($fp) && ($pos = ftell($fp)) <= $rangeEnd) {
if($pos + $chunkSize > $rangeEnd) $chunkSize = $rangeEnd - $pos + 1;
set_time_limit(600);
echo fread($fp, $chunkSize);
$bytesSent += $chunkSize;
}
fclose($fp);
return $bytesSent;
}
/**
* Send currently set HTTP request headers to connected HTTP client
*
* This will send all HTTP headers previously set with setHeader() or setHeaders().
*
* Note: if a header with name `httpCode` and integer value has been previously set, it will be sent as an HTTP status header
* before the other headers. This can also be specified with the `httpCode` in the $options argument.
*
* #pw-internal
*
* @param array $options Options to modify default behavior:
* - `reset` (bool): Reset/clear headers that were set to WireHttp after sending? (default=false)
* - `headers` (array): Array [ name => value ] of headers to send, or omit to use headers set to WireHttp instance (default=[])
* - `httpCode` (int): HTTP status code to send or omit for none (default=0, aka dont send)
* - `httpVersion` (string): HTTP version string (default='1.1')
* - `replacements` (array): Associative array of [ find => replace ] strings to replace values in headers, i.e. `[ '{filesize}' => 12345 ]` (default=[])
* @return array Returns the headers that were sent (with duplicates removed, replacements processed, and lowercase header names)
* @throws WireException If given an unrecognized `$option['status']` code
* @since 3.0.131
*
*/
public function sendHeaders(array $options = array()) {
$defaults = array(
'reset' => false,
'headers' => array(),
'httpCode' => 0,
'httpVersion' => '1.1',
'replacements' => array(),
);
$options = array_merge($defaults, $options);
$headers = empty($options['headers']) ? $this->headers : $options['headers'];
$httpCode = (int) $options['httpCode'];
if(!$httpCode && isset($headers['httpcode'])) {
if(ctype_digit($headers['httpcode'])) $httpCode = (int) $headers['httpcode'];
}
if($httpCode > 0) {
if(!isset($this->httpCodes[$httpCode])) throw new WireException("Unrecognized http status code: $httpCode");
$this->sendHeader("HTTP/$options[httpVersion] $httpCode " . $this->httpCodes[$httpCode]);
}
$a = array();
foreach($headers as $key => $value) {
$key = strtolower($key);
if($value === null || $key === 'httpcode') continue;
if(count($options['replacements'])) {
$value = str_replace(array_keys($options['replacements']), array_values($options['replacements']), $value);
}
$a[$key] = $value;
}
foreach($a as $key => $value) {
$this->sendHeader($key, $value);
}
if($options['reset'] && $headers === $this->headers) $this->headers = array();
return $a;
}
/**
* Send a specific HTTP header to currenty connected HTTP client
*
* #pw-internal
*
* @param string $name Header name or entire header string.
* @param null|string|int $value Header value, or omit if you provided entire header string in $name argument
* @since 3.0.131
*
*/
public function sendHeader($name, $value = null) {
if($value === null) {
header($name);
} else {
header("$name: $value");
}
}
/**
* Validate a URL for WireHttp use
*
* #pw-internal
*
* @param string $url URL to validate
* @param bool $throw Whether to throw exception on validation fail (default=false)
@@ -1309,6 +1574,8 @@ class WireHttp extends Wire {
/**
* Get last HTTP code
*
* #pw-group-HTTP-codes
*
* @param bool $withText Specify true to include the HTTP code text label with the code
* @return int|string
@@ -1321,6 +1588,8 @@ class WireHttp extends Wire {
/**
* Return array of all possible HTTP codes as (code => description)
*
* #pw-group-HTTP-codes
*
* @return array
*
@@ -1331,6 +1600,8 @@ class WireHttp extends Wire {
/**
* Return array of all possible HTTP success codes as (code => description)
*
* #pw-group-HTTP-codes
*
* @return array
*
@@ -1346,6 +1617,8 @@ class WireHttp extends Wire {
/**
* Return array of all possible HTTP error codes as (code => description)
*
* #pw-group-HTTP-codes
*
* @return array
*
*/
@@ -1359,6 +1632,8 @@ class WireHttp extends Wire {
/**
* Set schemes WireHttp is allowed to access (default=[http, https])
*
* #pw-group-settings
*
* @param array|string $schemes Array of schemes or space-separated string of schemes
* @param bool $replace Specify true to replace any existing schemes already allowed (default=false)
@@ -1383,6 +1658,18 @@ class WireHttp extends Wire {
}
return $this;
}
/**
* Return array of allowed schemes
*
* #pw-group-settings
*
* @return array
*
*/
public function getAllowSchemes() {
return $this->allowSchemes;
}
/**
* Set options array given to $sanitizer->url()
@@ -1393,6 +1680,8 @@ class WireHttp extends Wire {
*
* To return current validate URL options, omit the $options argument.
*
* #pw-group-advanced
*
* @param array $options Options to set, see the $sanitizer->url() method for details on options.
* @return array Always returns current options
*
@@ -1402,21 +1691,13 @@ class WireHttp extends Wire {
return $this->validateURLOptions;
}
/**
* Return array of allowed schemes
*
* @return array
*
*/
public function getAllowSchemes() {
return $this->allowSchemes;
}
/**
* Get the current user-agent header
*
* To set the user agent header, use `$http->setHeader('user-agent', '...');`
*
* #pw-group-request-headers
*
* @return string
*
*/
@@ -1433,6 +1714,8 @@ class WireHttp extends Wire {
/**
* Set the number of seconds till connection times out
*
* #pw-group-settings
*
* @param int|float $seconds
* @return $this
*
@@ -1446,6 +1729,8 @@ class WireHttp extends Wire {
* Get the number of seconds till connection times out
*
* Used by send(), get(), post(), getJSON(), but not by download() methods.
*
* #pw-group-settings
*
* @return float
*