[ Index ]

PHP Cross Reference of phpBB-3.3.12-deutsch

title

Body

[close]

/vendor/guzzlehttp/psr7/src/ -> Message.php (source)

   1  <?php
   2  
   3  namespace GuzzleHttp\Psr7;
   4  
   5  use Psr\Http\Message\MessageInterface;
   6  use Psr\Http\Message\RequestInterface;
   7  use Psr\Http\Message\ResponseInterface;
   8  
   9  final class Message
  10  {
  11      /**
  12       * Returns the string representation of an HTTP message.
  13       *
  14       * @param MessageInterface $message Message to convert to a string.
  15       *
  16       * @return string
  17       */
  18      public static function toString(MessageInterface $message)
  19      {
  20          if ($message instanceof RequestInterface) {
  21              $msg = trim($message->getMethod() . ' '
  22                      . $message->getRequestTarget())
  23                  . ' HTTP/' . $message->getProtocolVersion();
  24              if (!$message->hasHeader('host')) {
  25                  $msg .= "\r\nHost: " . $message->getUri()->getHost();
  26              }
  27          } elseif ($message instanceof ResponseInterface) {
  28              $msg = 'HTTP/' . $message->getProtocolVersion() . ' '
  29                  . $message->getStatusCode() . ' '
  30                  . $message->getReasonPhrase();
  31          } else {
  32              throw new \InvalidArgumentException('Unknown message type');
  33          }
  34  
  35          foreach ($message->getHeaders() as $name => $values) {
  36              if (strtolower($name) === 'set-cookie') {
  37                  foreach ($values as $value) {
  38                      $msg .= "\r\n{$name}: " . $value;
  39                  }
  40              } else {
  41                  $msg .= "\r\n{$name}: " . implode(', ', $values);
  42              }
  43          }
  44  
  45          return "{$msg}\r\n\r\n" . $message->getBody();
  46      }
  47  
  48      /**
  49       * Get a short summary of the message body.
  50       *
  51       * Will return `null` if the response is not printable.
  52       *
  53       * @param MessageInterface $message    The message to get the body summary
  54       * @param int              $truncateAt The maximum allowed size of the summary
  55       *
  56       * @return string|null
  57       */
  58      public static function bodySummary(MessageInterface $message, $truncateAt = 120)
  59      {
  60          $body = $message->getBody();
  61  
  62          if (!$body->isSeekable() || !$body->isReadable()) {
  63              return null;
  64          }
  65  
  66          $size = $body->getSize();
  67  
  68          if ($size === 0) {
  69              return null;
  70          }
  71  
  72          $summary = $body->read($truncateAt);
  73          $body->rewind();
  74  
  75          if ($size > $truncateAt) {
  76              $summary .= ' (truncated...)';
  77          }
  78  
  79          // Matches any printable character, including unicode characters:
  80          // letters, marks, numbers, punctuation, spacing, and separators.
  81          if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/u', $summary)) {
  82              return null;
  83          }
  84  
  85          return $summary;
  86      }
  87  
  88      /**
  89       * Attempts to rewind a message body and throws an exception on failure.
  90       *
  91       * The body of the message will only be rewound if a call to `tell()`
  92       * returns a value other than `0`.
  93       *
  94       * @param MessageInterface $message Message to rewind
  95       *
  96       * @throws \RuntimeException
  97       */
  98      public static function rewindBody(MessageInterface $message)
  99      {
 100          $body = $message->getBody();
 101  
 102          if ($body->tell()) {
 103              $body->rewind();
 104          }
 105      }
 106  
 107      /**
 108       * Parses an HTTP message into an associative array.
 109       *
 110       * The array contains the "start-line" key containing the start line of
 111       * the message, "headers" key containing an associative array of header
 112       * array values, and a "body" key containing the body of the message.
 113       *
 114       * @param string $message HTTP request or response to parse.
 115       *
 116       * @return array
 117       */
 118      public static function parseMessage($message)
 119      {
 120          if (!$message) {
 121              throw new \InvalidArgumentException('Invalid message');
 122          }
 123  
 124          $message = ltrim($message, "\r\n");
 125  
 126          $messageParts = preg_split("/\r?\n\r?\n/", $message, 2);
 127  
 128          if ($messageParts === false || count($messageParts) !== 2) {
 129              throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
 130          }
 131  
 132          list($rawHeaders, $body) = $messageParts;
 133          $rawHeaders .= "\r\n"; // Put back the delimiter we split previously
 134          $headerParts = preg_split("/\r?\n/", $rawHeaders, 2);
 135  
 136          if ($headerParts === false || count($headerParts) !== 2) {
 137              throw new \InvalidArgumentException('Invalid message: Missing status line');
 138          }
 139  
 140          list($startLine, $rawHeaders) = $headerParts;
 141  
 142          if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
 143              // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
 144              $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
 145          }
 146  
 147          /** @var array[] $headerLines */
 148          $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER);
 149  
 150          // If these aren't the same, then one line didn't match and there's an invalid header.
 151          if ($count !== substr_count($rawHeaders, "\n")) {
 152              // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4
 153              if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {
 154                  throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding');
 155              }
 156  
 157              throw new \InvalidArgumentException('Invalid header syntax');
 158          }
 159  
 160          $headers = [];
 161  
 162          foreach ($headerLines as $headerLine) {
 163              $headers[$headerLine[1]][] = $headerLine[2];
 164          }
 165  
 166          return [
 167              'start-line' => $startLine,
 168              'headers' => $headers,
 169              'body' => $body,
 170          ];
 171      }
 172  
 173      /**
 174       * Constructs a URI for an HTTP request message.
 175       *
 176       * @param string $path    Path from the start-line
 177       * @param array  $headers Array of headers (each value an array).
 178       *
 179       * @return string
 180       */
 181      public static function parseRequestUri($path, array $headers)
 182      {
 183          $hostKey = array_filter(array_keys($headers), function ($k) {
 184              return strtolower($k) === 'host';
 185          });
 186  
 187          // If no host is found, then a full URI cannot be constructed.
 188          if (!$hostKey) {
 189              return $path;
 190          }
 191  
 192          $host = $headers[reset($hostKey)][0];
 193          $scheme = substr($host, -4) === ':443' ? 'https' : 'http';
 194  
 195          return $scheme . '://' . $host . '/' . ltrim($path, '/');
 196      }
 197  
 198      /**
 199       * Parses a request message string into a request object.
 200       *
 201       * @param string $message Request message string.
 202       *
 203       * @return Request
 204       */
 205      public static function parseRequest($message)
 206      {
 207          $data = self::parseMessage($message);
 208          $matches = [];
 209          if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) {
 210              throw new \InvalidArgumentException('Invalid request string');
 211          }
 212          $parts = explode(' ', $data['start-line'], 3);
 213          $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1';
 214  
 215          $request = new Request(
 216              $parts[0],
 217              $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1],
 218              $data['headers'],
 219              $data['body'],
 220              $version
 221          );
 222  
 223          return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]);
 224      }
 225  
 226      /**
 227       * Parses a response message string into a response object.
 228       *
 229       * @param string $message Response message string.
 230       *
 231       * @return Response
 232       */
 233      public static function parseResponse($message)
 234      {
 235          $data = self::parseMessage($message);
 236          // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
 237          // between status-code and reason-phrase is required. But browsers accept
 238          // responses without space and reason as well.
 239          if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
 240              throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']);
 241          }
 242          $parts = explode(' ', $data['start-line'], 3);
 243  
 244          return new Response(
 245              (int) $parts[1],
 246              $data['headers'],
 247              $data['body'],
 248              explode('/', $parts[0])[1],
 249              isset($parts[2]) ? $parts[2] : null
 250          );
 251      }
 252  }


Generated: Sun Jun 23 12:25:44 2024 Cross-referenced by PHPXref 0.7.1