[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Http/Transport/ -> StreamTransport.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   8   */
   9  
  10  namespace Joomla\CMS\Http\Transport;
  11  
  12  use Composer\CaBundle\CaBundle;
  13  use Joomla\CMS\Factory;
  14  use Joomla\CMS\Http\Response;
  15  use Joomla\CMS\Http\TransportInterface;
  16  use Joomla\Http\AbstractTransport;
  17  use Joomla\Http\Exception\InvalidResponseCodeException;
  18  use Joomla\Uri\Uri;
  19  use Joomla\Uri\UriInterface;
  20  use Laminas\Diactoros\Stream as StreamResponse;
  21  
  22  // phpcs:disable PSR1.Files.SideEffects
  23  \defined('JPATH_PLATFORM') or die;
  24  // phpcs:enable PSR1.Files.SideEffects
  25  
  26  /**
  27   * HTTP transport class for using PHP streams.
  28   *
  29   * @since  1.7.3
  30   */
  31  class StreamTransport extends AbstractTransport implements TransportInterface
  32  {
  33      /**
  34       * Send a request to the server and return a Response object with the response.
  35       *
  36       * @param   string        $method     The HTTP method for sending the request.
  37       * @param   UriInterface  $uri        The URI to the resource to request.
  38       * @param   mixed         $data       Either an associative array or a string to be sent with the request.
  39       * @param   array         $headers    An array of request headers to send with the request.
  40       * @param   integer       $timeout    Read timeout in seconds.
  41       * @param   string        $userAgent  The optional user agent string to send with the request.
  42       *
  43       * @return  Response
  44       *
  45       * @since   1.7.3
  46       * @throws  \RuntimeException
  47       */
  48      public function request($method, UriInterface $uri, $data = null, array $headers = [], $timeout = null, $userAgent = null)
  49      {
  50          // Create the stream context options array with the required method offset.
  51          $options = array('method' => strtoupper($method));
  52  
  53          // If data exists let's encode it and make sure our Content-Type header is set.
  54          if (isset($data)) {
  55              // If the data is a scalar value simply add it to the stream context options.
  56              if (is_scalar($data)) {
  57                  $options['content'] = $data;
  58              } else {
  59                  // Otherwise we need to encode the value first.
  60                  $options['content'] = http_build_query($data);
  61              }
  62  
  63              if (!isset($headers['Content-Type'])) {
  64                  $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
  65              }
  66  
  67              // Add the relevant headers.
  68              $headers['Content-Length'] = \strlen($options['content']);
  69          }
  70  
  71          // If an explicit timeout is given user it.
  72          if (isset($timeout)) {
  73              $options['timeout'] = (int) $timeout;
  74          }
  75  
  76          // If an explicit user agent is given use it.
  77          if (isset($userAgent)) {
  78              $options['user_agent'] = $userAgent;
  79          }
  80  
  81          // Ignore HTTP errors so that we can capture them.
  82          $options['ignore_errors'] = 1;
  83  
  84          // Follow redirects.
  85          $options['follow_location'] = (int) $this->getOption('follow_location', 1);
  86  
  87          // Set any custom transport options
  88          foreach ($this->getOption('transport.stream', array()) as $key => $value) {
  89              $options[$key] = $value;
  90          }
  91  
  92          // Add the proxy configuration, if any.
  93          $app = Factory::getApplication();
  94  
  95          if ($app->get('proxy_enable')) {
  96              $options['proxy'] = $app->get('proxy_host') . ':' . $app->get('proxy_port');
  97              $options['request_fulluri'] = true;
  98  
  99              // Put any required authorization into the headers array to be handled later
 100              // @todo: do we need to support any auth type other than Basic?
 101              if ($user = $app->get('proxy_user')) {
 102                  $auth = base64_encode($app->get('proxy_user') . ':' . $app->get('proxy_pass'));
 103  
 104                  $headers['Proxy-Authorization'] = 'Basic ' . $auth;
 105              }
 106          }
 107  
 108          // Build the headers string for the request.
 109          $headerEntries = array();
 110  
 111          if (isset($headers)) {
 112              foreach ($headers as $key => $value) {
 113                  $headerEntries[] = $key . ': ' . $value;
 114              }
 115  
 116              // Add the headers string into the stream context options array.
 117              $options['header'] = implode("\r\n", $headerEntries);
 118          }
 119  
 120          // Get the current context options.
 121          $contextOptions = stream_context_get_options(stream_context_get_default());
 122  
 123          // Add our options to the current ones, if any.
 124          $contextOptions['http'] = isset($contextOptions['http']) ? array_merge($contextOptions['http'], $options) : $options;
 125  
 126          // Create the stream context for the request.
 127          $context = stream_context_create(
 128              array(
 129                  'http' => $options,
 130                  'ssl' => array(
 131                      'verify_peer'      => true,
 132                      'cafile'           => $this->getOption('stream.certpath', CaBundle::getBundledCaBundlePath()),
 133                      'verify_depth'     => 5,
 134                      'verify_peer_name' => true,
 135                  ),
 136              )
 137          );
 138  
 139          // Authentication, if needed
 140          if ($uri instanceof Uri && $this->getOption('userauth') && $this->getOption('passwordauth')) {
 141              $uri->setUser($this->getOption('userauth'));
 142              $uri->setPass($this->getOption('passwordauth'));
 143          }
 144  
 145          // Capture PHP errors
 146          $php_errormsg = '';
 147          $track_errors = ini_get('track_errors');
 148          ini_set('track_errors', true);
 149  
 150          // Open the stream for reading.
 151          $stream = @fopen((string) $uri, 'r', false, $context);
 152  
 153          if (!$stream) {
 154              if (!$php_errormsg) {
 155                  // Error but nothing from php? Create our own
 156                  $php_errormsg = sprintf('Could not connect to resource: %s', $uri);
 157              }
 158  
 159              // Restore error tracking to give control to the exception handler
 160              ini_set('track_errors', $track_errors);
 161  
 162              throw new \RuntimeException($php_errormsg);
 163          }
 164  
 165          // Restore error tracking to what it was before.
 166          ini_set('track_errors', $track_errors);
 167  
 168          // Get the metadata for the stream, including response headers.
 169          $metadata = stream_get_meta_data($stream);
 170  
 171          // Get the contents from the stream.
 172          $content = stream_get_contents($stream);
 173  
 174          // Close the stream.
 175          fclose($stream);
 176  
 177          if (isset($metadata['wrapper_data']['headers'])) {
 178              $headers = $metadata['wrapper_data']['headers'];
 179          } elseif (isset($metadata['wrapper_data'])) {
 180              $headers = $metadata['wrapper_data'];
 181          } else {
 182              $headers = array();
 183          }
 184  
 185          return $this->getResponse($headers, $content);
 186      }
 187  
 188      /**
 189       * Method to get a response object from a server response.
 190       *
 191       * @param   array   $headers  The response headers as an array.
 192       * @param   string  $body     The response body as a string.
 193       *
 194       * @return  Response
 195       *
 196       * @since   1.7.3
 197       * @throws  InvalidResponseCodeException
 198       */
 199      protected function getResponse(array $headers, $body)
 200      {
 201          // Get the response code from the first offset of the response headers.
 202          preg_match('/[0-9]{3}/', array_shift($headers), $matches);
 203          $code = $matches[0];
 204  
 205          if (!is_numeric($code)) {
 206              // No valid response code was detected.
 207              throw new InvalidResponseCodeException('No HTTP response code found.');
 208          }
 209  
 210          $statusCode      = (int) $code;
 211          $verifiedHeaders = $this->processHeaders($headers);
 212  
 213          $streamInterface = new StreamResponse('php://memory', 'rw');
 214          $streamInterface->write($body);
 215  
 216          return new Response($streamInterface, $statusCode, $verifiedHeaders);
 217      }
 218  
 219      /**
 220       * Method to check if http transport stream available for use
 221       *
 222       * @return  boolean  true if available else false
 223       *
 224       * @since   3.0.0
 225       */
 226      public static function isSupported()
 227      {
 228          return \function_exists('fopen') && \is_callable('fopen') && ini_get('allow_url_fopen');
 229      }
 230  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer