Request.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <?php
  2. declare(strict_types=1);
  3. namespace GuzzleHttp\Psr7;
  4. use InvalidArgumentException;
  5. use Psr\Http\Message\RequestInterface;
  6. use Psr\Http\Message\StreamInterface;
  7. use Psr\Http\Message\UriInterface;
  8. /**
  9. * PSR-7 request implementation.
  10. */
  11. class Request implements RequestInterface
  12. {
  13. use MessageTrait;
  14. /** @var string */
  15. private $method;
  16. /** @var string|null */
  17. private $requestTarget;
  18. /** @var UriInterface */
  19. private $uri;
  20. /**
  21. * @param string $method HTTP method
  22. * @param string|UriInterface $uri URI
  23. * @param array<string, string|string[]> $headers Request headers
  24. * @param string|resource|StreamInterface|null $body Request body
  25. * @param string $version Protocol version
  26. */
  27. public function __construct(
  28. string $method,
  29. $uri,
  30. array $headers = [],
  31. $body = null,
  32. string $version = '1.1'
  33. ) {
  34. $this->assertMethod($method);
  35. if (!($uri instanceof UriInterface)) {
  36. $uri = new Uri($uri);
  37. }
  38. $this->method = strtoupper($method);
  39. $this->uri = $uri;
  40. $this->setHeaders($headers);
  41. $this->protocol = $version;
  42. if (!isset($this->headerNames['host'])) {
  43. $this->updateHostFromUri();
  44. }
  45. if ($body !== '' && $body !== null) {
  46. $this->stream = Utils::streamFor($body);
  47. }
  48. }
  49. public function getRequestTarget(): string
  50. {
  51. if ($this->requestTarget !== null) {
  52. return $this->requestTarget;
  53. }
  54. $target = $this->uri->getPath();
  55. if ($target === '') {
  56. $target = '/';
  57. }
  58. if ($this->uri->getQuery() != '') {
  59. $target .= '?' . $this->uri->getQuery();
  60. }
  61. return $target;
  62. }
  63. public function withRequestTarget($requestTarget): RequestInterface
  64. {
  65. if (preg_match('#\s#', $requestTarget)) {
  66. throw new InvalidArgumentException(
  67. 'Invalid request target provided; cannot contain whitespace'
  68. );
  69. }
  70. $new = clone $this;
  71. $new->requestTarget = $requestTarget;
  72. return $new;
  73. }
  74. public function getMethod(): string
  75. {
  76. return $this->method;
  77. }
  78. public function withMethod($method): RequestInterface
  79. {
  80. $this->assertMethod($method);
  81. $new = clone $this;
  82. $new->method = strtoupper($method);
  83. return $new;
  84. }
  85. public function getUri(): UriInterface
  86. {
  87. return $this->uri;
  88. }
  89. public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface
  90. {
  91. if ($uri === $this->uri) {
  92. return $this;
  93. }
  94. $new = clone $this;
  95. $new->uri = $uri;
  96. if (!$preserveHost || !isset($this->headerNames['host'])) {
  97. $new->updateHostFromUri();
  98. }
  99. return $new;
  100. }
  101. private function updateHostFromUri(): void
  102. {
  103. $host = $this->uri->getHost();
  104. if ($host == '') {
  105. return;
  106. }
  107. if (($port = $this->uri->getPort()) !== null) {
  108. $host .= ':' . $port;
  109. }
  110. if (isset($this->headerNames['host'])) {
  111. $header = $this->headerNames['host'];
  112. } else {
  113. $header = 'Host';
  114. $this->headerNames['host'] = 'Host';
  115. }
  116. // Ensure Host is the first header.
  117. // See: http://tools.ietf.org/html/rfc7230#section-5.4
  118. $this->headers = [$header => [$host]] + $this->headers;
  119. }
  120. /**
  121. * @param mixed $method
  122. */
  123. private function assertMethod($method): void
  124. {
  125. if (!is_string($method) || $method === '') {
  126. throw new InvalidArgumentException('Method must be a non-empty string.');
  127. }
  128. }
  129. }