Restructure HTTPClient for new paradigm
This commit is contained in:
		
					parent
					
						
							
								fa55928ea3
							
						
					
				
			
			
				commit
				
					
						409d909d0f
					
				
			
		
					 25 changed files with 210 additions and 198 deletions
				
			
		|  | @ -1,13 +1,13 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Friendica\Network; | ||||
| namespace Friendica\Network\HTTPClient\Capability; | ||||
| 
 | ||||
| use Psr\Http\Message\MessageInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Temporary class to map Friendica used variables based on PSR-7 HTTPResponse | ||||
|  */ | ||||
| interface IHTTPResult | ||||
| interface ICanHandleHttpResponses | ||||
| { | ||||
| 	/** | ||||
| 	 * Gets the Return Code | ||||
|  | @ -25,13 +25,14 @@ interface IHTTPResult | |||
| 
 | ||||
| 	/** | ||||
| 	 * Returns the headers | ||||
| 	 * @see MessageInterface::getHeader() | ||||
| 	 * | ||||
| 	 * @param string $header optional header field. Return all fields if empty | ||||
| 	 * | ||||
| 	 * @return string[] the headers or the specified content of the header variable | ||||
| 	 *@see MessageInterface::getHeader() | ||||
| 	 * | ||||
| 	 */ | ||||
| 	public function getHeader($header); | ||||
| 	public function getHeader(string $header); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Returns all headers | ||||
|  | @ -19,14 +19,14 @@ | |||
|  * | ||||
|  */ | ||||
| 
 | ||||
| namespace Friendica\Network; | ||||
| namespace Friendica\Network\HTTPClient\Capability; | ||||
| 
 | ||||
| use GuzzleHttp\Exception\TransferException; | ||||
| 
 | ||||
| /** | ||||
|  * Interface for calling HTTP requests and returning their responses | ||||
|  */ | ||||
| interface IHTTPClient | ||||
| interface ICanRequestPerHttp | ||||
| { | ||||
| 	/** | ||||
| 	 * Fetches the content of an URL | ||||
|  | @ -41,7 +41,7 @@ interface IHTTPClient | |||
| 	 * | ||||
| 	 * @return string The fetched content | ||||
| 	 */ | ||||
| 	public function fetch(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = ''); | ||||
| 	public function fetch(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = ''): string; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Fetches the whole response of an URL. | ||||
|  | @ -54,12 +54,12 @@ interface IHTTPClient | |||
| 	 * @param string $accept_content  supply Accept: header with 'accept_content' as the value | ||||
| 	 * @param string $cookiejar       Path to cookie jar file | ||||
| 	 * | ||||
| 	 * @return IHTTPResult With all relevant information, 'body' contains the actual fetched content. | ||||
| 	 * @return ICanHandleHttpResponses With all relevant information, 'body' contains the actual fetched content. | ||||
| 	 */ | ||||
| 	public function fetchFull(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = ''); | ||||
| 	public function fetchFull(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = ''): ICanHandleHttpResponses; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Send a HEAD to an URL. | ||||
| 	 * Send a HEAD to a URL. | ||||
| 	 * | ||||
| 	 * @param string $url        URL to fetch | ||||
| 	 * @param array  $opts       (optional parameters) associative array with: | ||||
|  | @ -68,9 +68,9 @@ interface IHTTPClient | |||
| 	 *                           'cookiejar' => path to cookie jar file | ||||
| 	 *                           'header' => header array | ||||
| 	 * | ||||
| 	 * @return CurlResult | ||||
| 	 * @return ICanHandleHttpResponses | ||||
| 	 */ | ||||
| 	public function head(string $url, array $opts = []); | ||||
| 	public function head(string $url, array $opts = []): ICanHandleHttpResponses; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Send a GET to an URL. | ||||
|  | @ -83,9 +83,9 @@ interface IHTTPClient | |||
| 	 *                           'header' => header array | ||||
| 	 *                           'content_length' => int maximum File content length | ||||
| 	 * | ||||
| 	 * @return IHTTPResult | ||||
| 	 * @return ICanHandleHttpResponses | ||||
| 	 */ | ||||
| 	public function get(string $url, array $opts = []); | ||||
| 	public function get(string $url, array $opts = []): ICanHandleHttpResponses; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Sends a HTTP request to a given url | ||||
|  | @ -101,9 +101,9 @@ interface IHTTPClient | |||
| 	 *                           'content_length' => int maximum File content length | ||||
| 	 *                           'auth' => array authentication settings | ||||
| 	 * | ||||
| 	 * @return IHTTPResult | ||||
| 	 * @return ICanHandleHttpResponses | ||||
| 	 */ | ||||
| 	public function request(string $method, string $url, array $opts = []); | ||||
| 	public function request(string $method, string $url, array $opts = []): ICanHandleHttpResponses; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Send POST request to an URL | ||||
|  | @ -113,9 +113,9 @@ interface IHTTPClient | |||
| 	 * @param array  $headers HTTP headers | ||||
| 	 * @param int    $timeout The timeout in seconds, default system config value or 60 seconds | ||||
| 	 * | ||||
| 	 * @return IHTTPResult The content | ||||
| 	 * @return ICanHandleHttpResponses The content | ||||
| 	 */ | ||||
| 	public function post(string $url, $params, array $headers = [], int $timeout = 0); | ||||
| 	public function post(string $url, $params, array $headers = [], int $timeout = 0): ICanHandleHttpResponses; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Returns the original URL of the provided URL | ||||
|  | @ -129,5 +129,5 @@ interface IHTTPClient | |||
| 	 * | ||||
| 	 * @throws TransferException In case there's an error during the resolving | ||||
| 	 */ | ||||
| 	public function finalUrl(string $url); | ||||
| 	public function finalUrl(string $url): string; | ||||
| } | ||||
|  | @ -19,9 +19,14 @@ | |||
|  * | ||||
|  */ | ||||
| 
 | ||||
| namespace Friendica\Network; | ||||
| namespace Friendica\Network\HTTPClient\Client; | ||||
| 
 | ||||
| use Friendica\Core\System; | ||||
| use Friendica\Network\HTTPClient\Response\CurlResult; | ||||
| use Friendica\Network\HTTPClient\Response\GuzzleResponse; | ||||
| use Friendica\Network\HTTPClient\Capability\ICanRequestPerHttp; | ||||
| use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses; | ||||
| use Friendica\Network\HTTPException\InternalServerErrorException; | ||||
| use Friendica\Util\Network; | ||||
| use Friendica\Util\Profiler; | ||||
| use GuzzleHttp\Client; | ||||
|  | @ -37,7 +42,7 @@ use Psr\Log\LoggerInterface; | |||
| /** | ||||
|  * Performs HTTP requests to a given URL | ||||
|  */ | ||||
| class HTTPClient implements IHTTPClient | ||||
| class HttpClientCan implements ICanRequestPerHttp | ||||
| { | ||||
| 	/** @var LoggerInterface */ | ||||
| 	private $logger; | ||||
|  | @ -59,7 +64,7 @@ class HTTPClient implements IHTTPClient | |||
| 	/** | ||||
| 	 * {@inheritDoc} | ||||
| 	 */ | ||||
| 	public function request(string $method, string $url, array $opts = []): IHTTPResult | ||||
| 	public function request(string $method, string $url, array $opts = []): ICanHandleHttpResponses | ||||
| 	{ | ||||
| 		$this->profiler->startRecording('network'); | ||||
| 		$this->logger->debug('Request start.', ['url' => $url, 'method' => $method]); | ||||
|  | @ -95,43 +100,43 @@ class HTTPClient implements IHTTPClient | |||
| 
 | ||||
| 		$conf = []; | ||||
| 
 | ||||
| 		if (!empty($opts[HTTPClientOptions::COOKIEJAR])) { | ||||
| 			$jar                           = new FileCookieJar($opts[HTTPClientOptions::COOKIEJAR]); | ||||
| 		if (!empty($opts[HttpClientOptions::COOKIEJAR])) { | ||||
| 			$jar                           = new FileCookieJar($opts[HttpClientOptions::COOKIEJAR]); | ||||
| 			$conf[RequestOptions::COOKIES] = $jar; | ||||
| 		} | ||||
| 
 | ||||
| 		$headers = []; | ||||
| 
 | ||||
| 		if (!empty($opts[HTTPClientOptions::ACCEPT_CONTENT])) { | ||||
| 			$headers['Accept'] = $opts[HTTPClientOptions::ACCEPT_CONTENT]; | ||||
| 		if (!empty($opts[HttpClientOptions::ACCEPT_CONTENT])) { | ||||
| 			$headers['Accept'] = $opts[HttpClientOptions::ACCEPT_CONTENT]; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!empty($opts[HTTPClientOptions::LEGACY_HEADER])) { | ||||
| 		if (!empty($opts[HttpClientOptions::LEGACY_HEADER])) { | ||||
| 			$this->logger->notice('Wrong option \'headers\' used.'); | ||||
| 			$headers = array_merge($opts[HTTPClientOptions::LEGACY_HEADER], $headers); | ||||
| 			$headers = array_merge($opts[HttpClientOptions::LEGACY_HEADER], $headers); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!empty($opts[HTTPClientOptions::HEADERS])) { | ||||
| 			$headers = array_merge($opts[HTTPClientOptions::HEADERS], $headers); | ||||
| 		if (!empty($opts[HttpClientOptions::HEADERS])) { | ||||
| 			$headers = array_merge($opts[HttpClientOptions::HEADERS], $headers); | ||||
| 		} | ||||
| 
 | ||||
| 		$conf[RequestOptions::HEADERS] = array_merge($this->client->getConfig(RequestOptions::HEADERS), $headers); | ||||
| 
 | ||||
| 		if (!empty($opts[HTTPClientOptions::TIMEOUT])) { | ||||
| 			$conf[RequestOptions::TIMEOUT] = $opts[HTTPClientOptions::TIMEOUT]; | ||||
| 		if (!empty($opts[HttpClientOptions::TIMEOUT])) { | ||||
| 			$conf[RequestOptions::TIMEOUT] = $opts[HttpClientOptions::TIMEOUT]; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!empty($opts[HTTPClientOptions::BODY])) { | ||||
| 			$conf[RequestOptions::BODY] = $opts[HTTPClientOptions::BODY]; | ||||
| 		if (!empty($opts[HttpClientOptions::BODY])) { | ||||
| 			$conf[RequestOptions::BODY] = $opts[HttpClientOptions::BODY]; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!empty($opts[HTTPClientOptions::AUTH])) { | ||||
| 			$conf[RequestOptions::AUTH] = $opts[HTTPClientOptions::AUTH]; | ||||
| 		if (!empty($opts[HttpClientOptions::AUTH])) { | ||||
| 			$conf[RequestOptions::AUTH] = $opts[HttpClientOptions::AUTH]; | ||||
| 		} | ||||
| 
 | ||||
| 		$conf[RequestOptions::ON_HEADERS] = function (ResponseInterface $response) use ($opts) { | ||||
| 			if (!empty($opts[HTTPClientOptions::CONTENT_LENGTH]) && | ||||
| 				(int)$response->getHeaderLine('Content-Length') > $opts[HTTPClientOptions::CONTENT_LENGTH]) { | ||||
| 			if (!empty($opts[HttpClientOptions::CONTENT_LENGTH]) && | ||||
| 				(int)$response->getHeaderLine('Content-Length') > $opts[HttpClientOptions::CONTENT_LENGTH]) { | ||||
| 				throw new TransferException('The file is too big!'); | ||||
| 			} | ||||
| 		}; | ||||
|  | @ -159,7 +164,7 @@ class HTTPClient implements IHTTPClient | |||
| 
 | ||||
| 	/** {@inheritDoc} | ||||
| 	 */ | ||||
| 	public function head(string $url, array $opts = []): IHTTPResult | ||||
| 	public function head(string $url, array $opts = []): ICanHandleHttpResponses | ||||
| 	{ | ||||
| 		return $this->request('head', $url, $opts); | ||||
| 	} | ||||
|  | @ -167,7 +172,7 @@ class HTTPClient implements IHTTPClient | |||
| 	/** | ||||
| 	 * {@inheritDoc} | ||||
| 	 */ | ||||
| 	public function get(string $url, array $opts = []): IHTTPResult | ||||
| 	public function get(string $url, array $opts = []): ICanHandleHttpResponses | ||||
| 	{ | ||||
| 		return $this->request('get', $url, $opts); | ||||
| 	} | ||||
|  | @ -175,18 +180,18 @@ class HTTPClient implements IHTTPClient | |||
| 	/** | ||||
| 	 * {@inheritDoc} | ||||
| 	 */ | ||||
| 	public function post(string $url, $params, array $headers = [], int $timeout = 0): IHTTPResult | ||||
| 	public function post(string $url, $params, array $headers = [], int $timeout = 0): ICanHandleHttpResponses | ||||
| 	{ | ||||
| 		$opts = []; | ||||
| 
 | ||||
| 		$opts[HTTPClientOptions::BODY] = $params; | ||||
| 		$opts[HttpClientOptions::BODY] = $params; | ||||
| 
 | ||||
| 		if (!empty($headers)) { | ||||
| 			$opts[HTTPClientOptions::HEADERS] = $headers; | ||||
| 			$opts[HttpClientOptions::HEADERS] = $headers; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!empty($timeout)) { | ||||
| 			$opts[HTTPClientOptions::TIMEOUT] = $timeout; | ||||
| 			$opts[HttpClientOptions::TIMEOUT] = $timeout; | ||||
| 		} | ||||
| 
 | ||||
| 		return $this->request('post', $url, $opts); | ||||
|  | @ -195,7 +200,7 @@ class HTTPClient implements IHTTPClient | |||
| 	/** | ||||
| 	 * {@inheritDoc} | ||||
| 	 */ | ||||
| 	public function finalUrl(string $url) | ||||
| 	public function finalUrl(string $url): string | ||||
| 	{ | ||||
| 		$this->profiler->startRecording('network'); | ||||
| 
 | ||||
|  | @ -229,7 +234,7 @@ class HTTPClient implements IHTTPClient | |||
| 	/** | ||||
| 	 * {@inheritDoc} | ||||
| 	 */ | ||||
| 	public function fetch(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = '') | ||||
| 	public function fetch(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = ''): string | ||||
| 	{ | ||||
| 		$ret = $this->fetchFull($url, $timeout, $accept_content, $cookiejar); | ||||
| 
 | ||||
|  | @ -239,7 +244,7 @@ class HTTPClient implements IHTTPClient | |||
| 	/** | ||||
| 	 * {@inheritDoc} | ||||
| 	 */ | ||||
| 	public function fetchFull(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = '') | ||||
| 	public function fetchFull(string $url, int $timeout = 0, string $accept_content = '', string $cookiejar = ''): ICanHandleHttpResponses | ||||
| 	{ | ||||
| 		return $this->get( | ||||
| 			$url, | ||||
|  | @ -1,13 +1,13 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Friendica\Network; | ||||
| namespace Friendica\Network\HTTPClient\Client; | ||||
| 
 | ||||
| use GuzzleHttp\RequestOptions; | ||||
| 
 | ||||
| /** | ||||
|  * This class contains a list of possible HTTPClient request options. | ||||
|  */ | ||||
| class HTTPClientOptions | ||||
| class HttpClientOptions | ||||
| { | ||||
| 	/** | ||||
| 	 * accept_content: (array) supply Accept: header with 'accept_content' as the value | ||||
							
								
								
									
										113
									
								
								src/Network/HTTPClient/Factory/HttpClient.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								src/Network/HTTPClient/Factory/HttpClient.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,113 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Friendica\Network\HTTPClient\Factory; | ||||
| 
 | ||||
| use Friendica\App; | ||||
| use Friendica\BaseFactory; | ||||
| use Friendica\Core\Config\Capability\IManageConfigValues; | ||||
| use Friendica\Network\HTTPClient\Client; | ||||
| use Friendica\Network\HTTPClient\Capability\ICanRequestPerHttp; | ||||
| use Friendica\Util\Profiler; | ||||
| use Friendica\Util\Strings; | ||||
| use GuzzleHttp; | ||||
| use GuzzleHttp\HandlerStack; | ||||
| use GuzzleHttp\RequestOptions; | ||||
| use mattwright\URLResolver; | ||||
| use Psr\Http\Message\RequestInterface; | ||||
| use Psr\Http\Message\ResponseInterface; | ||||
| use Psr\Http\Message\UriInterface; | ||||
| use Psr\Log\LoggerInterface; | ||||
| 
 | ||||
| require_once __DIR__ . '/../../../../static/dbstructure.config.php'; | ||||
| 
 | ||||
| class HttpClient extends BaseFactory | ||||
| { | ||||
| 	/** @var IManageConfigValues */ | ||||
| 	private $config; | ||||
| 	/** @var Profiler */ | ||||
| 	private $profiler; | ||||
| 	/** @var App\BaseURL */ | ||||
| 	private $baseUrl; | ||||
| 
 | ||||
| 	public function __construct(LoggerInterface $logger, IManageConfigValues $config, Profiler $profiler, App\BaseURL $baseUrl) | ||||
| 	{ | ||||
| 		parent::__construct($logger); | ||||
| 		$this->config   = $config; | ||||
| 		$this->profiler = $profiler; | ||||
| 		$this->baseUrl  = $baseUrl; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Creates a IHTTPClient for communications with HTTP endpoints | ||||
| 	 * | ||||
| 	 * @param HandlerStack|null $handlerStack (optional) A handler replacement (just usefull at test environments) | ||||
| 	 * | ||||
| 	 * @return ICanRequestPerHttp | ||||
| 	 */ | ||||
| 	public function createClient(HandlerStack $handlerStack = null): ICanRequestPerHttp | ||||
| 	{ | ||||
| 		$proxy = $this->config->get('system', 'proxy'); | ||||
| 
 | ||||
| 		if (!empty($proxy)) { | ||||
| 			$proxyUser = $this->config->get('system', 'proxyuser'); | ||||
| 
 | ||||
| 			if (!empty($proxyUser)) { | ||||
| 				$proxy = $proxyUser . '@' . $proxy; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		$logger = $this->logger; | ||||
| 
 | ||||
| 		$onRedirect = function ( | ||||
| 			RequestInterface $request, | ||||
| 			ResponseInterface $response, | ||||
| 			UriInterface $uri | ||||
| 		) use ($logger) { | ||||
| 			$logger->notice('Curl redirect.', ['url' => $request->getUri(), 'to' => $uri, 'method' => $request->getMethod()]); | ||||
| 		}; | ||||
| 
 | ||||
| 		$userAgent = FRIENDICA_PLATFORM . " '" . | ||||
| 					 FRIENDICA_CODENAME . "' " . | ||||
| 					 FRIENDICA_VERSION . '-' . | ||||
| 					 DB_UPDATE_VERSION . '; ' . | ||||
| 					 $this->baseUrl->get(); | ||||
| 
 | ||||
| 		$guzzle = new GuzzleHttp\Client([ | ||||
| 			RequestOptions::ALLOW_REDIRECTS => [ | ||||
| 				'max'            => 8, | ||||
| 				'on_redirect'    => $onRedirect, | ||||
| 				'track_redirect' => true, | ||||
| 				'strict'         => true, | ||||
| 				'referer'        => true, | ||||
| 			], | ||||
| 			RequestOptions::HTTP_ERRORS => false, | ||||
| 			// Without this setting it seems as if some webservers send compressed content
 | ||||
| 			// This seems to confuse curl so that it shows this uncompressed.
 | ||||
| 			/// @todo  We could possibly set this value to "gzip" or something similar
 | ||||
| 			RequestOptions::DECODE_CONTENT   => '', | ||||
| 			RequestOptions::FORCE_IP_RESOLVE => ($this->config->get('system', 'ipv4_resolve') ? 'v4' : null), | ||||
| 			RequestOptions::CONNECT_TIMEOUT  => 10, | ||||
| 			RequestOptions::TIMEOUT          => $this->config->get('system', 'curl_timeout', 60), | ||||
| 			// by default, we will allow self-signed certs,
 | ||||
| 			// but it can be overridden
 | ||||
| 			RequestOptions::VERIFY  => (bool)$this->config->get('system', 'verifyssl'), | ||||
| 			RequestOptions::PROXY   => $proxy, | ||||
| 			RequestOptions::HEADERS => [ | ||||
| 				'User-Agent' => $userAgent, | ||||
| 			], | ||||
| 			'handler' => $handlerStack ?? HandlerStack::create(), | ||||
| 		]); | ||||
| 
 | ||||
| 		$resolver = new URLResolver(); | ||||
| 		$resolver->setUserAgent($userAgent); | ||||
| 		$resolver->setMaxRedirects(10); | ||||
| 		$resolver->setRequestTimeout(10); | ||||
| 		// if the file is too large then exit
 | ||||
| 		$resolver->setMaxResponseDataSize(1000000); | ||||
| 		// Designate a temporary file that will store cookies during the session.
 | ||||
| 		// Some websites test the browser for cookie support, so this enhances results.
 | ||||
| 		$resolver->setCookieJar(get_temppath() .'/resolver-cookie-' . Strings::getRandomName(10)); | ||||
| 
 | ||||
| 		return new Client\HttpClientCan($logger, $this->profiler, $guzzle, $resolver); | ||||
| 	} | ||||
| } | ||||
|  | @ -19,17 +19,17 @@ | |||
|  * | ||||
|  */ | ||||
| 
 | ||||
| namespace Friendica\Network; | ||||
| namespace Friendica\Network\HTTPClient\Response; | ||||
| 
 | ||||
| use Friendica\Core\Logger; | ||||
| use Friendica\Core\System; | ||||
| use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses; | ||||
| use Friendica\Network\HTTPException\InternalServerErrorException; | ||||
| use Friendica\Util\Network; | ||||
| 
 | ||||
| /** | ||||
|  * A content class for Curl call results | ||||
|  */ | ||||
| class CurlResult implements IHTTPResult | ||||
| class CurlResult implements ICanHandleHttpResponses | ||||
| { | ||||
| 	/** | ||||
| 	 * @var int HTTP return code or 0 if timeout or failure | ||||
|  | @ -101,35 +101,36 @@ class CurlResult implements IHTTPResult | |||
| 	 * | ||||
| 	 * @param string $url optional URL | ||||
| 	 * | ||||
| 	 * @return IHTTPResult a CURL with error response | ||||
| 	 * @return ICanHandleHttpResponses a CURL with error response | ||||
| 	 * @throws InternalServerErrorException | ||||
| 	 */ | ||||
| 	public static function createErrorCurl($url = '') | ||||
| 	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 | ||||
| 	 * | ||||
| 	 * @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 | ||||
| 	 */ | ||||
| 	public function __construct($url, $result, $info, $errorNumber = 0, $error = '') | ||||
| 	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'); | ||||
| 		} | ||||
| 
 | ||||
| 		$this->returnCode = $info['http_code']; | ||||
| 		$this->url = $url; | ||||
| 		$this->info = $info; | ||||
| 		$this->returnCode  = $info['http_code']; | ||||
| 		$this->url         = $url; | ||||
| 		$this->info        = $info; | ||||
| 		$this->errorNumber = $errorNumber; | ||||
| 		$this->error = $error; | ||||
| 		$this->error       = $error; | ||||
| 
 | ||||
| 		Logger::debug('construct', ['url' => $url, 'returncode' => $this->returnCode, 'result' => $result]); | ||||
| 
 | ||||
|  | @ -145,15 +146,15 @@ class CurlResult implements IHTTPResult | |||
| 		// allow for HTTP/2.x without fixing code
 | ||||
| 
 | ||||
| 		$header = ''; | ||||
| 		$base = $result; | ||||
| 		$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->body          = substr($result, strlen($header)); | ||||
| 		$this->header        = $header; | ||||
| 		$this->header_fields = []; // Is filled on demand
 | ||||
| 	} | ||||
| 
 | ||||
|  | @ -185,7 +186,7 @@ class CurlResult implements IHTTPResult | |||
| 			$this->redirectUrl = $this->info['url']; | ||||
| 		} | ||||
| 
 | ||||
| 		if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode== 307) { | ||||
| 		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 = []; | ||||
|  | @ -229,19 +230,19 @@ class CurlResult implements IHTTPResult | |||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getReturnCode() | ||||
| 	public function getReturnCode(): string | ||||
| 	{ | ||||
| 		return $this->returnCode; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getContentType() | ||||
| 	public function getContentType(): string | ||||
| 	{ | ||||
| 		return $this->contentType; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getHeader($header) | ||||
| 	public function getHeader(string $header): array | ||||
| 	{ | ||||
| 		if (empty($header)) { | ||||
| 			return []; | ||||
|  | @ -259,13 +260,13 @@ class CurlResult implements IHTTPResult | |||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getHeaders() | ||||
| 	public function getHeaders(): array | ||||
| 	{ | ||||
| 		return $this->getHeaderArray(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function inHeader(string $field) | ||||
| 	public function inHeader(string $field): bool | ||||
| 	{ | ||||
| 		$field = strtolower(trim($field)); | ||||
| 
 | ||||
|  | @ -275,7 +276,7 @@ class CurlResult implements IHTTPResult | |||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getHeaderArray() | ||||
| 	public function getHeaderArray(): array | ||||
| 	{ | ||||
| 		if (!empty($this->header_fields)) { | ||||
| 			return $this->header_fields; | ||||
|  | @ -285,9 +286,9 @@ class CurlResult implements IHTTPResult | |||
| 
 | ||||
| 		$lines = explode("\n", trim($this->header)); | ||||
| 		foreach ($lines as $line) { | ||||
| 			$parts = explode(':', $line); | ||||
| 			$parts       = explode(':', $line); | ||||
| 			$headerfield = strtolower(trim(array_shift($parts))); | ||||
| 			$headerdata = trim(implode(':', $parts)); | ||||
| 			$headerdata  = trim(implode(':', $parts)); | ||||
| 			if (empty($this->header_fields[$headerfield])) { | ||||
| 				$this->header_fields[$headerfield] = [$headerdata]; | ||||
| 			} elseif (!in_array($headerdata, $this->header_fields[$headerfield])) { | ||||
|  | @ -299,49 +300,49 @@ class CurlResult implements IHTTPResult | |||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function isSuccess() | ||||
| 	public function isSuccess(): bool | ||||
| 	{ | ||||
| 		return $this->isSuccess; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getUrl() | ||||
| 	public function getUrl(): string | ||||
| 	{ | ||||
| 		return $this->url; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getRedirectUrl() | ||||
| 	public function getRedirectUrl(): string | ||||
| 	{ | ||||
| 		return $this->redirectUrl; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getBody() | ||||
| 	public function getBody(): string | ||||
| 	{ | ||||
| 		return $this->body; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function isRedirectUrl() | ||||
| 	public function isRedirectUrl(): bool | ||||
| 	{ | ||||
| 		return $this->isRedirectUrl; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getErrorNumber() | ||||
| 	public function getErrorNumber(): int | ||||
| 	{ | ||||
| 		return $this->errorNumber; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getError() | ||||
| 	public function getError(): string | ||||
| 	{ | ||||
| 		return $this->error; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function isTimeout() | ||||
| 	public function isTimeout(): bool | ||||
| 	{ | ||||
| 		return $this->isTimeout; | ||||
| 	} | ||||
|  | @ -19,10 +19,10 @@ | |||
|  * | ||||
|  */ | ||||
| 
 | ||||
| namespace Friendica\Network; | ||||
| namespace Friendica\Network\HTTPClient\Response; | ||||
| 
 | ||||
| use Friendica\Core\Logger; | ||||
| use Friendica\Core\System; | ||||
| use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses; | ||||
| use Friendica\Network\HTTPException\NotImplementedException; | ||||
| use GuzzleHttp\Psr7\Response; | ||||
| use Psr\Http\Message\ResponseInterface; | ||||
|  | @ -30,7 +30,7 @@ use Psr\Http\Message\ResponseInterface; | |||
| /** | ||||
|  * A content wrapper class for Guzzle call results | ||||
|  */ | ||||
| class GuzzleResponse extends Response implements IHTTPResult, ResponseInterface | ||||
| class GuzzleResponse extends Response implements ICanHandleHttpResponses, ResponseInterface | ||||
| { | ||||
| 	/** @var string The URL */ | ||||
| 	private $url; | ||||
|  | @ -79,68 +79,72 @@ class GuzzleResponse extends Response implements IHTTPResult, ResponseInterface | |||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getReturnCode() | ||||
| 	public function getReturnCode(): string | ||||
| 	{ | ||||
| 		return $this->getStatusCode(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getContentType() | ||||
| 	public function getContentType(): string | ||||
| 	{ | ||||
| 		$contentTypes = $this->getHeader('Content-Type') ?? []; | ||||
| 
 | ||||
| 		return array_pop($contentTypes) ?? ''; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function inHeader(string $field) | ||||
| 	public function inHeader(string $field): bool | ||||
| 	{ | ||||
| 		return $this->hasHeader($field); | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getHeaderArray() | ||||
| 	public function getHeaderArray(): array | ||||
| 	{ | ||||
| 		return $this->getHeaders(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function isSuccess() | ||||
| 	public function isSuccess(): bool | ||||
| 	{ | ||||
| 		return $this->isSuccess; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getUrl() | ||||
| 	public function getUrl(): string | ||||
| 	{ | ||||
| 		return $this->url; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getRedirectUrl() | ||||
| 	public function getRedirectUrl(): string | ||||
| 	{ | ||||
| 		return $this->url; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function isRedirectUrl() | ||||
| 	/** {@inheritDoc} | ||||
| 	 * | ||||
| 	 * @throws NotImplementedException | ||||
| 	 */ | ||||
| 	public function isRedirectUrl(): bool | ||||
| 	{ | ||||
| 		throw new NotImplementedException(); | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getErrorNumber() | ||||
| 	public function getErrorNumber(): int | ||||
| 	{ | ||||
| 		return $this->errorNumber; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function getError() | ||||
| 	public function getError(): string | ||||
| 	{ | ||||
| 		return $this->error; | ||||
| 	} | ||||
| 
 | ||||
| 	/** {@inheritDoc} */ | ||||
| 	public function isTimeout() | ||||
| 	public function isTimeout(): bool | ||||
| 	{ | ||||
| 		return $this->isTimeout; | ||||
| 	} | ||||
|  | @ -34,6 +34,7 @@ use Friendica\Model\Contact; | |||
| use Friendica\Model\GServer; | ||||
| use Friendica\Model\Profile; | ||||
| use Friendica\Model\User; | ||||
| use Friendica\Network\HTTPClient\Client\HttpClientOptions; | ||||
| use Friendica\Protocol\ActivityNamespace; | ||||
| use Friendica\Protocol\ActivityPub; | ||||
| use Friendica\Protocol\Email; | ||||
|  | @ -170,7 +171,7 @@ class Probe | |||
| 		Logger::info('Probing', ['host' => $host, 'ssl_url' => $ssl_url, 'url' => $url, 'callstack' => System::callstack(20)]); | ||||
| 		$xrd = null; | ||||
| 
 | ||||
| 		$curlResult = DI::httpClient()->get($ssl_url, [HTTPClientOptions::TIMEOUT => $xrd_timeout, HTTPClientOptions::ACCEPT_CONTENT => ['application/xrd+xml']]); | ||||
| 		$curlResult = DI::httpClient()->get($ssl_url, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => ['application/xrd+xml']]); | ||||
| 		$ssl_connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); | ||||
| 		if ($curlResult->isSuccess()) { | ||||
| 			$xml = $curlResult->getBody(); | ||||
|  | @ -187,7 +188,7 @@ class Probe | |||
| 		} | ||||
| 
 | ||||
| 		if (!is_object($xrd) && !empty($url)) { | ||||
| 			$curlResult = DI::httpClient()->get($url, [HTTPClientOptions::TIMEOUT => $xrd_timeout, HTTPClientOptions::ACCEPT_CONTENT => ['application/xrd+xml']]); | ||||
| 			$curlResult = DI::httpClient()->get($url, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => ['application/xrd+xml']]); | ||||
| 			$connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); | ||||
| 			if ($curlResult->isTimeout()) { | ||||
| 				Logger::info('Probing timeout', ['url' => $url]); | ||||
|  | @ -429,7 +430,7 @@ class Probe | |||
| 	 */ | ||||
| 	private static function getHideStatus($url) | ||||
| 	{ | ||||
| 		$curlResult = DI::httpClient()->get($url, [HTTPClientOptions::CONTENT_LENGTH => 1000000]); | ||||
| 		$curlResult = DI::httpClient()->get($url, [HttpClientOptions::CONTENT_LENGTH => 1000000]); | ||||
| 		if (!$curlResult->isSuccess()) { | ||||
| 			return false; | ||||
| 		} | ||||
|  | @ -950,7 +951,7 @@ class Probe | |||
| 	{ | ||||
| 		$xrd_timeout = DI::config()->get('system', 'xrd_timeout', 20); | ||||
| 
 | ||||
| 		$curlResult = DI::httpClient()->get($url, [HTTPClientOptions::TIMEOUT => $xrd_timeout, HTTPClientOptions::ACCEPT_CONTENT => [$type]]); | ||||
| 		$curlResult = DI::httpClient()->get($url, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => [$type]]); | ||||
| 		if ($curlResult->isTimeout()) { | ||||
| 			self::$istimeout = true; | ||||
| 			return []; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue