Skip to content

Commit

Permalink
Add requestTarget implementation.
Browse files Browse the repository at this point in the history
Add getRequestTarget() as a replacement for here(false). There is no
replacement for here(true). From looking at the core code, we generally
rely on here(false), and Router::url() to get the full path.

I'm deprecating here() as it has a high degree of overlap with the new
method and I think we can get away with one fewer method.
  • Loading branch information
markstory committed Sep 16, 2016
1 parent 255b082 commit 1b7bb0a
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/Network/Request.php
Expand Up @@ -202,6 +202,13 @@ class Request implements ArrayAccess
*/
protected $protocol;

/**
* The request target if overridden
*
* @var string|null
*/
protected $requestTarget;

/**
* Wrapper method to create a new request from PHP superglobals.
*
Expand Down Expand Up @@ -921,6 +928,7 @@ public function addPaths(array $paths)
*
* @param bool $base Include the base path, set to false to trim the base path off.
* @return string The current request URL including query string args.
* @deprecated 3.4.0 This method will be removed in 4.0.0. You should use getRequestTarget() instead.
*/
public function here($base = true)
{
Expand Down Expand Up @@ -1791,6 +1799,54 @@ public function withUri(UriInterface $uri)
return $new;
}

/**
* Create a new instance with a specific request-target.
*
* You can use this method to overwrite the request target that is
* inferred from the request's Uri. This also lets you change the request
* target's form to an absolute-form, authority-form or asterisk-form
*
* @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various
* request-target forms allowed in request messages)
* @param string $target The request target.
* @return static
*/
public function withRequestTarget($target)
{
$new = clone $this;
$new->requestTarget = $target;

return $new;
}

/**
* Retrieves the request's target.
*
* Retrieves the message's request-target either as it was requested,
* or as set with `withRequestTarget()`. By default this will return the
* application relative path without base directory, and the query string
* defined in the SERVER environment.
*
* @return string
*/
public function getRequestTarget()
{
if ($this->requestTarget !== null) {
return $this->requestTarget;
}

$target = $this->uri->getPath();
if ($this->uri->getQuery()) {
$target .= '?' . $this->uri->getQuery();
}

if (empty($target)) {
$target = '/';
}

return $target;
}

/**
* Array access read implementation
*
Expand Down
30 changes: 30 additions & 0 deletions tests/TestCase/Network/RequestTest.php
Expand Up @@ -3183,6 +3183,36 @@ public function testWithoutAttributesDenyEmulatedProperties($prop)
$request->withoutAttribute($prop);
}

/**
* Test the requestTarget methods.
*
* @return void
*/
public function testWithRequestTarget()
{
$request = new Request([
'environment' => [
'REQUEST_URI' => '/articles/view/1',
'QUERY_STRING' => 'comments=1&open=0'
],
'base' => '/basedir'
]);
$this->assertEquals(
'/articles/view/1?comments=1&open=0',
$request->getRequestTarget(),
'Should not include basedir.'
);

$new = $request->withRequestTarget('/articles/view/3');
$this->assertNotSame($new, $request);
$this->assertEquals(
'/articles/view/1?comments=1&open=0',
$request->getRequestTarget(),
'should be unchanged.'
);
$this->assertEquals('/articles/view/3', $new->getRequestTarget(), 'reflects method call');
}

/**
* Data provider for emulated property tests.
*
Expand Down

0 comments on commit 1b7bb0a

Please sign in to comment.