Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove deprecated upper functionality in Request::getMethod() #8186

Merged
merged 24 commits into from Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
88c89d0
refactor!: remove $upper functionality in Request::getMethod()
kenjis Nov 10, 2023
5bd6cbb
refactor: remove strtoupper()/strtolower() for $request->getMethod()
kenjis Nov 10, 2023
111d73b
chore: update phpstan-baseline.php
kenjis Nov 10, 2023
38e0f58
docs: add doc comment
kenjis Nov 10, 2023
7d866e2
docs: update existing docs
kenjis Nov 10, 2023
aca22d1
refactor: remove feature flag
kenjis Nov 10, 2023
0b6a273
docs: change Filters::$methods keys to uppercase
kenjis Nov 10, 2023
f54e420
test: change Filters::$methods keys to uppercase
kenjis Nov 10, 2023
d397154
docs: add changelog and upgrade
kenjis Nov 10, 2023
905c3d1
test: fix $routes->match() HTTP verbs
kenjis Nov 10, 2023
a09e750
test: fix $request->setMethod() HTTP verbs
kenjis Nov 10, 2023
b4a70bb
docs: fix $routes->match() HTTP verbs
kenjis Nov 10, 2023
1c50d82
docs: fix $client->request() HTTP verbs
kenjis Nov 10, 2023
303eaa1
docs: add about CURLRequest::request() HTTP verbs
kenjis Nov 10, 2023
6aff805
refactor: fix HTTP verbs for FeatureTestTrait::withRoutes()
kenjis Nov 10, 2023
399367e
docs: add deprecated features that accept lowercase HTTP methods
kenjis Nov 10, 2023
ad3bb95
docs: add section "Core Class Changes"
kenjis Nov 12, 2023
8680872
docs: add about lowercase HTTP method name
kenjis Nov 12, 2023
8d92882
feat: add HTTP\Method class
kenjis Nov 19, 2023
a394ac0
docs: add doc comment
kenjis Nov 19, 2023
7149fa5
refactor: use HTTP\Method constants
kenjis Nov 19, 2023
cb35ef7
test: use HTTP\Method constants
kenjis Nov 19, 2023
375c340
feat: add trigger_error E_USER_DEPRECATED
kenjis Nov 19, 2023
fe6babf
test: replace 'get' with 'GET'
kenjis Nov 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/Config/Filters.php
Expand Up @@ -50,7 +50,7 @@ class Filters extends BaseConfig
* particular HTTP method (GET, POST, etc.).
*
* Example:
* 'post' => ['foo', 'bar']
* 'POST' => ['foo', 'bar']
*
* If you use this, you should disable auto-routing because auto-routing
* permits any HTTP method to access a controller. Accessing the controller
Expand Down
2 changes: 1 addition & 1 deletion app/Views/errors/html/error_exception.php
Expand Up @@ -205,7 +205,7 @@
</tr>
<tr>
<td>HTTP Method</td>
<td><?= esc(strtoupper($request->getMethod())) ?></td>
<td><?= esc($request->getMethod()) ?></td>
</tr>
<tr>
<td>IP Address</td>
Expand Down
5 changes: 0 additions & 5 deletions phpstan-baseline.php
Expand Up @@ -1926,11 +1926,6 @@
'count' => 2,
'path' => __DIR__ . '/system/Filters/Filters.php',
];
$ignoreErrors[] = [
'message' => '#^Expression on left side of \\?\\? is not nullable\\.$#',
'count' => 1,
'path' => __DIR__ . '/system/Filters/Filters.php',
];
$ignoreErrors[] = [
'message' => '#^Only booleans are allowed in a negated boolean, array given\\.$#',
'count' => 1,
Expand Down
5 changes: 3 additions & 2 deletions system/CodeIgniter.php
Expand Up @@ -21,6 +21,7 @@
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\Exceptions\RedirectException;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\Method;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Request;
use CodeIgniter\HTTP\ResponsableInterface;
Expand Down Expand Up @@ -1027,7 +1028,7 @@ public function storePreviousURL($uri)
public function spoofRequestMethod()
{
// Only works with POSTED forms
if (strtolower($this->request->getMethod()) !== 'post') {
if ($this->request->getMethod() !== Method::POST) {
return;
}

Expand All @@ -1038,7 +1039,7 @@ public function spoofRequestMethod()
}

// Only allows PUT, PATCH, DELETE
if (in_array(strtoupper($method), ['PUT', 'PATCH', 'DELETE'], true)) {
if (in_array($method, [Method::PUT, Method::PATCH, Method::DELETE], true)) {
$this->request = $this->request->setMethod($method);
}
}
Expand Down
2 changes: 1 addition & 1 deletion system/Debug/Exceptions.php
Expand Up @@ -128,7 +128,7 @@ public function exceptionHandler(Throwable $exception)

if ($this->config->log === true && ! in_array($statusCode, $this->config->ignoreCodes, true)) {
$uri = $this->request->getPath() === '' ? '/' : $this->request->getPath();
$routeInfo = '[Method: ' . strtoupper($this->request->getMethod()) . ', Route: ' . $uri . ']';
$routeInfo = '[Method: ' . $this->request->getMethod() . ', Route: ' . $uri . ']';

log_message('critical', "{message}\n{routeInfo}\nin {exFile} on line {exLine}.\n{trace}", [
'message' => $exception->getMessage(),
Expand Down
2 changes: 1 addition & 1 deletion system/Debug/Toolbar.php
Expand Up @@ -79,7 +79,7 @@ public function run(float $startTime, float $totalTime, RequestInterface $reques
$data = [];
// Data items used within the view.
$data['url'] = current_url();
$data['method'] = strtoupper($request->getMethod());
$data['method'] = $request->getMethod();
$data['isAJAX'] = $request->isAJAX();
$data['startTime'] = $startTime;
$data['totalTime'] = $totalTime * 1000;
Expand Down
22 changes: 20 additions & 2 deletions system/Filters/Filters.php
Expand Up @@ -494,10 +494,28 @@ protected function processMethods()
return;
}

// Request method won't be set for CLI-based requests
$method = strtolower($this->request->getMethod()) ?? 'cli';
$method = $this->request->getMethod();

$found = false;

if (array_key_exists($method, $this->config->methods)) {
$found = true;
}
// Checks lowercase HTTP method for backward compatibility.
// @deprecated 4.5.0
// @TODO remove this in the future.
elseif (array_key_exists(strtolower($method), $this->config->methods)) {
@trigger_error(
'Setting lowercase HTTP method key "' . strtolower($method) . '" is deprecated.'
. ' Use uppercase HTTP method like "' . strtoupper($method) . '".',
E_USER_DEPRECATED
);

$found = true;
$method = strtolower($method);
}

if ($found) {
if (config(Feature::class)->oldFilterOrder) {
$this->filters['before'] = array_merge($this->filters['before'], $this->config->methods[$method]);
} else {
Expand Down
2 changes: 1 addition & 1 deletion system/HTTP/CLIRequest.php
Expand Up @@ -56,7 +56,7 @@ class CLIRequest extends Request
*
* @var string
*/
protected $method = 'cli';
protected $method = 'CLI';

/**
* Constructor
Expand Down
33 changes: 10 additions & 23 deletions system/HTTP/CURLRequest.php
Expand Up @@ -112,7 +112,7 @@ public function __construct(App $config, URI $uri, ?ResponseInterface $response
throw HTTPException::forMissingCurl(); // @codeCoverageIgnore
}

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

$this->responseOrig = $response ?? new Response(config(App::class));
$this->baseURI = $uri->useRawQueryString();
Expand All @@ -130,7 +130,7 @@ public function __construct(App $config, URI $uri, ?ResponseInterface $response
* Sends an HTTP request to the specified $url. If this is a relative
* URL, it will be merged with $this->baseURI to form a complete URL.
*
* @param string $method
* @param string $method HTTP method
*/
public function request($method, string $url, array $options = []): ResponseInterface
{
Expand Down Expand Up @@ -177,55 +177,55 @@ protected function resetOptions()
*/
public function get(string $url, array $options = []): ResponseInterface
{
return $this->request('get', $url, $options);
return $this->request(Method::GET, $url, $options);
}

/**
* Convenience method for sending a DELETE request.
*/
public function delete(string $url, array $options = []): ResponseInterface
{
return $this->request('delete', $url, $options);
return $this->request('DELETE', $url, $options);
}

/**
* Convenience method for sending a HEAD request.
*/
public function head(string $url, array $options = []): ResponseInterface
{
return $this->request('head', $url, $options);
return $this->request('HEAD', $url, $options);
}

/**
* Convenience method for sending an OPTIONS request.
*/
public function options(string $url, array $options = []): ResponseInterface
{
return $this->request('options', $url, $options);
return $this->request('OPTIONS', $url, $options);
}

/**
* Convenience method for sending a PATCH request.
*/
public function patch(string $url, array $options = []): ResponseInterface
{
return $this->request('patch', $url, $options);
return $this->request('PATCH', $url, $options);
}

/**
* Convenience method for sending a POST request.
*/
public function post(string $url, array $options = []): ResponseInterface
{
return $this->request('post', $url, $options);
return $this->request(Method::POST, $url, $options);
}

/**
* Convenience method for sending a PUT request.
*/
public function put(string $url, array $options = []): ResponseInterface
{
return $this->request('put', $url, $options);
return $this->request(Method::PUT, $url, $options);
}

/**
Expand Down Expand Up @@ -339,17 +339,6 @@ protected function prepareURL(string $url): string
);
}

/**
* Get the request method. Overrides the Request class' method
* since users expect a different answer here.
*
* @param bool|false $upper Whether to return in upper or lower case.
*/
public function getMethod(bool $upper = false): string
{
return ($upper) ? strtoupper($this->method) : strtolower($this->method);
}

/**
* Fires the actual cURL request.
*
Expand Down Expand Up @@ -446,8 +435,6 @@ protected function applyRequestHeaders(array $curlOptions = []): array
*/
protected function applyMethod(string $method, array $curlOptions): array
{
$method = strtoupper($method);

$this->method = $method;
$curlOptions[CURLOPT_CUSTOMREQUEST] = $method;

Expand All @@ -458,7 +445,7 @@ protected function applyMethod(string $method, array $curlOptions): array
return $this->applyBody($curlOptions);
}

if ($method === 'PUT' || $method === 'POST') {
if ($method === Method::PUT || $method === Method::POST) {
// See http://tools.ietf.org/html/rfc7230#section-3.3.2
if ($this->header('content-length') === null && ! isset($this->config['multipart'])) {
$this->setHeader('Content-Length', '0');
Expand Down
7 changes: 4 additions & 3 deletions system/HTTP/IncomingRequest.php
Expand Up @@ -396,17 +396,18 @@ public function negotiate(string $type, array $supported, bool $strictMatch = fa
/**
* Checks this request type.
*
* @param string $type HTTP verb or 'json' or 'ajax'
* @param string $type HTTP verb or 'json' or 'ajax'.
* HTTP verb should be case-sensitive, but this is case-insensitive.
* @phpstan-param string|'get'|'post'|'put'|'delete'|'head'|'patch'|'options'|'json'|'ajax' $type
*/
public function is(string $type): bool
{
$valueUpper = strtoupper($type);

$httpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'PATCH', 'OPTIONS'];
$httpMethods = Method::all();

if (in_array($valueUpper, $httpMethods, true)) {
return strtoupper($this->getMethod()) === $valueUpper;
return $this->getMethod() === $valueUpper;
}

if ($valueUpper === 'JSON') {
Expand Down
95 changes: 95 additions & 0 deletions system/HTTP/Method.php
@@ -0,0 +1,95 @@
<?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;

/**
* HTTP Method List
*/
class Method
{
/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT
*/
public const CONNECT = 'CONNECT';

/**
* Idempotent
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
*/
public const DELETE = 'DELETE';

/**
* Safe, Idempotent, Cacheable
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
*/
public const GET = 'GET';

/**
* Safe, Idempotent, Cacheable
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD
*/
public const HEAD = 'HEAD';

/**
* Safe, Idempotent
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
*/
public const OPTIONS = 'OPTIONS';

/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH
*/
public const PATCH = 'PATCH';

/**
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
*/
public const POST = 'POST';

/**
* Idempotent
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT
*/
public const PUT = 'PUT';

/**
* Safe, Idempotent
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE
*/
public const TRACE = 'TRACE';

/**
* Returns all HTTP methods.
*
* @return list<string>
*/
public static function all(): array
{
return [
self::CONNECT,
self::DELETE,
self::GET,
self::HEAD,
self::OPTIONS,
self::PATCH,
self::POST,
self::PUT,
self::TRACE,
];
}
}
10 changes: 4 additions & 6 deletions system/HTTP/OutgoingRequest.php
Expand Up @@ -66,15 +66,13 @@ private function getHostFromUri(URI $uri): string
}

/**
* Get the request method.
* Retrieves the HTTP method of the request.
*
* @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
* @return string Returns the request method (always uppercase)
*/
public function getMethod(bool $upper = false): string
public function getMethod(): string
{
return ($upper) ? strtoupper($this->method) : strtolower($this->method);
return $this->method;
michalsn marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
9 changes: 3 additions & 6 deletions system/HTTP/OutgoingRequestInterface.php
Expand Up @@ -21,14 +21,11 @@
interface OutgoingRequestInterface extends MessageInterface
{
/**
* Get the request method.
* An extension of PSR-7's getMethod to allow casing.
* Retrieves the HTTP method of the request.
*
* @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
* @return string Returns the request method.
*/
public function getMethod(bool $upper = false): string;
public function getMethod(): string;

/**
* Return an instance with the provided HTTP method.
Expand Down