[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Part of the Joomla Framework Http Package 4 * 5 * @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved. 6 * @license GNU General Public License version 2 or later; see LICENSE 7 */ 8 9 namespace Joomla\Http\Transport; 10 11 use Composer\CaBundle\CaBundle; 12 use Joomla\Http\AbstractTransport; 13 use Joomla\Http\Exception\InvalidResponseCodeException; 14 use Joomla\Http\Response; 15 use Joomla\Uri\Uri; 16 use Joomla\Uri\UriInterface; 17 use Laminas\Diactoros\Stream as StreamResponse; 18 19 /** 20 * HTTP transport class for using PHP streams. 21 * 22 * @since 1.0 23 */ 24 class Stream extends AbstractTransport 25 { 26 /** 27 * Send a request to the server and return a Response object with the response. 28 * 29 * @param string $method The HTTP method for sending the request. 30 * @param UriInterface $uri The URI to the resource to request. 31 * @param mixed $data Either an associative array or a string to be sent with the request. 32 * @param array $headers An array of request headers to send with the request. 33 * @param integer $timeout Read timeout in seconds. 34 * @param string $userAgent The optional user agent string to send with the request. 35 * 36 * @return Response 37 * 38 * @since 1.0 39 * @throws \RuntimeException 40 */ 41 public function request($method, UriInterface $uri, $data = null, array $headers = [], $timeout = null, $userAgent = null) 42 { 43 // Create the stream context options array with the required method offset. 44 $options = ['method' => strtoupper($method)]; 45 46 // If data exists let's encode it and make sure our Content-Type header is set. 47 if (isset($data)) 48 { 49 // If the data is a scalar value simply add it to the stream context options. 50 if (is_scalar($data)) 51 { 52 $options['content'] = $data; 53 } 54 else 55 { 56 // Otherwise we need to encode the value first. 57 $options['content'] = http_build_query($data); 58 } 59 60 if (!isset($headers['Content-Type'])) 61 { 62 $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'; 63 } 64 65 // Add the relevant headers. 66 $headers['Content-Length'] = \strlen($options['content']); 67 } 68 69 // If an explicit timeout is given user it. 70 if (isset($timeout)) 71 { 72 $options['timeout'] = (int) $timeout; 73 } 74 75 // If an explicit user agent is given use it. 76 if (isset($userAgent)) 77 { 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 // Configure protocol version, use transport's default if not set otherwise. 88 $options['follow_location'] = $this->getOption('protocolVersion', '1.0'); 89 90 // Add the proxy configuration if enabled 91 if ($this->getOption('proxy.enabled', false)) 92 { 93 $options['request_fulluri'] = true; 94 95 if ($this->getOption('proxy.host') && $this->getOption('proxy.port')) 96 { 97 $options['proxy'] = $this->getOption('proxy.host') . ':' . (int) $this->getOption('proxy.port'); 98 } 99 100 // If authentication details are provided, add those as well 101 if ($this->getOption('proxy.user') && $this->getOption('proxy.password')) 102 { 103 $headers['Proxy-Authorization'] = 'Basic ' . base64_encode($this->getOption('proxy.user') . ':' . $this->getOption('proxy.password')); 104 } 105 } 106 107 // Build the headers string for the request. 108 if (!empty($headers)) 109 { 110 $headerString = ''; 111 112 foreach ($headers as $key => $value) 113 { 114 if (\is_array($value)) 115 { 116 foreach ($value as $header) 117 { 118 $headerString .= "$key: $header\r\n"; 119 } 120 } 121 else 122 { 123 $headerString .= "$key: $value\r\n"; 124 } 125 } 126 127 // Add the headers string into the stream context options array. 128 $options['header'] = trim($headerString, "\r\n"); 129 } 130 131 // Authentication, if needed 132 if ($uri instanceof Uri && $this->getOption('userauth') && $this->getOption('passwordauth')) 133 { 134 $uri->setUser($this->getOption('userauth')); 135 $uri->setPass($this->getOption('passwordauth')); 136 } 137 138 // Set any custom transport options 139 foreach ($this->getOption('transport.stream', []) as $key => $value) 140 { 141 $options[$key] = $value; 142 } 143 144 // Get the current context options. 145 $contextOptions = stream_context_get_options(stream_context_get_default()); 146 147 // Add our options to the currently defined options, if any. 148 $contextOptions['http'] = isset($contextOptions['http']) ? array_merge($contextOptions['http'], $options) : $options; 149 150 // Create the stream context for the request. 151 $streamOptions = [ 152 'http' => $options, 153 'ssl' => [ 154 'verify_peer' => true, 155 'verify_depth' => 5, 156 'verify_peer_name' => true, 157 ], 158 ]; 159 160 // The cacert may be a file or path 161 $certpath = $this->getOption('stream.certpath', CaBundle::getSystemCaRootBundlePath()); 162 163 if (is_dir($certpath)) 164 { 165 $streamOptions['ssl']['capath'] = $certpath; 166 } 167 else 168 { 169 $streamOptions['ssl']['cafile'] = $certpath; 170 } 171 172 $context = stream_context_create($streamOptions); 173 174 // Capture PHP errors 175 $php_errormsg = ''; 176 $trackErrors = ini_get('track_errors'); 177 ini_set('track_errors', true); 178 179 // Open the stream for reading. 180 $stream = @fopen((string) $uri, 'r', false, $context); 181 182 if (!$stream) 183 { 184 if (!$php_errormsg) 185 { 186 // Error but nothing from php? Create our own 187 $php_errormsg = sprintf('Could not connect to resource: %s', $uri); 188 } 189 190 // Restore error tracking to give control to the exception handler 191 ini_set('track_errors', $trackErrors); 192 193 throw new \RuntimeException($php_errormsg); 194 } 195 196 // Restore error tracking to what it was before. 197 ini_set('track_errors', $trackErrors); 198 199 // Get the metadata for the stream, including response headers. 200 $metadata = stream_get_meta_data($stream); 201 202 // Get the contents from the stream. 203 $content = stream_get_contents($stream); 204 205 // Close the stream. 206 fclose($stream); 207 208 $headers = []; 209 210 if (isset($metadata['wrapper_data']['headers'])) 211 { 212 $headers = $metadata['wrapper_data']['headers']; 213 } 214 elseif (isset($metadata['wrapper_data'])) 215 { 216 $headers = $metadata['wrapper_data']; 217 } 218 219 return $this->getResponse($headers, $content); 220 } 221 222 /** 223 * Method to get a response object from a server response. 224 * 225 * @param array $headers The response headers as an array. 226 * @param string $body The response body as a string. 227 * 228 * @return Response 229 * 230 * @since 1.0 231 * @throws InvalidResponseCodeException 232 */ 233 protected function getResponse(array $headers, $body) 234 { 235 // Get the response code from the first offset of the response headers. 236 preg_match('/[0-9]{3}/', array_shift($headers), $matches); 237 $code = $matches[0]; 238 239 if (!is_numeric($code)) 240 { 241 // No valid response code was detected. 242 throw new InvalidResponseCodeException('No HTTP response code found.'); 243 } 244 245 $statusCode = (int) $code; 246 $verifiedHeaders = $this->processHeaders($headers); 247 248 $streamInterface = new StreamResponse('php://memory', 'rw'); 249 $streamInterface->write($body); 250 251 return new Response($streamInterface, $statusCode, $verifiedHeaders); 252 } 253 254 /** 255 * Method to check if http transport stream available for use 256 * 257 * @return boolean True if available else false 258 * 259 * @since 1.0 260 */ 261 public static function isSupported() 262 { 263 return \function_exists('fopen') && \is_callable('fopen') && ini_get('allow_url_fopen'); 264 } 265 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |