Skip to content

Commit 943ae36

Browse files
committed
Extend web.Request::dispatch() to accept query strings inside path
1 parent e89ab23 commit 943ae36

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

ChangeLog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ Web change log
33

44
## ?.?.? / ????-??-??
55

6+
## 4.3.0 / 2024-05-20
7+
8+
* Extended `web.Request::dispatch()` to accept query strings inside path
9+
(@thekid)
10+
611
## 4.2.0 / 2024-05-20
712

813
* Deprecated the `web.Dispatch` class. This class was never intended to

src/main/php/web/Request.class.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,17 @@ public function cookies() {
255255
* @return iterable
256256
*/
257257
public function dispatch($path, $params= []) {
258-
yield 'dispatch' => $this->uri()->using()->path($path)->params($params)->create();
258+
if (false === ($p= strpos($path, '?'))) {
259+
$uri= $this->uri()->using()->path($path)->params($params);
260+
} else {
261+
$uri= $this->uri()->using()->path(substr($path, 0, $p))->query(substr($path, $p + 1), false);
262+
263+
// Merge parameters instead of overwriting them all via `params()`
264+
foreach ($params as $name => $value) {
265+
$uri->param($name, $value);
266+
}
267+
}
268+
yield 'dispatch' => $uri->create();
259269
}
260270

261271
/**

src/test/php/web/unittest/ApplicationTest.class.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,22 @@ public function dispatch_request_without_query() {
162162

163163
#[Test]
164164
public function dispatch_request_with_query() {
165+
$passed= null;
166+
$this->handle(function() use(&$passed) {
167+
return [
168+
'/deref' => function($request, $response) use(&$passed) {
169+
$passed= $request->params();
170+
},
171+
'/' => function($request, $response) {
172+
return $request->dispatch('/deref?url=http://example.com/');
173+
},
174+
];
175+
});
176+
Assert::equals(['url' => 'http://example.com/'], $passed);
177+
}
178+
179+
#[Test]
180+
public function dispatch_request_with_params() {
165181
$passed= null;
166182
$this->handle(function() use(&$passed) {
167183
return [
@@ -176,6 +192,22 @@ public function dispatch_request_with_query() {
176192
Assert::equals(['url' => 'http://example.com/'], $passed);
177193
}
178194

195+
#[Test, Values([['/test?a=b&c=d', []], ['/test?a=b', ['c' => 'd']], ['/test', ['a' => 'b', 'c' => 'd']], ['/test?a=#', ['a' => 'b', 'c' => 'd']], ['/test', ['a' => 'b', 'c' => 'd']], ['/test?x=#', ['a' => 'b', 'c' => 'd', 'x' => null]]])]
196+
public function dispatch_request_with_query_and_params($path, $params) {
197+
$passed= null;
198+
$this->handle(function() use($path, $params, &$passed) {
199+
return [
200+
'/test' => function($request, $response) use(&$passed) {
201+
$passed= $request->params();
202+
},
203+
'/' => function($request, $response) use($path, $params) {
204+
return $request->dispatch($path, $params);
205+
},
206+
];
207+
});
208+
Assert::equals(['a' => 'b', 'c' => 'd'], $passed);
209+
}
210+
179211
#[Test, Expect(class: Error::class, message: '/Internal redirect loop/')]
180212
public function dispatch_request_to_self_causes_error() {
181213
$this->assertHandled($handled, function() use(&$handled) {

0 commit comments

Comments
 (0)