Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Client.php

Zuletzt modifiziert: 01.05.2026, 11:26 - Dateigröße: 18.86 KiB


 001  <?php
 002  namespace GuzzleHttp;
 003   
 004  use GuzzleHttp\Cookie\CookieJar;
 005  use GuzzleHttp\Exception\GuzzleException;
 006  use GuzzleHttp\Promise;
 007  use GuzzleHttp\Psr7;
 008  use Psr\Http\Message\RequestInterface;
 009  use Psr\Http\Message\ResponseInterface;
 010  use Psr\Http\Message\UriInterface;
 011   
 012  /**
 013   * @method ResponseInterface get(string|UriInterface $uri, array $options = [])
 014   * @method ResponseInterface head(string|UriInterface $uri, array $options = [])
 015   * @method ResponseInterface put(string|UriInterface $uri, array $options = [])
 016   * @method ResponseInterface post(string|UriInterface $uri, array $options = [])
 017   * @method ResponseInterface patch(string|UriInterface $uri, array $options = [])
 018   * @method ResponseInterface delete(string|UriInterface $uri, array $options = [])
 019   * @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = [])
 020   * @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = [])
 021   * @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = [])
 022   * @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = [])
 023   * @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
 024   * @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
 025   */
 026  class Client implements ClientInterface
 027  {
 028      /** @var array Default request options */
 029      private $config;
 030   
 031      /**
 032       * Clients accept an array of constructor parameters.
 033       *
 034       * Here's an example of creating a client using a base_uri and an array of
 035       * default request options to apply to each request:
 036       *
 037       *     $client = new Client([
 038       *         'base_uri'        => 'http://www.foo.com/1.0/',
 039       *         'timeout'         => 0,
 040       *         'allow_redirects' => false,
 041       *         'proxy'           => '192.168.16.1:10'
 042       *     ]);
 043       *
 044       * Client configuration settings include the following options:
 045       *
 046       * - handler: (callable) Function that transfers HTTP requests over the
 047       *   wire. The function is called with a Psr7\Http\Message\RequestInterface
 048       *   and array of transfer options, and must return a
 049       *   GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
 050       *   Psr7\Http\Message\ResponseInterface on success.
 051       *   If no handler is provided, a default handler will be created
 052       *   that enables all of the request options below by attaching all of the
 053       *   default middleware to the handler.
 054       * - base_uri: (string|UriInterface) Base URI of the client that is merged
 055       *   into relative URIs. Can be a string or instance of UriInterface.
 056       * - **: any request option
 057       *
 058       * @param array $config Client configuration settings.
 059       *
 060       * @see \GuzzleHttp\RequestOptions for a list of available request options.
 061       */
 062      public function __construct(array $config = [])
 063      {
 064          if (!isset($config['handler'])) {
 065              $config['handler'] = HandlerStack::create();
 066          } elseif (!is_callable($config['handler'])) {
 067              throw new \InvalidArgumentException('handler must be a callable');
 068          }
 069   
 070          // Convert the base_uri to a UriInterface
 071          if (isset($config['base_uri'])) {
 072              $config['base_uri'] = Psr7\uri_for($config['base_uri']);
 073          }
 074   
 075          $this->configureDefaults($config);
 076      }
 077   
 078      /**
 079       * @param string $method
 080       * @param array  $args
 081       *
 082       * @return Promise\PromiseInterface
 083       */
 084      public function __call($method, $args)
 085      {
 086          if (count($args) < 1) {
 087              throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
 088          }
 089   
 090          $uri = $args[0];
 091          $opts = isset($args[1]) ? $args[1] : [];
 092   
 093          return substr($method, -5) === 'Async'
 094              ? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
 095              : $this->request($method, $uri, $opts);
 096      }
 097   
 098      /**
 099       * Asynchronously send an HTTP request.
 100       *
 101       * @param array $options Request options to apply to the given
 102       *                       request and to the transfer. See \GuzzleHttp\RequestOptions.
 103       *
 104       * @return Promise\PromiseInterface
 105       */
 106      public function sendAsync(RequestInterface $request, array $options = [])
 107      {
 108          // Merge the base URI into the request URI if needed.
 109          $options = $this->prepareDefaults($options);
 110   
 111          return $this->transfer(
 112              $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
 113              $options
 114          );
 115      }
 116   
 117      /**
 118       * Send an HTTP request.
 119       *
 120       * @param array $options Request options to apply to the given
 121       *                       request and to the transfer. See \GuzzleHttp\RequestOptions.
 122       *
 123       * @return ResponseInterface
 124       * @throws GuzzleException
 125       */
 126      public function send(RequestInterface $request, array $options = [])
 127      {
 128          $options[RequestOptions::SYNCHRONOUS] = true;
 129          return $this->sendAsync($request, $options)->wait();
 130      }
 131   
 132      /**
 133       * Create and send an asynchronous HTTP request.
 134       *
 135       * Use an absolute path to override the base path of the client, or a
 136       * relative path to append to the base path of the client. The URL can
 137       * contain the query string as well. Use an array to provide a URL
 138       * template and additional variables to use in the URL template expansion.
 139       *
 140       * @param string              $method  HTTP method
 141       * @param string|UriInterface $uri     URI object or string.
 142       * @param array               $options Request options to apply. See \GuzzleHttp\RequestOptions.
 143       *
 144       * @return Promise\PromiseInterface
 145       */
 146      public function requestAsync($method, $uri = '', array $options = [])
 147      {
 148          $options = $this->prepareDefaults($options);
 149          // Remove request modifying parameter because it can be done up-front.
 150          $headers = isset($options['headers']) ? $options['headers'] : [];
 151          $body = isset($options['body']) ? $options['body'] : null;
 152          $version = isset($options['version']) ? $options['version'] : '1.1';
 153          // Merge the URI into the base URI.
 154          $uri = $this->buildUri($uri, $options);
 155          if (is_array($body)) {
 156              $this->invalidBody();
 157          }
 158          $request = new Psr7\Request($method, $uri, $headers, $body, $version);
 159          // Remove the option so that they are not doubly-applied.
 160          unset($options['headers'], $options['body'], $options['version']);
 161   
 162          return $this->transfer($request, $options);
 163      }
 164   
 165      /**
 166       * Create and send an HTTP request.
 167       *
 168       * Use an absolute path to override the base path of the client, or a
 169       * relative path to append to the base path of the client. The URL can
 170       * contain the query string as well.
 171       *
 172       * @param string              $method  HTTP method.
 173       * @param string|UriInterface $uri     URI object or string.
 174       * @param array               $options Request options to apply. See \GuzzleHttp\RequestOptions.
 175       *
 176       * @return ResponseInterface
 177       * @throws GuzzleException
 178       */
 179      public function request($method, $uri = '', array $options = [])
 180      {
 181          $options[RequestOptions::SYNCHRONOUS] = true;
 182          return $this->requestAsync($method, $uri, $options)->wait();
 183      }
 184   
 185      /**
 186       * Get a client configuration option.
 187       *
 188       * These options include default request options of the client, a "handler"
 189       * (if utilized by the concrete client), and a "base_uri" if utilized by
 190       * the concrete client.
 191       *
 192       * @param string|null $option The config option to retrieve.
 193       *
 194       * @return mixed
 195       */
 196      public function getConfig($option = null)
 197      {
 198          return $option === null
 199              ? $this->config
 200              : (isset($this->config[$option]) ? $this->config[$option] : null);
 201      }
 202   
 203      /**
 204       * @param  string|null $uri
 205       *
 206       * @return UriInterface
 207       */
 208      private function buildUri($uri, array $config)
 209      {
 210          // for BC we accept null which would otherwise fail in uri_for
 211          $uri = Psr7\uri_for($uri === null ? '' : $uri);
 212   
 213          if (isset($config['base_uri'])) {
 214              $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
 215          }
 216   
 217          if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
 218              $idnOptions = ($config['idn_conversion'] === true) ? IDNA_DEFAULT : $config['idn_conversion'];
 219              $uri = Utils::idnUriConvert($uri, $idnOptions);
 220          }
 221   
 222          return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
 223      }
 224   
 225      /**
 226       * Configures the default options for a client.
 227       *
 228       * @param array $config
 229       * @return void
 230       */
 231      private function configureDefaults(array $config)
 232      {
 233          $defaults = [
 234              'allow_redirects' => RedirectMiddleware::$defaultSettings,
 235              'http_errors'     => true,
 236              'decode_content'  => true,
 237              'verify'          => true,
 238              'cookies'         => false,
 239              'idn_conversion'  => true,
 240          ];
 241   
 242          // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
 243   
 244          // We can only trust the HTTP_PROXY environment variable in a CLI
 245          // process due to the fact that PHP has no reliable mechanism to
 246          // get environment variables that start with "HTTP_".
 247          if (php_sapi_name() === 'cli' && getenv('HTTP_PROXY')) {
 248              $defaults['proxy']['http'] = getenv('HTTP_PROXY');
 249          }
 250   
 251          if ($proxy = getenv('HTTPS_PROXY')) {
 252              $defaults['proxy']['https'] = $proxy;
 253          }
 254   
 255          if ($noProxy = getenv('NO_PROXY')) {
 256              $cleanedNoProxy = str_replace(' ', '', $noProxy);
 257              $defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
 258          }
 259   
 260          $this->config = $config + $defaults;
 261   
 262          if (!empty($config['cookies']) && $config['cookies'] === true) {
 263              $this->config['cookies'] = new CookieJar();
 264          }
 265   
 266          // Add the default user-agent header.
 267          if (!isset($this->config['headers'])) {
 268              $this->config['headers'] = ['User-Agent' => default_user_agent()];
 269          } else {
 270              // Add the User-Agent header if one was not already set.
 271              foreach (array_keys($this->config['headers']) as $name) {
 272                  if (strtolower($name) === 'user-agent') {
 273                      return;
 274                  }
 275              }
 276              $this->config['headers']['User-Agent'] = default_user_agent();
 277          }
 278      }
 279   
 280      /**
 281       * Merges default options into the array.
 282       *
 283       * @param array $options Options to modify by reference
 284       *
 285       * @return array
 286       */
 287      private function prepareDefaults(array $options)
 288      {
 289          $defaults = $this->config;
 290   
 291          if (!empty($defaults['headers'])) {
 292              // Default headers are only added if they are not present.
 293              $defaults['_conditional'] = $defaults['headers'];
 294              unset($defaults['headers']);
 295          }
 296   
 297          // Special handling for headers is required as they are added as
 298          // conditional headers and as headers passed to a request ctor.
 299          if (array_key_exists('headers', $options)) {
 300              // Allows default headers to be unset.
 301              if ($options['headers'] === null) {
 302                  $defaults['_conditional'] = [];
 303                  unset($options['headers']);
 304              } elseif (!is_array($options['headers'])) {
 305                  throw new \InvalidArgumentException('headers must be an array');
 306              }
 307          }
 308   
 309          // Shallow merge defaults underneath options.
 310          $result = $options + $defaults;
 311   
 312          // Remove null values.
 313          foreach ($result as $k => $v) {
 314              if ($v === null) {
 315                  unset($result[$k]);
 316              }
 317          }
 318   
 319          return $result;
 320      }
 321   
 322      /**
 323       * Transfers the given request and applies request options.
 324       *
 325       * The URI of the request is not modified and the request options are used
 326       * as-is without merging in default options.
 327       *
 328       * @param array $options See \GuzzleHttp\RequestOptions.
 329       *
 330       * @return Promise\PromiseInterface
 331       */
 332      private function transfer(RequestInterface $request, array $options)
 333      {
 334          // save_to -> sink
 335          if (isset($options['save_to'])) {
 336              $options['sink'] = $options['save_to'];
 337              unset($options['save_to']);
 338          }
 339   
 340          // exceptions -> http_errors
 341          if (isset($options['exceptions'])) {
 342              $options['http_errors'] = $options['exceptions'];
 343              unset($options['exceptions']);
 344          }
 345   
 346          $request = $this->applyOptions($request, $options);
 347          /** @var HandlerStack $handler */
 348          $handler = $options['handler'];
 349   
 350          try {
 351              return Promise\promise_for($handler($request, $options));
 352          } catch (\Exception $e) {
 353              return Promise\rejection_for($e);
 354          }
 355      }
 356   
 357      /**
 358       * Applies the array of request options to a request.
 359       *
 360       * @param RequestInterface $request
 361       * @param array            $options
 362       *
 363       * @return RequestInterface
 364       */
 365      private function applyOptions(RequestInterface $request, array &$options)
 366      {
 367          $modify = [
 368              'set_headers' => [],
 369          ];
 370   
 371          if (isset($options['headers'])) {
 372              $modify['set_headers'] = $options['headers'];
 373              unset($options['headers']);
 374          }
 375   
 376          if (isset($options['form_params'])) {
 377              if (isset($options['multipart'])) {
 378                  throw new \InvalidArgumentException('You cannot use '
 379                      . 'form_params and multipart at the same time. Use the '
 380                      . 'form_params option if you want to send application/'
 381                      . 'x-www-form-urlencoded requests, and the multipart '
 382                      . 'option to send multipart/form-data requests.');
 383              }
 384              $options['body'] = http_build_query($options['form_params'], '', '&');
 385              unset($options['form_params']);
 386              // Ensure that we don't have the header in different case and set the new value.
 387              $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
 388              $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
 389          }
 390   
 391          if (isset($options['multipart'])) {
 392              $options['body'] = new Psr7\MultipartStream($options['multipart']);
 393              unset($options['multipart']);
 394          }
 395   
 396          if (isset($options['json'])) {
 397              $options['body'] = \GuzzleHttp\json_encode($options['json']);
 398              unset($options['json']);
 399              // Ensure that we don't have the header in different case and set the new value.
 400              $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
 401              $options['_conditional']['Content-Type'] = 'application/json';
 402          }
 403   
 404          if (!empty($options['decode_content'])
 405              && $options['decode_content'] !== true
 406          ) {
 407              // Ensure that we don't have the header in different case and set the new value.
 408              $options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
 409              $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
 410          }
 411   
 412          if (isset($options['body'])) {
 413              if (is_array($options['body'])) {
 414                  $this->invalidBody();
 415              }
 416              $modify['body'] = Psr7\stream_for($options['body']);
 417              unset($options['body']);
 418          }
 419   
 420          if (!empty($options['auth']) && is_array($options['auth'])) {
 421              $value = $options['auth'];
 422              $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
 423              switch ($type) {
 424                  case 'basic':
 425                      // Ensure that we don't have the header in different case and set the new value.
 426                      $modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
 427                      $modify['set_headers']['Authorization'] = 'Basic '
 428                          . base64_encode("$value[0]:$value[1]");
 429                      break;
 430                  case 'digest':
 431                      // @todo: Do not rely on curl
 432                      $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
 433                      $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
 434                      break;
 435                  case 'ntlm':
 436                      $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
 437                      $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
 438                      break;
 439              }
 440          }
 441   
 442          if (isset($options['query'])) {
 443              $value = $options['query'];
 444              if (is_array($value)) {
 445                  $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
 446              }
 447              if (!is_string($value)) {
 448                  throw new \InvalidArgumentException('query must be a string or array');
 449              }
 450              $modify['query'] = $value;
 451              unset($options['query']);
 452          }
 453   
 454          // Ensure that sink is not an invalid value.
 455          if (isset($options['sink'])) {
 456              // TODO: Add more sink validation?
 457              if (is_bool($options['sink'])) {
 458                  throw new \InvalidArgumentException('sink must not be a boolean');
 459              }
 460          }
 461   
 462          $request = Psr7\modify_request($request, $modify);
 463          if ($request->getBody() instanceof Psr7\MultipartStream) {
 464              // Use a multipart/form-data POST if a Content-Type is not set.
 465              // Ensure that we don't have the header in different case and set the new value.
 466              $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
 467              $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
 468                  . $request->getBody()->getBoundary();
 469          }
 470   
 471          // Merge in conditional headers if they are not present.
 472          if (isset($options['_conditional'])) {
 473              // Build up the changes so it's in a single clone of the message.
 474              $modify = [];
 475              foreach ($options['_conditional'] as $k => $v) {
 476                  if (!$request->hasHeader($k)) {
 477                      $modify['set_headers'][$k] = $v;
 478                  }
 479              }
 480              $request = Psr7\modify_request($request, $modify);
 481              // Don't pass this internal value along to middleware/handlers.
 482              unset($options['_conditional']);
 483          }
 484   
 485          return $request;
 486      }
 487   
 488      /**
 489       * Throw Exception with pre-set message.
 490       * @return void
 491       * @throws \InvalidArgumentException Invalid body.
 492       */
 493      private function invalidBody()
 494      {
 495          throw new \InvalidArgumentException('Passing in the "body" request '
 496              . 'option as an array to send a POST request has been deprecated. '
 497              . 'Please use the "form_params" request option to send a '
 498              . 'application/x-www-form-urlencoded request, or the "multipart" '
 499              . 'request option to send a multipart/form-data request.');
 500      }
 501  }
 502