forked from leftypol/leftypol
HttpDriver.php: backport from upstream
This commit is contained in:
parent
c4d7bc39de
commit
a5cc1c2b42
2 changed files with 136 additions and 1 deletions
131
inc/Data/Driver/HttpDriver.php
Normal file
131
inc/Data/Driver/HttpDriver.php
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
<?php
|
||||||
|
namespace Vichan\Data\Driver;
|
||||||
|
|
||||||
|
defined('TINYBOARD') or exit;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Honestly this is just a wrapper for cURL. Still useful to mock it and have an OOP API on PHP 7.
|
||||||
|
*/
|
||||||
|
class HttpDriver {
|
||||||
|
private mixed $inner;
|
||||||
|
private int $timeout;
|
||||||
|
private int $max_file_size;
|
||||||
|
|
||||||
|
|
||||||
|
private function resetTowards(string $url, int $timeout): void {
|
||||||
|
\curl_reset($this->inner);
|
||||||
|
\curl_setopt_array($this->inner, [
|
||||||
|
\CURLOPT_URL => $url,
|
||||||
|
\CURLOPT_TIMEOUT => $timeout,
|
||||||
|
\CURLOPT_USERAGENT => 'Tinyboard',
|
||||||
|
\CURLOPT_PROTOCOLS => \CURLPROTO_HTTP | \CURLPROTO_HTTPS,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct(int $timeout, int $max_file_size) {
|
||||||
|
$this->inner = \curl_init();
|
||||||
|
$this->timeout = $timeout;
|
||||||
|
$this->max_file_size = $max_file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
\curl_close($this->inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a GET request.
|
||||||
|
*
|
||||||
|
* @param string $endpoint Uri endpoint.
|
||||||
|
* @param ?array $data Optional GET parameters.
|
||||||
|
* @param int $timeout Optional request timeout in seconds. Use the default timeout if 0.
|
||||||
|
* @return string Returns the body of the response.
|
||||||
|
* @throws RuntimeException Throws on IO error.
|
||||||
|
*/
|
||||||
|
public function requestGet(string $endpoint, ?array $data, int $timeout = 0): string {
|
||||||
|
if (!empty($data)) {
|
||||||
|
$endpoint .= '?' . \http_build_query($data);
|
||||||
|
}
|
||||||
|
if ($timeout == 0) {
|
||||||
|
$timeout = $this->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resetTowards($endpoint, $timeout);
|
||||||
|
\curl_setopt($this->inner, \CURLOPT_RETURNTRANSFER, true);
|
||||||
|
$ret = \curl_exec($this->inner);
|
||||||
|
|
||||||
|
if ($ret === false) {
|
||||||
|
throw new \RuntimeException(\curl_error($this->inner));
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a POST request.
|
||||||
|
*
|
||||||
|
* @param string $endpoint Uri endpoint.
|
||||||
|
* @param ?array $data Optional POST parameters.
|
||||||
|
* @param int $timeout Optional request timeout in seconds. Use the default timeout if 0.
|
||||||
|
* @return string Returns the body of the response.
|
||||||
|
* @throws RuntimeException Throws on IO error.
|
||||||
|
*/
|
||||||
|
public function requestPost(string $endpoint, ?array $data, int $timeout = 0): string {
|
||||||
|
if ($timeout == 0) {
|
||||||
|
$timeout = $this->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resetTowards($endpoint, $timeout);
|
||||||
|
\curl_setopt($this->inner, \CURLOPT_POST, true);
|
||||||
|
if (!empty($data)) {
|
||||||
|
\curl_setopt($this->inner, \CURLOPT_POSTFIELDS, \http_build_query($data));
|
||||||
|
}
|
||||||
|
\curl_setopt($this->inner, \CURLOPT_RETURNTRANSFER, true);
|
||||||
|
$ret = \curl_exec($this->inner);
|
||||||
|
|
||||||
|
if ($ret === false) {
|
||||||
|
throw new \RuntimeException(\curl_error($this->inner));
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download the url's target with curl.
|
||||||
|
*
|
||||||
|
* @param string $url Url to the file to download.
|
||||||
|
* @param ?array $data Optional GET parameters.
|
||||||
|
* @param resource $fd File descriptor to save the content to.
|
||||||
|
* @param int $timeout Optional request timeout in seconds. Use the default timeout if 0.
|
||||||
|
* @return bool Returns true on success, false if the file was too large.
|
||||||
|
* @throws RuntimeException Throws on IO error.
|
||||||
|
*/
|
||||||
|
public function requestGetInto(string $endpoint, ?array $data, mixed $fd, int $timeout = 0): bool {
|
||||||
|
if (!empty($data)) {
|
||||||
|
$endpoint .= '?' . \http_build_query($data);
|
||||||
|
}
|
||||||
|
if ($timeout == 0) {
|
||||||
|
$timeout = $this->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resetTowards($endpoint, $timeout);
|
||||||
|
// Adapted from: https://stackoverflow.com/a/17642638
|
||||||
|
$opt = (\PHP_MAJOR_VERSION >= 8 && \PHP_MINOR_VERSION >= 2) ? \CURLOPT_XFERINFOFUNCTION : \CURLOPT_PROGRESSFUNCTION;
|
||||||
|
\curl_setopt_array($this->inner, [
|
||||||
|
\CURLOPT_NOPROGRESS => false,
|
||||||
|
$opt => fn($res, $next_dl, $dl, $next_up, $up) => (int)($dl <= $this->max_file_size),
|
||||||
|
\CURLOPT_FAILONERROR => true,
|
||||||
|
\CURLOPT_FOLLOWLOCATION => false,
|
||||||
|
\CURLOPT_FILE => $fd,
|
||||||
|
\CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
|
||||||
|
]);
|
||||||
|
$ret = \curl_exec($this->inner);
|
||||||
|
|
||||||
|
if ($ret === false) {
|
||||||
|
if (\curl_errno($this->inner) === CURLE_ABORTED_BY_CALLBACK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \RuntimeException(\curl_error($this->inner));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
namespace Vichan;
|
namespace Vichan;
|
||||||
|
|
||||||
use Vichan\Data\{IpNoteQueries, ReportQueries, UserPostQueries};
|
use Vichan\Data\{IpNoteQueries, ReportQueries, UserPostQueries};
|
||||||
use Vichan\Data\Driver\{CacheDriver, ErrorLogLogDriver, FileLogDriver, LogDriver, StderrLogDriver, SyslogLogDriver};
|
use Vichan\Data\Driver\{CacheDriver, HttpDriver, ErrorLogLogDriver, FileLogDriver, LogDriver, StderrLogDriver, SyslogLogDriver};
|
||||||
|
|
||||||
defined('TINYBOARD') or exit;
|
defined('TINYBOARD') or exit;
|
||||||
|
|
||||||
|
@ -63,6 +63,10 @@ function build_context(array $config): Context {
|
||||||
// Use the global for backwards compatibility.
|
// Use the global for backwards compatibility.
|
||||||
return \cache::getCache();
|
return \cache::getCache();
|
||||||
},
|
},
|
||||||
|
HttpDriver::class => function($c) {
|
||||||
|
$config = $c->get('config');
|
||||||
|
return new HttpDriver($config['upload_by_url_timeout'], $config['max_filesize']);
|
||||||
|
},
|
||||||
\PDO::class => function($c) {
|
\PDO::class => function($c) {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
// Ensure the PDO is initialized.
|
// Ensure the PDO is initialized.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue