• File: Psr18Client.php
  • Full Path: /home/matthif/www/wp-includes/SimplePie/src/HTTP/Psr18Client.php
  • Date Modified: 12/03/2025 4:34 AM
  • File size: 4.34 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php

// SPDX-FileCopyrightText: 2004-2023 Ryan Parman, Sam Sneddon, Ryan McCue
// SPDX-License-Identifier: BSD-3-Clause

declare(strict_types=1);

namespace 
SimplePie\HTTP;

use 
InvalidArgumentException;
use 
Psr\Http\Client\ClientExceptionInterface;
use 
Psr\Http\Client\ClientInterface;
use 
Psr\Http\Message\RequestFactoryInterface;
use 
Psr\Http\Message\UriFactoryInterface;
use 
Throwable;

/**
 * HTTP Client based on PSR-18 and PSR-17 implementations
 *
 * @internal
 */
final class Psr18Client implements Client
{
    
/**
     * @var ClientInterface
     */
    
private $httpClient;

    
/**
     * @var RequestFactoryInterface
     */
    
private $requestFactory;

    
/**
     * @var UriFactoryInterface
     */
    
private $uriFactory;

    
/**
     * @var int
     */
    
private $allowedRedirects 5;

    public function 
__construct(ClientInterface $httpClientRequestFactoryInterface $requestFactoryUriFactoryInterface $uriFactory)
    {
        
$this->httpClient $httpClient;
        
$this->requestFactory $requestFactory;
        
$this->uriFactory $uriFactory;
    }

    public function 
getHttpClient(): ClientInterface
    
{
        return 
$this->httpClient;
    }

    public function 
getRequestFactory(): RequestFactoryInterface
    
{
        return 
$this->requestFactory;
    }

    public function 
getUriFactory(): UriFactoryInterface
    
{
        return 
$this->uriFactory;
    }

    
/**
     * send a request and return the response
     *
     * @param Client::METHOD_* $method
     * @param string $url
     * @param array<string,string|string[]> $headers
     *
     * @throws ClientException if anything goes wrong requesting the data
     */
    
public function request(string $methodstring $url, array $headers = []): Response
    
{
        if (
$method !== self::METHOD_GET) {
            throw new 
InvalidArgumentException(sprintf(
                
'%s(): Argument #1 ($method) only supports method "%s".',
                
__METHOD__,
                
self::METHOD_GET
            
), 1);
        }

        if (
preg_match('/^http(s)?:\/\//i'$url)) {
            return 
$this->requestUrl($method$url$headers);
        }

        return 
$this->requestLocalFile($url);
    }

    
/**
     * @param array<string,string|string[]> $headers
     */
    
private function requestUrl(string $methodstring $url, array $headers): Response
    
{
        
$permanentUrl $url;
        
$requestedUrl $url;
        
$remainingRedirects $this->allowedRedirects;

        
$request $this->requestFactory->createRequest(
            
$method,
            
$this->uriFactory->createUri($requestedUrl)
        );

        foreach (
$headers as $name => $value) {
            
$request $request->withHeader($name$value);
        }

        do {
            
$followRedirect false;

            try {
                
$response $this->httpClient->sendRequest($request);
            } catch (
ClientExceptionInterface $th) {
                throw new 
ClientException($th->getMessage(), $th->getCode(), $th);
            }

            
$statusCode $response->getStatusCode();

            
// If we have a redirect
            
if (in_array($statusCode, [300301302303307]) && $response->hasHeader('Location')) {
                
// Prevent infinity redirect loops
                
if ($remainingRedirects <= 0) {
                    break;
                }

                
$remainingRedirects--;
                
$followRedirect true;

                
$requestedUrl $response->getHeaderLine('Location');

                if (
$statusCode === 301) {
                    
$permanentUrl $requestedUrl;
                }

                
$request $request->withUri($this->uriFactory->createUri($requestedUrl));
            }
        } while (
$followRedirect);

        return new 
Psr7Response($response$permanentUrl$requestedUrl);
    }

    private function 
requestLocalFile(string $path): Response
    
{
        if (!
is_readable($path)) {
            throw new 
ClientException(sprintf('file "%s" is not readable'$path));
        }

        try {
            
$raw file_get_contents($path);
        } catch (
Throwable $th) {
            throw new 
ClientException($th->getMessage(), $th->getCode(), $th);
        }

        if (
$raw === false) {
            throw new 
ClientException('file_get_contents() could not read the file'1);
        }

        return new 
RawTextResponse($raw$path);
    }
}