Skip to content

Commit 0daf98f

Browse files
committed
Consistently resolve base URL according to HTTP specs
1 parent 8656944 commit 0daf98f

4 files changed

Lines changed: 31 additions & 71 deletions

File tree

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,16 +2282,16 @@ The `withBase(string|null $baseUrl): Browser` method can be used to
22822282
change the base URL used to resolve relative URLs to.
22832283

22842284
If you configure a base URL, any requests to relative URLs will be
2285-
processed by first prepending this absolute base URL. Note that this
2286-
merely prepends the base URL and does *not* resolve any relative path
2287-
references (like `../` etc.). This is mostly useful for (RESTful) API
2288-
calls where all endpoints (URLs) are located under a common base URL.
2285+
processed by first resolving this relative to the given absolute base
2286+
URL. This supports resolving relative path references (like `../` etc.).
2287+
This is particularly useful for (RESTful) API calls where all endpoints
2288+
(URLs) are located under a common base URL.
22892289

22902290
```php
2291-
$browser = $browser->withBase('http://api.example.com/v3');
2291+
$browser = $browser->withBase('http://api.example.com/v3/');
22922292

2293-
// will request http://api.example.com/v3/example
2294-
$browser->get('/example')->then(…);
2293+
// will request http://api.example.com/v3/users
2294+
$browser->get('users')->then(…);
22952295
```
22962296

22972297
You can pass in a `null` base URL to return a new instance that does not

src/Browser.php

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace React\Http;
44

55
use Psr\Http\Message\ResponseInterface;
6+
use RingCentral\Psr7\Uri;
67
use React\EventLoop\LoopInterface;
78
use React\Http\Io\MessageFactory;
89
use React\Http\Io\Sender;
@@ -542,16 +543,16 @@ public function withRejectErrorResponse($obeySuccessCode)
542543
* Changes the base URL used to resolve relative URLs to.
543544
*
544545
* If you configure a base URL, any requests to relative URLs will be
545-
* processed by first prepending this absolute base URL. Note that this
546-
* merely prepends the base URL and does *not* resolve any relative path
547-
* references (like `../` etc.). This is mostly useful for (RESTful) API
548-
* calls where all endpoints (URLs) are located under a common base URL.
546+
* processed by first resolving this relative to the given absolute base
547+
* URL. This supports resolving relative path references (like `../` etc.).
548+
* This is particularly useful for (RESTful) API calls where all endpoints
549+
* (URLs) are located under a common base URL.
549550
*
550551
* ```php
551-
* $browser = $browser->withBase('http://api.example.com/v3');
552+
* $browser = $browser->withBase('http://api.example.com/v3/');
552553
*
553-
* // will request http://api.example.com/v3/example
554-
* $browser->get('/example')->then(…);
554+
* // will request http://api.example.com/v3/users
555+
* $browser->get('users')->then(…);
555556
* ```
556557
*
557558
* You can pass in a `null` base URL to return a new instance that does not
@@ -725,12 +726,13 @@ private function withOptions(array $options)
725726
*/
726727
private function requestMayBeStreaming($method, $url, array $headers = array(), $contents = '')
727728
{
728-
$request = $this->messageFactory->request($method, $url, $headers, $contents, $this->protocolVersion);
729729
if ($this->baseUrl !== null) {
730730
// ensure we're actually below the base URL
731-
$request = $request->withUri($this->messageFactory->expandBase($request->getUri(), $this->baseUrl));
731+
$url = Uri::resolve($this->baseUrl, $url);
732732
}
733733

734+
$request = $this->messageFactory->request($method, $url, $headers, $contents, $this->protocolVersion);
735+
734736
return $this->transaction->send($request);
735737
}
736738
}

src/Io/MessageFactory.php

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -99,41 +99,4 @@ public function uriRelative(UriInterface $base, $uri)
9999
{
100100
return Uri::resolve($base, $uri);
101101
}
102-
103-
/**
104-
* Resolves the given relative or absolute $uri by appending it behind $this base URI
105-
*
106-
* The given $uri parameter can be either a relative or absolute URI and
107-
* as such can not contain any URI template placeholders.
108-
*
109-
* As such, the outcome of this method represents a valid, absolute URI
110-
* which will be returned as an instance implementing `UriInterface`.
111-
*
112-
* If the given $uri is a relative URI, it will simply be appended behind $base URI.
113-
*
114-
* If the given $uri is an absolute URI, it will simply be returned as-is.
115-
*
116-
* @param UriInterface $uri
117-
* @param UriInterface $base
118-
* @return UriInterface
119-
*/
120-
public function expandBase(UriInterface $uri, UriInterface $base)
121-
{
122-
if ($uri->getScheme() !== '') {
123-
return $uri;
124-
}
125-
126-
$uri = (string)$uri;
127-
$base = (string)$base;
128-
129-
if ($uri !== '' && substr($base, -1) !== '/' && substr($uri, 0, 1) !== '?') {
130-
$base .= '/';
131-
}
132-
133-
if (isset($uri[0]) && $uri[0] === '/') {
134-
$uri = substr($uri, 1);
135-
}
136-
137-
return $this->uri($base . $uri);
138-
}
139102
}

tests/BrowserTest.php

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -223,35 +223,30 @@ public function provideOtherUris()
223223
'http://example.com/base/another',
224224
'http://example.com/base/another',
225225
),
226-
'slash returns added slash' => array(
226+
'slash returns base without path' => array(
227227
'http://example.com/base',
228228
'/',
229-
'http://example.com/base/',
230-
),
231-
'slash does not add duplicate slash if base already ends with slash' => array(
232-
'http://example.com/base/',
233-
'/',
234-
'http://example.com/base/',
229+
'http://example.com/',
235230
),
236231
'relative is added behind base' => array(
237232
'http://example.com/base/',
238233
'test',
239234
'http://example.com/base/test',
240235
),
241-
'relative with slash is added behind base without duplicate slashes' => array(
242-
'http://example.com/base/',
243-
'/test',
244-
'http://example.com/base/test',
245-
),
246-
'relative is added behind base with automatic slash inbetween' => array(
236+
'relative is added behind base without path' => array(
247237
'http://example.com/base',
248238
'test',
249-
'http://example.com/base/test',
239+
'http://example.com/test',
250240
),
251-
'relative with slash is added behind base' => array(
241+
'relative level up is added behind parent path' => array(
242+
'http://example.com/base/foo/',
243+
'../bar',
244+
'http://example.com/base/bar',
245+
),
246+
'absolute with slash is added behind base without path' => array(
252247
'http://example.com/base',
253248
'/test',
254-
'http://example.com/base/test',
249+
'http://example.com/test',
255250
),
256251
'query string is added behind base' => array(
257252
'http://example.com/base',
@@ -263,10 +258,10 @@ public function provideOtherUris()
263258
'?key=value',
264259
'http://example.com/base/?key=value',
265260
),
266-
'query string with slash is added behind base' => array(
261+
'query string with slash is added behind base without path' => array(
267262
'http://example.com/base',
268263
'/?key=value',
269-
'http://example.com/base/?key=value',
264+
'http://example.com/?key=value',
270265
),
271266
'absolute with query string below base is returned as-is' => array(
272267
'http://example.com/base',

0 commit comments

Comments
 (0)