From: Michael Date: Sun, 31 Oct 2021 05:25:39 +0000 (+0000) Subject: Merge remote-tracking branch 'upstream/develop' into error-handling X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=516018861e011865a902587876d484d6f0f42a66;p=friendica.git Merge remote-tracking branch 'upstream/develop' into error-handling --- 516018861e011865a902587876d484d6f0f42a66 diff --cc src/Database/Database.php index 88363cc397,a6cc3f875d..0e1cffb4ac --- a/src/Database/Database.php +++ b/src/Database/Database.php @@@ -21,9 -21,9 +21,9 @@@ namespace Friendica\Database; - use Friendica\Core\Config\Cache; + use Friendica\Core\Config\ValueObject\Cache; use Friendica\Core\System; -use Friendica\Network\HTTPException\InternalServerErrorException; +use Friendica\Network\HTTPException\ServiceUnavailableException; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; use mysqli; diff --cc src/Module/Admin/Summary.php index 730cf3719d,078f08721d..ca244260f6 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@@ -29,10 -29,11 +29,10 @@@ use Friendica\Core\Update use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\DI; - use Friendica\Factory\ConfigFactory; + use Friendica\Core\Config\Factory\Config; use Friendica\Model\Register; use Friendica\Module\BaseAdmin; -use Friendica\Network\HTTPException\InternalServerErrorException; -use Friendica\Core\Config\Util\ConfigFileLoader; +use Friendica\Network\HTTPException\ServiceUnavailableException; use Friendica\Util\DateTimeFormat; class Summary extends BaseAdmin diff --cc src/Module/Photo.php index 58a2eeac56,db21803e6d..21e02c7cd8 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@@ -29,11 -29,10 +29,11 @@@ use Friendica\Model\Contact use Friendica\Model\Photo as MPhoto; use Friendica\Model\Post; use Friendica\Model\Profile; - use Friendica\Model\Storage\ExternalResource; - use Friendica\Model\Storage\SystemResource; + use Friendica\Core\Storage\Type\ExternalResource; + use Friendica\Core\Storage\Type\SystemResource; use Friendica\Model\User; use Friendica\Network\HTTPException; +use Friendica\Network\HTTPException\NotModifiedException; use Friendica\Object\Image; use Friendica\Util\Images; use Friendica\Util\Network; diff --cc src/Network/HTTPClient/Response/CurlResult.php index 0000000000,adff9b8dca..e5c2777cd3 mode 000000,100644..100644 --- a/src/Network/HTTPClient/Response/CurlResult.php +++ b/src/Network/HTTPClient/Response/CurlResult.php @@@ -1,0 -1,349 +1,349 @@@ + . + * + */ + + namespace Friendica\Network\HTTPClient\Response; + + use Friendica\Core\Logger; + use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses; -use Friendica\Network\HTTPException\InternalServerErrorException; ++use Friendica\Network\HTTPException\UnprocessableEntityException; + use Friendica\Util\Network; + + /** + * A content class for Curl call results + */ + class CurlResult implements ICanHandleHttpResponses + { + /** + * @var int HTTP return code or 0 if timeout or failure + */ + private $returnCode; + + /** + * @var string the content type of the Curl call + */ + private $contentType; + + /** + * @var string the HTTP headers of the Curl call + */ + private $header; + + /** + * @var array the HTTP headers of the Curl call + */ + private $header_fields; + + /** + * @var boolean true (if HTTP 2xx result) or false + */ + private $isSuccess; + + /** + * @var string the URL which was called + */ + private $url; + + /** + * @var string in case of redirect, content was finally retrieved from this URL + */ + private $redirectUrl; + + /** + * @var string fetched content + */ + private $body; + + /** + * @var array some informations about the fetched data + */ + private $info; + + /** + * @var boolean true if the URL has a redirect + */ + private $isRedirectUrl; + + /** + * @var boolean true if the curl request timed out + */ + private $isTimeout; + + /** + * @var int the error number or 0 (zero) if no error + */ + private $errorNumber; + + /** + * @var string the error message or '' (the empty string) if no + */ + private $error; + + /** + * Creates an errored CURL response + * + * @param string $url optional URL + * + * @return ICanHandleHttpResponses a CURL with error response - * @throws InternalServerErrorException ++ * @throws UnprocessableEntityException + */ + public static function createErrorCurl(string $url = '') + { + return new CurlResult($url, '', ['http_code' => 0]); + } + + /** + * Curl constructor. + * + * @param string $url the URL which was called + * @param string $result the result of the curl execution + * @param array $info an additional info array + * @param int $errorNumber the error number or 0 (zero) if no error + * @param string $error the error message or '' (the empty string) if no + * - * @throws InternalServerErrorException when HTTP code of the CURL response is missing ++ * @throws UnprocessableEntityException when HTTP code of the CURL response is missing + */ + public function __construct(string $url, string $result, array $info, int $errorNumber = 0, string $error = '') + { + if (!array_key_exists('http_code', $info)) { - throw new InternalServerErrorException('CURL response doesn\'t contains a response HTTP code'); ++ throw new UnprocessableEntityException('CURL response doesn\'t contains a response HTTP code'); + } + + $this->returnCode = $info['http_code']; + $this->url = $url; + $this->info = $info; + $this->errorNumber = $errorNumber; + $this->error = $error; + + Logger::debug('construct', ['url' => $url, 'returncode' => $this->returnCode, 'result' => $result]); + + $this->parseBodyHeader($result); + $this->checkSuccess(); + $this->checkRedirect(); + $this->checkInfo(); + } + + private function parseBodyHeader($result) + { + // Pull out multiple headers, e.g. proxy and continuation headers + // allow for HTTP/2.x without fixing code + + $header = ''; + $base = $result; + while (preg_match('/^HTTP\/.+? \d+/', $base)) { + $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4); + $header .= $chunk; + $base = substr($base, strlen($chunk)); + } + + $this->body = substr($result, strlen($header)); + $this->header = $header; + $this->header_fields = []; // Is filled on demand + } + + private function checkSuccess() + { + $this->isSuccess = ($this->returnCode >= 200 && $this->returnCode <= 299) || $this->errorNumber == 0; + + // Everything higher or equal 400 is not a success + if ($this->returnCode >= 400) { + $this->isSuccess = false; + } + + if (!$this->isSuccess) { + Logger::debug('debug', ['info' => $this->info]); + } + + if (!$this->isSuccess && $this->errorNumber == CURLE_OPERATION_TIMEDOUT) { + $this->isTimeout = true; + } else { + $this->isTimeout = false; + } + } + + private function checkRedirect() + { + if (!array_key_exists('url', $this->info)) { + $this->redirectUrl = ''; + } else { + $this->redirectUrl = $this->info['url']; + } + + if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode == 307) { + $redirect_parts = parse_url($this->info['redirect_url'] ?? ''); + if (empty($redirect_parts)) { + $redirect_parts = []; + } + + if (preg_match('/(Location:|URI:)(.*?)\n/i', $this->header, $matches)) { + $redirect_parts2 = parse_url(trim(array_pop($matches))); + if (!empty($redirect_parts2)) { + $redirect_parts = array_merge($redirect_parts, $redirect_parts2); + } + } + + $parts = parse_url($this->info['url'] ?? ''); + if (empty($parts)) { + $parts = []; + } + + /// @todo Checking the corresponding RFC which parts of a redirect can be ommitted. + $components = ['scheme', 'host', 'path', 'query', 'fragment']; + foreach ($components as $component) { + if (empty($redirect_parts[$component]) && !empty($parts[$component])) { + $redirect_parts[$component] = $parts[$component]; + } + } + + $this->redirectUrl = Network::unparseURL($redirect_parts); + + $this->isRedirectUrl = true; + } else { + $this->isRedirectUrl = false; + } + } + + private function checkInfo() + { + if (isset($this->info['content_type'])) { + $this->contentType = $this->info['content_type']; + } else { + $this->contentType = ''; + } + } + + /** {@inheritDoc} */ + public function getReturnCode(): string + { + return $this->returnCode; + } + + /** {@inheritDoc} */ + public function getContentType(): string + { + return $this->contentType; + } + + /** {@inheritDoc} */ + public function getHeader(string $header): array + { + if (empty($header)) { + return []; + } + + $header = strtolower(trim($header)); + + $headers = $this->getHeaderArray(); + + if (isset($headers[$header])) { + return $headers[$header]; + } + + return []; + } + + /** {@inheritDoc} */ + public function getHeaders(): array + { + return $this->getHeaderArray(); + } + + /** {@inheritDoc} */ + public function inHeader(string $field): bool + { + $field = strtolower(trim($field)); + + $headers = $this->getHeaderArray(); + + return array_key_exists($field, $headers); + } + + /** {@inheritDoc} */ + public function getHeaderArray(): array + { + if (!empty($this->header_fields)) { + return $this->header_fields; + } + + $this->header_fields = []; + + $lines = explode("\n", trim($this->header)); + foreach ($lines as $line) { + $parts = explode(':', $line); + $headerfield = strtolower(trim(array_shift($parts))); + $headerdata = trim(implode(':', $parts)); + if (empty($this->header_fields[$headerfield])) { + $this->header_fields[$headerfield] = [$headerdata]; + } elseif (!in_array($headerdata, $this->header_fields[$headerfield])) { + $this->header_fields[$headerfield][] = $headerdata; + } + } + + return $this->header_fields; + } + + /** {@inheritDoc} */ + public function isSuccess(): bool + { + return $this->isSuccess; + } + + /** {@inheritDoc} */ + public function getUrl(): string + { + return $this->url; + } + + /** {@inheritDoc} */ + public function getRedirectUrl(): string + { + return $this->redirectUrl; + } + + /** {@inheritDoc} */ + public function getBody(): string + { + return $this->body; + } + + /** {@inheritDoc} */ + public function isRedirectUrl(): bool + { + return $this->isRedirectUrl; + } + + /** {@inheritDoc} */ + public function getErrorNumber(): int + { + return $this->errorNumber; + } + + /** {@inheritDoc} */ + public function getError(): string + { + return $this->error; + } + + /** {@inheritDoc} */ + public function isTimeout(): bool + { + return $this->isTimeout; + } + }