25

I'm using Guzzle in a set of PHPUnit-powered tests for a REST API.

I create my client as follows:

use GuzzleHttp\Client;

$client = new Client(['base_url' => ['http://api.localhost/api/{version}', ['version' => '1.0']]]);

This works fine, and I can make requests using the following code:

$request = $client->createRequest('GET', '/auth');
$request->setBody(Stream::factory(json_encode(['test'=>'data'])));
$response = $client->send($request);
$decodedResponse = $response->json();

However, Guzzle is ignoring the /api/{version} part of the base URL and makes the request to here:

http://api.localhost/auth

However, I would have expected it to make the request here:

http://api.localhost/api/1.0/auth

Have I mis-read the documentation and my expected behaviour is thus wrong, or is there some other option I need to enable to get it to append the /auth url to the /api/1.0 base path when making the request?

Benjamin Nolan
  • 1,170
  • 1
  • 10
  • 20

3 Answers3

24

You're using an absolute path in your requests, so it's overriding the path set in the base URL. Guzzle follows RFC 3986 when combining URLs: https://www.rfc-editor.org/rfc/rfc3986#section-5.2

Community
  • 1
  • 1
Michael Dowling
  • 5,098
  • 4
  • 32
  • 28
12

Here are examples for Guzzle 7 (7.4.1) of what Michael Dowling wrote

$client = new Client(['base_uri' => 'http://my-app.com/api/']);
$response = $client->get('facets'); // no leading slash - append to base
//    http://my-app.com/api/facets

$client = new Client(['base_uri' => 'http://my-app.com/api/']);
$response = $client->get('facets/'); // no leading slash - append to base // ending slash preserved
//    http://my-app.com/api/facets/

$client = new Client(['base_uri' => 'http://my-app.com/api/']);
$response = $client->get('/facets'); // leading slash - absolute path - base path is lost
//    http://my-app.com/facets

$client = new Client(['base_uri' => 'http://my-app.com/api']); // no ending slash in base path - ignored
$response = $client->get('facets');
//    http://my-app.com/facets

$client = new Client(['base_uri' => 'http://my-app.com/api']);
$response = $client->get('/facets'); // leading slash - absolute path - base path is lost
//    http://my-app.com/facets
hrvoj3e
  • 2,512
  • 1
  • 23
  • 22
6

I have a sort of oblique answer that might help someone who's predisposed to the same type of typos as I am.

It's base_uri, and that's "uri". Not base_url, as in "url".

The consequence of setting a base_url is similar to the problem described by OP - the request won't build on the configured base.

Cameron Hurd
  • 4,836
  • 1
  • 22
  • 31
  • 1
    As a side note, in 2014 when the issue occurred, it was `base_url` with an L. The current version uses `base_uri`. My issue was that I was starting the call itself with an initial slash, so instead of getting calls to http://api.localhost/api/{version}/auth as expected, I was getting calls to http://api.localhost/auth. – Benjamin Nolan Aug 23 '18 at 01:51