Skip to content

Commit

Permalink
Merge pull request #6698 from kenjis/add-OutgoingRequestInterface
Browse files Browse the repository at this point in the history
feat: add OutgoingRequestInterface
  • Loading branch information
kenjis authored Oct 28, 2022
2 parents 1abb1f4 + 583689c commit 949b622
Show file tree
Hide file tree
Showing 10 changed files with 400 additions and 40 deletions.
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
namespace App\Controllers;

use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
Expand All @@ -24,7 +22,7 @@ abstract class BaseController extends Controller
/**
* Instance of the main Request object.
*
* @var CLIRequest|IncomingRequest
* @var RequestInterface
*/
protected $request;

Expand Down
10 changes: 5 additions & 5 deletions phpstan-baseline.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,6 @@ parameters:
count: 1
path: system/HTTP/Request.php

-
message: "#^Property CodeIgniter\\\\HTTP\\\\Request\\:\\:\\$uri \\(CodeIgniter\\\\HTTP\\\\URI\\) in empty\\(\\) is not falsy\\.$#"
count: 1
path: system/HTTP/Request.php

-
message: "#^Property CodeIgniter\\\\HTTP\\\\URI\\:\\:\\$fragment \\(string\\) on left side of \\?\\? is not nullable\\.$#"
count: 1
Expand Down Expand Up @@ -459,3 +454,8 @@ parameters:
message: "#^Property Config\\\\View\\:\\:\\$plugins \\(array\\) on left side of \\?\\? is not nullable\\.$#"
count: 1
path: system/View/Parser.php

