Currently, we send in Guzzle v5 configuration parameter to the constructor of the GuzzleClient. As an example only, something like:
$this->client = new GuzzleClient(['verify' => false ]);
Is there a way to instantiate the Guzzle object without sending in the constructor parameter? And then later set the config, but before the actual call/action to .post or .get, etc.? Something like:
$this->client = new GuzzleClient();
$this->client->config = ['verify' => false ];
...
Thank you.
Related
I am using PHPUnit and Guzzle to make API unit test. The probleme I have is that I am not able or I can't really figure out how to persiste cookie between my test methods. Or maybe am doing it all wrong ^^
The first test testGetFirst gets the data and set a session cookie on server side. The response has a Set-Cookie header with the right cookie.
The seconde test testGetSecond should return a data set if the cookie exists. Unfortunatelly it seems that Guzzle::Client doesn't store/persiste the cookie between the methods.
use PHPUnit\Framework\TestCase;
use GuzzleHttp\Client;
class MyTest extends Testcase
{
public $guzzleClient;
/**
* #before
*/
function initVariables() {
$this->guzzleClient = new Client([
'base_uri' => 'http://apiuri.com',
'cookies' => true
]);
}
// This call get some data and set a cookie (session cookie) on server side
function testGetFirst() {
$params = [
'query' => [
'param1' => 'myparam'
]
];
$response = $this->guzzleClient->request('GET', '/', $params);
// if I print out the response headers I get my cookie in 'Set-Cookie' header
// I suppose the cookie has been set correctly
print_r($response->getHeaders());
// if I print out the client conf cookie, I get the cookie too
print_r($this->guzzleClient->getConfig('cookies')->toArray());
}
// This call get data to have access it need to use a cookie that has been set by testGetFirst
// But unfortunatelly the cookie is empty while making the request
/**
* #depends testGetFirst
*/
function testGetSecond() {
$params = [
'query' => [
'param1' => 'hello'
]
];
// if I print out the client conf cookie, cookies is empty
print_r($this->guzzleClient->getConfig('cookies')->toArray());
$response = $this->guzzleClient->request('GET', '/second', $params);
// as the request can't access to a cookie it sends an error response
}
}
I know there is CookieJar that I can use in each method and pass the Set-Cookie value in to Jar but I was hopping to avoid it.
Do you have any idea or suggestion ?
Very appreciate your help.
Due to the #before annotation for the initVariables method, this method is executed before each test. That method is creating a fresh client before each test.
To solve your particular situation, since you're using the #depends testGetFirst annotation, you could have the testGetFirst method return the client object. The testGetSecond method can then receive it as an argument. Check the Test Dependencies documentation for more info regarding passing arguments into dependent tests.
Is there a way using Guzzle in PHP that when I make a request to an API call that I can map my response to a Response object?
So instead of having to get the response data and then passing my array value as an argument, Guzzle can automatically resolve it to the required class?
In essence, this is what I am doing:
$client = new GuzzleHttp\Client();
$response = $client->request('myapi.users', 'GET');
$responseData = $response->getBody()->getContents();
$user = new User($responseData);
However I would like to try and avoid that boilerplate code by doing something like the following:
$client = new GuzzleHttp\Client();
$user = $client->request('myapi.users', 'GET');
Does Guzzle allow you to map response objects to Responses?
Thanks!
Nope, an HTTP Client (which Guzzle is) is not responsible for that. That's why there is not such a function there.
You can use Guzzle and your own object mapper, BTW, and create an SDK for the API you are using. Like the GitHub SDK, for example, that also uses Guzzle inside, but provides a specific interface for the domain.
I have tried to implement a Guzzle HandlerStack HttpClientAdapter for Swoole and use it via:
$handler = new \App\Swoole\HttpClientAdapter();
$client = new \GuzzleHttp\Client([
'handler' => \GuzzleHttp\HandlerStack::create($handler),
]);
$res = $client->request('POST', 'http://localhost/foo');
The handler class looks like this:
namespace App\Swoole;
class HttpClientAdapter
{
public function __invoke(RequestInterface $request, array $options)
{
// [..] init and request modification, path/port extraction removed
$cli = new \Swoole\Coroutine\Http\Client($ip, $port, $ssl);
$cli->execute($path);
$cli->close();
return new Promise\FulfilledPromise(
new Psr7\Response($cli->statusCode, $cli->headers, $cli->body)
);
}
}
This actually works - but only if i put in a MockServer Proxy in between.
Without, i just do not get any data back ... i have tried using different endpoints, but to no avail. Does anybody know how to tackle/debug the problem and/or is there a Swoole Guzzle Adapter out there in the wild?
Well, this work is awesome.
But I suggest another httpclient based on swoole coroutine:https://github.com/swlib/saber/blob/master/README-EN.md
It's developed by swoole core developer and you will find it quite look like Guzzle.
I am creating a client using GuzzleHttp 5.3. I want use the same Config object to configure the Guzzle Client. So, the creation of Guzzle Client depends of the object Config.
For example:
$config = new Config([
'user' => 'github',
'password' => '1234',
'base_url' => 'http://test_or_production_url.com'
]);
new GithubClient($config, new \GuzzleHttp\Client());
And the constructor:
public function __construct(Config $config)
{
$this->authData = [
'uname' => $config->getUser(),
'upassword' => $config->getPassword(),
];
$this->config = $config;
$this->httpClient = new \GuzzleHttp\Client(['base_url' => $config->getBaseUrl());
// I have to setup default headers, too.
}
But, I have to inject the Guzzle Client because I have to do unit tests.
One option is to inject a Guzzle Client configured as my client requires it. But the build process is a little cumbersome (set base_url, default header). The user must to know using Guzzle, I do not like this.
Other option is to create a new object (GithubClientFactory for example) to create my client.
$client = GithubClientFactory::make($config);
So, I hide the Guzzle dependency and the setup process. But the user always have to use the client factory.
Then, Is there a better (pattern) design to this problem?
Context: Laravel 5. Guzzle ~5.2. PHP 5.4. I'm building a class to interact with an external API. I'm providing this class with a Guzzle client using a Service Provider, to avoid instantiating the client within a method.
I want to cache the results. If the user is asking for something that is found in the cache, return it instead of performing a request to said API.
Problem: If I build up a Guzzle client and don't perform a request, the application crashes. Not even a stack trace from PHP. Actually, if I'm using Laravel's artisan serve, a Windows error message shows up saying, PHP CLI has stopped working.
For now, I'm passing the Guzzle client to the method on my class, every single time I call it.
Is there a way to just instantiate the Guzzle client without sending a request? What other route would you choose to achieve this? Is that intended behaviour?
tl;dr RTM
Longer version (from the docs):
Creating Requests
You can create a request without sending it. This is useful for building up requests over time or sending requests in concurrently.
$request = $client->createRequest('GET', 'http://httpbin.org', [
'headers' => ['X-Foo' => 'Bar']
]);
// Modify the request as needed
$request->setHeader('Baz', 'bar');
After creating a request, you can send it with the client’s send() method.
$response = $client->send($request);
from here:
http://docs.guzzlephp.org/en/stable/quickstart.html#making-a-request
use GuzzleHttp\Psr7\Request;
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'http://httpbin.org',
// You can set any number of default request options.
'timeout' => 2.0,
]);
$request = new Request('PUT', 'http://httpbin.org/put');
$response = $client->send($request, ['timeout' => 2]);