Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/Controllers/BaseController.php
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 DownExpand 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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
<?php

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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
Comment thread
MGatner marked this conversation as resolved.
{
if (! $this->hasHeader('Host')) {
return true;
}

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

/**
* This file is part of CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* 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
Comment thread
MGatner marked this conversation as resolved.
{
/**
* 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 numberDiff line numberDiff 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
Comment thread
MGatner marked this conversation as resolved.
{
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