-
message: "#^Constructor of class CodeIgniter\\\\HTTP\\\\CURLRequest has an unused parameter \\$config\\.$#"
count: 1
path: system/HTTP/CURLRequest.php
4 changes: 2 additions & 2 deletions system/HTTP/CURLRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
* A lightweight HTTP client for sending synchronous HTTP requests via cURL.
*/
class CURLRequest extends Request
class CURLRequest extends OutgoingRequest
{
/**
* The response object associated with this request
Expand Down Expand Up @@ -103,7 +103,7 @@ public function __construct(App $config, URI $uri, ?ResponseInterface $response
throw HTTPException::forMissingCurl(); // @codeCoverageIgnore
}

parent::__construct($config);
parent::__construct('GET', $uri);

$this->response = $response;
$this->baseURI = $uri->useRawQueryString();
Expand Down
4 changes: 4 additions & 0 deletions system/HTTP/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public function getBody()
*
* @deprecated Use Message::headers() to make room for PSR-7
*
* @TODO Incompatible return value with PSR-7
*
* @codeCoverageIgnore
*/
public function getHeaders(): array
Expand All @@ -76,6 +78,8 @@ public function getHeaders(): array
*
* @deprecated Use Message::header() to make room for PSR-7
*
* @TODO Incompatible return value with PSR-7
*
* @codeCoverageIgnore
*/
public function getHeader(string $name)
Expand Down
161 changes: 161 additions & 0 deletions system/HTTP/OutgoingRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\HTTP;

/**
* Representation of an outgoing, client-side request.
*/
class OutgoingRequest extends Message implements OutgoingRequestInterface
{
/**
* Request method.
*
* @var string
*/
protected $method;

/**
* A URI instance.
*
* @var URI|null
*/
protected $uri;

/**
* @param string $method HTTP method
* @param string|null $body
*/
public function __construct(
string $method,
?URI $uri = null,
array $headers = [],
$body = null,
string $version = '1.1'
) {
$this->method = $method;
$this->uri = $uri;

foreach ($headers as $header => $value) {
$this->setHeader($header, $value);
}

$this->body = $body;
$this->protocolVersion = $version;

if (! $this->hasHeader('Host') && $this->uri->getHost() !== '') {
$this->setHeader('Host', $this->getHostFromUri($this->uri));
}
}

private function getHostFromUri(URI $uri): string
{
$host = $uri->getHost();

return $host . ($uri->getPort() ? ':' . $uri->getPort() : '');
}

/**
* Get the request method.
*
* @param bool $upper Whether to return in upper or lower case.
*
* @deprecated The $upper functionality will be removed and this will revert to its PSR-7 equivalent
*/
public function getMethod(bool $upper = false): string
{
return ($upper) ? strtoupper($this->method) : strtolower($this->method);
}

/**
* Sets the request method. Used when spoofing the request.
*
* @return $this
*
* @deprecated Use withMethod() instead for immutability
*/
public function setMethod(string $method)
{
$this->method = $method;

return $this;
}

/**
* Returns an instance with the specified method.
*
* @param string $method
*
* @return static
*/
public function withMethod($method)
{
$request = clone $this;
$request->method = $method;

return $request;
}

/**
* Retrieves the URI instance.
*
* @return URI|null
*/
public function getUri()
{
return $this->uri;
}

/**
* Returns an instance with the provided URI.
*
* @param URI $uri New request URI to use.
* @param bool $preserveHost Preserve the original state of the Host header.
*
* @return static
*/
public function withUri(URI $uri, $preserveHost = false)
{
$request = clone $this;
$request->uri = $uri;

if ($preserveHost) {
if ($this->isHostHeaderMissingOrEmpty() && $uri->getHost() !== '') {
$request->setHeader('Host', $this->getHostFromUri($uri));

return $request;
}

if ($this->isHostHeaderMissingOrEmpty() && $uri->getHost() === '') {
return $request;
}

if (! $this->isHostHeaderMissingOrEmpty()) {
return $request;
}
}

if ($uri->getHost() !== '') {
$request->setHeader('Host', $this->getHostFromUri($uri));
}

return $request;
}

private function isHostHeaderMissingOrEmpty(): bool
{
if (! $this->hasHeader('Host')) {
return true;
}

return $this->header('Host')->getValue() === '';
}
}
94 changes: 94 additions & 0 deletions system/HTTP/OutgoingRequestInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\HTTP;

use InvalidArgumentException;

/**
* Representation of an outgoing, client-side request.
*
* Corresponds to Psr7\RequestInterface.
*/
interface OutgoingRequestInterface extends MessageInterface
{
/**
* Get the request method.
* An extension of PSR-7's getMethod to allow casing.
*
* @param bool $upper Whether to return in upper or lower case.
*
* @deprecated The $upper functionality will be removed and this will revert to its PSR-7 equivalent
*/
public function getMethod(bool $upper = false): string;

/**
* Return an instance with the provided HTTP method.
*
* While HTTP method names are typically all uppercase characters, HTTP
* method names are case-sensitive and thus implementations SHOULD NOT
* modify the given string.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* changed request method.
*
* @param string $method Case-sensitive method.
*
* @return static
*
* @throws InvalidArgumentException for invalid HTTP methods.
*/
public function withMethod($method);

/**
* Retrieves the URI instance.
*
* @see http://tools.ietf.org/html/rfc3986#section-4.3
*
* @return URI
*/
public function getUri();

/**
* Returns an instance with the provided URI.
*
* This method MUST update the Host header of the returned request by
* default if the URI contains a host component. If the URI does not
* contain a host component, any pre-existing Host header MUST be carried
* over to the returned request.
*
* You can opt-in to preserving the original state of the Host header by
* setting `$preserveHost` to `true`. When `$preserveHost` is set to
* `true`, this method interacts with the Host header in the following ways:
*
* - If the Host header is missing or empty, and the new URI contains
* a host component, this method MUST update the Host header in the returned
* request.
* - If the Host header is missing or empty, and the new URI does not contain a
* host component, this method MUST NOT update the Host header in the returned
* request.
* - If a Host header is present and non-empty, this method MUST NOT update
* the Host header in the returned request.
*
* This method MUST be implemented in such a way as to retain the
* immutability of the message, and MUST return an instance that has the
* new UriInterface instance.
*
* @see http://tools.ietf.org/html/rfc3986#section-4.3
*
* @param URI $uri New request URI to use.
* @param bool $preserveHost Preserve the original state of the Host header.
*
* @return static
*/
public function withUri(URI $uri, $preserveHost = false);
}
21 changes: 4 additions & 17 deletions system/HTTP/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
namespace CodeIgniter\HTTP;

use CodeIgniter\Validation\FormatRules;
use Config\App;

/**
* Representation of an HTTP request.
* Representation of an incoming, server-side HTTP request.
*/
class Request extends Message implements RequestInterface
class Request extends OutgoingRequest implements RequestInterface
{
use RequestTrait;

Expand All @@ -29,24 +30,10 @@ class Request extends Message implements RequestInterface
*/
protected $proxyIPs;

/**
* Request method.
*
* @var string
*/
protected $method;

/**
* A URI instance.
*
* @var URI
*/
protected $uri;

/**
* Constructor.
*
* @param object $config
* @param App $config
*
* @deprecated The $config is no longer needed and will be removed in a future version
*/
Expand Down
Loading

0 comments on commit 949b622

Please sign in to comment.