Skip to content

Commit d7dc8d2

Browse files
committed
refactor(http): clarify typed request input sources
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
1 parent b712df7 commit d7dc8d2

5 files changed

Lines changed: 35 additions & 106 deletions

File tree

system/HTTP/IncomingRequest.php

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -557,9 +557,9 @@ public function getRawInputVar($index = null, ?int $filter = null, $flags = null
557557
}
558558

559559
/**
560-
* Returns query-string parameters as a typed input object.
560+
* Returns GET parameters as a typed input object.
561561
*/
562-
public function getQueryInput(): InputData
562+
public function getGetInput(): InputData
563563
{
564564
$data = $this->getGet();
565565

@@ -577,36 +577,17 @@ public function getPostInput(): InputData
577577
}
578578

579579
/**
580-
* Returns request body payload parameters as a typed input object.
580+
* Returns JSON body parameters as a typed input object.
581581
*/
582-
public function getPayloadInput(): InputData
582+
public function getJSONInput(): InputData
583583
{
584-
$contentType = $this->getHeaderLine('Content-Type');
584+
$data = $this->getJSON(true) ?? [];
585585

586-
if (str_contains($contentType, 'application/json')) {
587-
$data = $this->getJSON(true) ?? [];
588-
589-
if (! is_array($data)) {
590-
throw HTTPException::forUnsupportedJSONFormat();
591-
}
592-
593-
return service('inputdatafactory')->create($data);
594-
}
595-
596-
if (
597-
in_array($this->getMethod(), [Method::PUT, Method::PATCH, Method::DELETE], true)
598-
&& ! str_contains($contentType, 'multipart/form-data')
599-
) {
600-
return service('inputdatafactory')->create($this->getRawInput());
601-
}
602-
603-
if (in_array($this->getMethod(), [Method::GET, Method::HEAD], true)) {
604-
return service('inputdatafactory')->create([]);
586+
if (! is_array($data)) {
587+
throw HTTPException::forUnsupportedJSONFormat();
605588
}
606589

607-
$data = $this->getPost();
608-
609-
return service('inputdatafactory')->create(is_array($data) ? $data : []);
590+
return service('inputdatafactory')->create($data);
610591
}
611592

612593
/**

tests/system/HTTP/IncomingRequestTest.php

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,14 @@ public function testCanGrabPostVars(): void
8787
$this->assertNull($this->request->getPost('TESTY'));
8888
}
8989

90-
public function testGetQueryInputReadsQueryData(): void
90+
public function testGetGetInputReadsGetData(): void
9191
{
9292
service('superglobals')->setGet('page', '3');
9393
service('superglobals')->setGet('filters', ['active' => 'true']);
9494
service('superglobals')->setPost('page', '10');
9595

9696
$request = $this->createRequest();
97-
$input = $request->getQueryInput();
97+
$input = $request->getGetInput();
9898

9999
$this->assertInstanceOf(InputData::class, $input);
100100
$this->assertSame(3, $input->integer('page'));
@@ -602,7 +602,7 @@ public function testCanGrabGetRawInput(): void
602602
$this->assertSame($expected, $request->getRawInput());
603603
}
604604

605-
public function testGetPayloadInputReadsJsonBody(): void
605+
public function testGetJSONInputReadsJsonBody(): void
606606
{
607607
$json = json_encode([
608608
'page' => '4',
@@ -611,93 +611,43 @@ public function testGetPayloadInputReadsJsonBody(): void
611611
]);
612612

613613
$request = $this->createRequest(new App(), $json);
614-
$request->setHeader('Content-Type', 'application/json');
615614

616-
$input = $request->getPayloadInput();
615+
$input = $request->getJSONInput();
617616

618617
$this->assertInstanceOf(InputData::class, $input);
619618
$this->assertSame(4, $input->integer('page'));
620619
$this->assertTrue($input->boolean('filters.active'));
621620
$this->assertTrue($input->has('nullable'));
622621
}
623622

624-
#[DataProvider('provideGetPayloadInputReadsRawBodyForWriteRequests')]
625-
public function testGetPayloadInputReadsRawBodyForWriteRequests(string $method): void
626-
{
627-
$request = $this->createRequest(new App(), 'title=Hello&published=1')
628-
->withMethod($method);
629-
630-
$input = $request->getPayloadInput();
631-
632-
$this->assertSame('Hello', $input->string('title'));
633-
$this->assertTrue($input->boolean('published'));
634-
}
635-
636-
/**
637-
* @return iterable<string, array{string}>
638-
*/
639-
public static function provideGetPayloadInputReadsRawBodyForWriteRequests(): iterable
640-
{
641-
yield 'PUT' => ['PUT'];
642-
643-
yield 'PATCH' => ['PATCH'];
644-
645-
yield 'DELETE' => ['DELETE'];
646-
}
647-
648-
public function testGetPayloadInputReadsPostBodyForPostRequests(): void
649-
{
650-
service('superglobals')->setGet('title', 'Query title');
651-
service('superglobals')->setPost('title', 'Post title');
652-
653-
$request = $this->createRequest()->withMethod('POST');
654-
$input = $request->getPayloadInput();
655-
656-
$this->assertSame('Post title', $input->string('title'));
657-
}
658-
659-
public function testGetPayloadInputDoesNotReadQueryDataForGetRequests(): void
660-
{
661-
service('superglobals')->setGet('page', '2');
662-
663-
$request = $this->createRequest()->withMethod('GET');
664-
$input = $request->getPayloadInput();
665-
666-
$this->assertFalse($input->has('page'));
667-
$this->assertSame(1, $input->integer('page', 1));
668-
}
669-
670-
public function testGetPayloadInputReturnsEmptyInputForEmptyJsonBody(): void
623+
public function testGetJSONInputReturnsEmptyInputForEmptyJsonBody(): void
671624
{
672625
$request = $this->createRequest(new App());
673-
$request->setHeader('Content-Type', 'application/json');
674626

675-
$input = $request->getPayloadInput();
627+
$input = $request->getJSONInput();
676628

677629
$this->assertInstanceOf(InputData::class, $input);
678630
$this->assertFalse($input->has('name'));
679631
}
680632

681-
public function testGetPayloadInputRejectsScalarJsonBody(): void
633+
public function testGetJSONInputRejectsScalarJsonBody(): void
682634
{
683635
$this->expectException(HTTPException::class);
684636
$this->expectExceptionMessage('The provided JSON format is not supported.');
685637

686638
$request = $this->createRequest(new App(), '"hello"');
687-
$request->setHeader('Content-Type', 'application/json');
688639

689-
$request->getPayloadInput();
640+
$request->getJSONInput();
690641
}
691642

692-
public function testGetPayloadInputKeepsInvalidJsonError(): void
643+
public function testGetJSONInputKeepsInvalidJsonError(): void
693644
{
694645
$this->expectException(HTTPException::class);
695646
$this->expectExceptionMessage('Failed to parse JSON string. Error: Syntax error');
696647

697648
$request = $this->createRequest(new App(), 'Invalid JSON string');
698-
$request->setHeader('Content-Type', 'application/json');
699649

700-
$request->getPayloadInput();
650+
$request->getJSONInput();
701651
}
702652

703653
/**

user_guide_src/source/changelogs/v4.8.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ HTTP
261261

262262
- Added the ``retry`` option to ``CURLRequest`` for retrying failed responses with configurable delays, retryable status codes, optional transient cURL error retries, and ``Retry-After`` support. See :ref:`curlrequest-request-options-retry`.
263263
- Added :ref:`Form Requests <form-requests>` - a new ``FormRequest`` base class that encapsulates validation rules, custom error messages, and authorization logic for a single HTTP request.
264-
- Added ``IncomingRequest::getQueryInput()``, ``getPostInput()``, and ``getPayloadInput()`` to read source-specific request data through ``InputData``.
264+
- Added ``IncomingRequest::getGetInput()``, ``getPostInput()``, and ``getJSONInput()`` to read GET, POST, and JSON request data through ``InputData``.
265265
- Added ``SSEResponse`` class for streaming Server-Sent Events (SSE) over HTTP. See :ref:`server-sent-events`.
266266
- ``Response`` and its child classes no longer require ``Config\App`` passed to their constructors.
267267
Consequently, ``CURLRequest``'s ``$config`` parameter is unused and will be removed in a future release.

user_guide_src/source/incoming/incomingrequest.rst

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,27 +161,25 @@ The ``getVar()`` method will pull from ``$_REQUEST``, so will return any data fr
161161
.. note:: If the incoming request has a ``Content-Type`` header set to ``application/json``,
162162
the ``getVar()`` method returns the JSON data instead of ``$_REQUEST`` data.
163163

164-
.. _incomingrequest-typed-source-input:
164+
.. _incomingrequest-typed-request-input:
165165

166-
Typed Source Input
167-
==================
166+
Typed Request Input
167+
===================
168168

169169
.. versionadded:: 4.8.0
170170

171-
``getQueryInput()``, ``getPostInput()``, and ``getPayloadInput()`` return
172-
request data as a ``CodeIgniter\Input\InputData`` object. Use these methods
173-
when you want source-explicit access with typed fallback helpers:
171+
``getGetInput()``, ``getPostInput()``, and ``getJSONInput()`` return
172+
request data as a ``CodeIgniter\Input\InputData`` object. Use these methods to
173+
read values from a specific part of the request with typed fallback helpers:
174174

175175
.. literalinclude:: incomingrequest/046.php
176176
:lines: 2-
177177

178-
``getQueryInput()`` reads query-string parameters. ``getPostInput()`` reads
179-
POST body parameters. ``getPayloadInput()`` reads the request body payload:
180-
JSON requests use the decoded JSON body, ``PUT``, ``PATCH``, and ``DELETE``
181-
requests use ``getRawInput()`` when they are not multipart requests, and
182-
ordinary form requests use POST body parameters.
183-
For non-JSON ``GET`` and ``HEAD`` requests, use ``getQueryInput()``;
184-
``getPayloadInput()`` returns an empty input object.
178+
``getGetInput()`` reads query-string parameters. ``getPostInput()`` reads
179+
POST body parameters. ``getJSONInput()`` reads JSON request body parameters.
180+
These methods keep GET, POST, and JSON data separate. They do not combine
181+
multiple request sources for you. For raw ``PUT``, ``PATCH``, or ``DELETE``
182+
data, continue using ``getRawInput()`` or ``getRawInputVar()``.
185183

186184
These methods do not validate input. They are fallback-friendly helpers for
187185
reading raw request data. Use Validation or :ref:`form-requests` when input
@@ -432,7 +430,7 @@ The methods provided by the parent classes that are available are:
432430

433431
.. literalinclude:: incomingrequest/045.php
434432

435-
.. php:method:: getQueryInput()
433+
.. php:method:: getGetInput()
436434
437435
:returns: Query-string parameters as a typed input object.
438436
:rtype: CodeIgniter\\Input\\InputData
@@ -454,9 +452,9 @@ The methods provided by the parent classes that are available are:
454452
:returns: POST body parameters as a typed input object.
455453
:rtype: CodeIgniter\\Input\\InputData
456454

457-
.. php:method:: getPayloadInput()
455+
.. php:method:: getJSONInput()
458456
459-
:returns: Request body payload parameters as a typed input object.
457+
:returns: JSON body parameters as a typed input object.
460458
:rtype: CodeIgniter\\Input\\InputData
461459

462460
.. php:method:: getPostGet([$index = null[, $filter = null[, $flags = null]]])
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?php
22

3-
$page = $request->getQueryInput()->integer('page', 1);
3+
$page = $request->getGetInput()->integer('page', 1);
44
$remember = $request->getPostInput()->boolean('remember', false);
5-
$name = $request->getPayloadInput()->string('name');
5+
$name = $request->getJSONInput()->string('name');

0 commit comments

Comments
 (0)