diff options
-rw-r--r-- | Dockerfile | 2 | ||||
-rw-r--r-- | Dockerfile.arm32v6 | 2 | ||||
-rw-r--r-- | Dockerfile.arm32v7 | 2 | ||||
-rw-r--r-- | Dockerfile.arm64v8 | 2 | ||||
-rw-r--r-- | app/Core/Http/Client.php | 130 | ||||
-rw-r--r-- | app/Template/config/about.php | 4 | ||||
-rw-r--r-- | app/constants.php | 1 | ||||
-rw-r--r-- | config.default.php | 1 |
8 files changed, 137 insertions, 7 deletions
@@ -12,7 +12,7 @@ RUN apk update && \ apk add openssl unzip nginx bash ca-certificates s6 curl ssmtp mailx php7 php7-phar php7-curl \ php7-fpm php7-json php7-zlib php7-xml php7-dom php7-ctype php7-opcache php7-zip php7-iconv \ php7-pdo php7-pdo_mysql php7-pdo_sqlite php7-pdo_pgsql php7-mbstring php7-session php7-bcmath \ - php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml && \ + php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml php7-curl && \ rm -rf /var/cache/apk/* && \ rm -rf /var/www/localhost && \ rm -f /etc/php7/php-fpm.d/www.conf diff --git a/Dockerfile.arm32v6 b/Dockerfile.arm32v6 index 1092360f..822b540e 100644 --- a/Dockerfile.arm32v6 +++ b/Dockerfile.arm32v6 @@ -12,7 +12,7 @@ RUN apk update && \ apk add openssl unzip nginx bash ca-certificates s6 curl ssmtp mailx php7 php7-phar php7-curl \ php7-fpm php7-json php7-zlib php7-xml php7-dom php7-ctype php7-opcache php7-zip php7-iconv \ php7-pdo php7-pdo_mysql php7-pdo_sqlite php7-pdo_pgsql php7-mbstring php7-session php7-bcmath \ - php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml && \ + php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml php7-curl && \ rm -rf /var/cache/apk/* && \ rm -rf /var/www/localhost && \ rm -f /etc/php7/php-fpm.d/www.conf diff --git a/Dockerfile.arm32v7 b/Dockerfile.arm32v7 index 2f0daa69..dddbfac9 100644 --- a/Dockerfile.arm32v7 +++ b/Dockerfile.arm32v7 @@ -12,7 +12,7 @@ RUN apk update && \ apk add openssl unzip nginx bash ca-certificates s6 curl ssmtp mailx php7 php7-phar php7-curl \ php7-fpm php7-json php7-zlib php7-xml php7-dom php7-ctype php7-opcache php7-zip php7-iconv \ php7-pdo php7-pdo_mysql php7-pdo_sqlite php7-pdo_pgsql php7-mbstring php7-session php7-bcmath \ - php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml && \ + php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml php7-curl && \ rm -rf /var/cache/apk/* && \ rm -rf /var/www/localhost && \ rm -f /etc/php7/php-fpm.d/www.conf diff --git a/Dockerfile.arm64v8 b/Dockerfile.arm64v8 index 4fc5f9ee..c78792a9 100644 --- a/Dockerfile.arm64v8 +++ b/Dockerfile.arm64v8 @@ -12,7 +12,7 @@ RUN apk update && \ apk add openssl unzip nginx bash ca-certificates s6 curl ssmtp mailx php7 php7-phar php7-curl \ php7-fpm php7-json php7-zlib php7-xml php7-dom php7-ctype php7-opcache php7-zip php7-iconv \ php7-pdo php7-pdo_mysql php7-pdo_sqlite php7-pdo_pgsql php7-mbstring php7-session php7-bcmath \ - php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml && \ + php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml php7-curl && \ rm -rf /var/cache/apk/* && \ rm -rf /var/www/localhost && \ rm -f /etc/php7/php-fpm.d/www.conf diff --git a/app/Core/Http/Client.php b/app/Core/Http/Client.php index 84099a23..230a5958 100644 --- a/app/Core/Http/Client.php +++ b/app/Core/Http/Client.php @@ -132,7 +132,7 @@ class Client extends Base } /** - * Make the HTTP request + * Make the HTTP request with cURL if detected, socket otherwise * * @access public * @param string $method @@ -144,10 +144,38 @@ class Client extends Base */ public function doRequest($method, $url, $content, array $headers, $raiseForErrors = false) { - if (empty($url)) { - return ''; + $requestBody = ''; + + if (! empty($url)) { + if (function_exists('curl_version')) { + if (DEBUG) { + $this->logger->debug('HttpClient::doRequest: cURL detected'); + } + $requestBody = $this->doRequestWithCurl($method, $url, $content, $headers, $raiseForErrors); + } else { + if (DEBUG) { + $this->logger->debug('HttpClient::doRequest: using socket'); + } + $requestBody = $this->doRequestWithSocket($method, $url, $content, $headers, $raiseForErrors); + } } + return $requestBody; + } + + /** + * Make the HTTP request with socket + * + * @access private + * @param string $method + * @param string $url + * @param string $content + * @param string[] $headers + * @param bool $raiseForErrors + * @return string + */ + private function doRequestWithSocket($method, $url, $content, array $headers, $raiseForErrors = false) + { $startTime = microtime(true); $stream = @fopen(trim($url), 'r', false, stream_context_create($this->getContext($method, $content, $headers, $raiseForErrors))); @@ -184,6 +212,91 @@ class Client extends Base return $body; } + + /** + * Make the HTTP request with cURL + * + * @access private + * @param string $method + * @param string $url + * @param string $content + * @param string[] $headers + * @param bool $raiseForErrors + * @return string + */ + private function doRequestWithCurl($method, $url, $content, array $headers, $raiseForErrors = false) + { + $startTime = microtime(true); + $curlSession = @curl_init(); + + curl_setopt($curlSession, CURLOPT_URL, trim($url)); + curl_setopt($curlSession, CURLOPT_USERAGENT, self::HTTP_USER_AGENT); + curl_setopt($curlSession, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + curl_setopt($curlSession, CURLOPT_TIMEOUT, HTTP_TIMEOUT); + curl_setopt($curlSession, CURLOPT_FORBID_REUSE, true); + curl_setopt($curlSession, CURLOPT_MAXREDIRS, HTTP_MAX_REDIRECTS); + curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curlSession, CURLOPT_FOLLOWLOCATION, true); + + if ('POST' === $method) { + curl_setopt($curlSession, CURLOPT_POST, true); + curl_setopt($curlSession, CURLOPT_POSTFIELDS, $content); + } + + if (! empty($headers)) { + curl_setopt($curlSession, CURLOPT_HTTPHEADER, $headers); + } + + if (HTTP_VERIFY_SSL_CERTIFICATE === false) { + curl_setopt($curlSession, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($curlSession, CURLOPT_SSL_VERIFYPEER, false); + } + + if (HTTP_PROXY_HOSTNAME) { + curl_setopt($curlSession, CURLOPT_PROXY, HTTP_PROXY_HOSTNAME); + curl_setopt($curlSession, CURLOPT_PROXYPORT, HTTP_PROXY_PORT); + curl_setopt($curlSession, CURLOPT_NOPROXY, HTTP_PROXY_EXCLUDE); + } + + if (HTTP_PROXY_USERNAME) { + curl_setopt($curlSession, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + curl_setopt($curlSession, CURLOPT_PROXYUSERPWD, HTTP_PROXY_USERNAME.':'.HTTP_PROXY_PASSWORD); + } + + $body = curl_exec($curlSession); + + if (! $body) { + $this->logger->error('HttpClient: request failed ('.$url.')'); + + if ($raiseForErrors) { + throw new ClientException('Unreachable URL: '.$url); + } + + curl_close($curlSession); + return ''; + } + + if ($raiseForErrors) { + $statusCode = curl_getinfo($curlSession, CURLINFO_RESPONSE_CODE); + + if ($statusCode >= 400) { + throw new InvalidStatusException('Request failed with status code '.$statusCode, $statusCode, $body); + } + } + + if (DEBUG) { + $this->logger->debug('HttpClient: url='.$url); + $this->logger->debug('HttpClient: headers='.var_export($headers, true)); + $this->logger->debug('HttpClient: payload='.$content); + $this->logger->debug('HttpClient: metadata='.var_export(curl_getinfo($curlSession), true)); + $this->logger->debug('HttpClient: body='.$body); + $this->logger->debug('HttpClient: executionTime='.(microtime(true) - $startTime)); + } + + curl_close($curlSession); + return $body; + } + /** * Get stream context * @@ -247,4 +360,15 @@ class Client extends Base return $status; } + + /** + * Get backend used for making HTTP connections + * + * @access public + * @return string + */ + public static function backend() + { + return function_exists('curl_version') ? 'cURL' : 'socket'; + } } diff --git a/app/Template/config/about.php b/app/Template/config/about.php index 29063841..628fb096 100644 --- a/app/Template/config/about.php +++ b/app/Template/config/about.php @@ -36,6 +36,10 @@ <strong><?= PHP_SAPI ?></strong> </li> <li> + <?= t('HTTP Client:') ?> + <strong><?= Kanboard\Core\Http\Client::backend() ?></strong> + </li> + <li> <?= t('OS version:') ?> <strong><?= @php_uname('s').' '.@php_uname('r') ?></strong> </li> diff --git a/app/constants.php b/app/constants.php index e7d8c41c..326ff401 100644 --- a/app/constants.php +++ b/app/constants.php @@ -148,6 +148,7 @@ defined('HTTP_PROXY_HOSTNAME') or define('HTTP_PROXY_HOSTNAME', ''); defined('HTTP_PROXY_PORT') or define('HTTP_PROXY_PORT', '3128'); defined('HTTP_PROXY_USERNAME') or define('HTTP_PROXY_USERNAME', ''); defined('HTTP_PROXY_PASSWORD') or define('HTTP_PROXY_PASSWORD', ''); +defined('HTTP_PROXY_EXCLUDE') or define('HTTP_PROXY_EXCLUDE', 'localhost'); defined('HTTP_VERIFY_SSL_CERTIFICATE') or define('HTTP_VERIFY_SSL_CERTIFICATE', true); defined('TOTP_ISSUER') or define('TOTP_ISSUER', 'Kanboard'); diff --git a/config.default.php b/config.default.php index 40dfc2c1..5db1ad16 100644 --- a/config.default.php +++ b/config.default.php @@ -241,6 +241,7 @@ define('HTTP_PROXY_HOSTNAME', ''); define('HTTP_PROXY_PORT', '3128'); define('HTTP_PROXY_USERNAME', ''); define('HTTP_PROXY_PASSWORD', ''); +define('HTTP_PROXY_EXCLUDE', 'localhost'); // Set to false to allow self-signed certificates define('HTTP_VERIFY_SSL_CERTIFICATE', true); |