Browse Source

Add requestTarget implementation.

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.
Mark Story 9 years ago
parent
commit
1b7bb0a370
2 changed files with 86 additions and 0 deletions
  1. 56 0
      src/Network/Request.php
  2. 30 0
      tests/TestCase/Network/RequestTest.php

+ 56 - 0
src/Network/Request.php

@@ -203,6 +203,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.
      *
      * Uses the $_GET, $_POST, $_FILES, $_COOKIE, $_SERVER, $_ENV and php://input data to construct
@@ -921,6 +928,7 @@ class Request implements ArrayAccess
      *
      * @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)
     {
@@ -1792,6 +1800,54 @@ class Request implements ArrayAccess
     }
 
     /**
+     * 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
      *
      * @param string $name Name of the key being accessed.

+ 30 - 0
tests/TestCase/Network/RequestTest.php

@@ -3184,6 +3184,36 @@ XML;
     }
 
     /**
+     * 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.
      *
      * @return array