Guzzle Request query params - php

I have a method using gullzehttp and would like to change it to the pool plus the pool implements the Request method
<?php
use GuzzleHttp\Client;
$params = ['password' => '123456'];
$header = ['Accept' => 'application/xml'];
$options = ['query' => $params, 'headers' => $header];
$response = $client->request('GET', 'http://httpbin.org/get', $options);
I need to change to the Request method, but I could not find in the documentation how to send querystring variables in the Request
<?php
use GuzzleHttp\Psr7\Request;
$request = new Request('GET', 'http://httpbin.org/get', $options);

You need to add the query as a string to the URI.
For that you can use http_build_query or a guzzle helper function to convert a parameter array to an encoded query string:
$uri = new Uri('http://httpbin.org/get');
$request = new Request('GET', $uri->withQuery(GuzzleHttp\Psr7\build_query($params)));
// OR
$request = new Request('GET', $uri->withQuery(http_build_query($params)));

I also had trouble figuring out how to properly place the new Request() parameters. but structuring it the way i did below using php http_build_query to convert my arrays to query params and then appended it to the url before sending fixed it.
try {
// Build a client
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'https://pro-api.coinmarketcap.com',
// You can set any number of default request options.
// 'timeout' => 2.0,
]);
// Prepare a request
$url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest';
$headers = [
'Accepts' => 'application/json',
'X-CMC_PRO_API_KEY' => '05-88df-6f98ba'
];
$params = [
'id' => '1'
];
$request = new Request('GET', $url.'?'.http_build_query($params), $headers);
// Send a request
$response = $client->send($request);
// Receive a response
dd($response->getBody()->getContents());
return $response->getBody()->getContents();
} catch (\Throwable $th) {
dd('did not work', $th);
return false;
}

Related

How to pass arguments to the PUT request in codeigniter?

I am using codeigniter-3, i have to update the data but the API is extrenal API .i am using Guzzle class to contact with that api it's working fine but it's not updating the data because it's not taking the data ,can you tell me how to pass the arguments or body to the curl request..?
library
public function putcurl($url,$headers,$args){
$client = new GuzzleHttp\Client();
$response = $client->request('PUT',$url,['headers' => $headers],['body'=>$args]);
$body = $response->getBody();
$arr_body = json_decode($body);
return ($arr_body);
}
controller.php
$url = $this->config->item('url')['editstation'].$id;
$headers=[
'Authorization' => 'Basic xxxxxxxxxxxxxx',
'Content-Type' => ' application/json',
'Cookie' =>'ci_session=3e7c29f86fd6b8e738d8caefc37fa5b61e3b9ed0',
'x-api-key' => 'test#123',
];
$res = $this->customcurls->putcurl($url,$headers,$args);

Authorization with token in guzzlehttp Laravel php

I'm trying to make a request with my other endpoint, using GuzzleHttp in laravel, but the token isn't authorizing it. I believe it's in the way I'm going. Anyone know how to fix this? This is my code.
public function productRecommendation($rowPerPage,$keywords, $page){
try{
$request = request();
$token = $request->bearerToken();
$client = new \GuzzleHttp\Client();
$promise = $client->request('GET', $this->sellerUrl.'recommended', [
'headers' => ['Authorization' => "Bearer {$token}"],
'query' =>
[
'rowPerPage' => $rowPerPage,
'page' => $page,
'keywords' => $keywords,
],
]);
$response = (string) $promise->getBody();
return json_decode($response, true);
}
catch (Exception $e){
return $e;
}
}
You are getting the bearer token of your first application using $request->bearerToken() and send it to your second application for authorization which must not work;
You need to get a working token from your second application. You can either generate a token in your second application and copy it inside your current $token variable, or first call the login endpoint of second application with your credentials and use that token.
By the way, Laravel now supports a guzzle wrapper called Illuminate\Support\Facades\Http which makes things lot easier, you can rewrite your code like this:
public function productRecommendation($rowPerPage, $keywords, $page)
{
try{
$token = "some valid token from second endpoint";
$response = Http::withToken(
$token
)->get(
$this->sellerUrl . 'recommended',
[
'rowPerPage' => $rowPerPage,
'page' => $page,
'keywords' => $keywords,
]
);
return response()->json(
json_decode($response->body(), true)
);
}
catch (Exception $e){
return $e;
}
}

PHPUnit and mock request from Guzzle

I have a class with the following function :
public function get(string $uri) : stdClass
{
$this->client = new Client;
$response = $this->client->request(
'GET',
$uri,
$this->headers
);
return json_decode($response->getBody());
}
How can I mock the request method from PHPUnit? I tried different ways but it always tries to connect to the uri specified.
I tried with :
$clientMock = $this->getMockBuilder('GuzzleHttp\Client')
->setMethods('request')
->getMock();
$clientMock->expects($this->once())
->method('request')
->willReturn('{}');
But this didn't work. What can I do? I just need to mock the response to be empty.
Thanks
PD : Client comes from (use GuzzleHttp\Client)
I think as suggested is better to use http://docs.guzzlephp.org/en/stable/testing.html#mock-handler
as it looks like the most elegant way to do it properly.
Thank you all
The mocked Response doesn't need to be anything in particular, your code just expects it to be an object with a getBody method. So you can just use a stdClass, with a getBody method which returns some json_encoded object. Something like:
$jsonObject = json_encode(['foo']);
$uri = 'path/to/foo/bar/';
$mockResponse = $this->getMockBuilder(\stdClass::class)->getMock();
$mockResponse->method('getBody')->willReturn($jsonObject);
$clientMock = $this->getMockBuilder('GuzzleHttp\Client')->getMock();
$clientMock->expects($this->once())
->method('request')
->with(
'GET',
$uri,
$this->anything()
)
->willReturn($mockResponse);
$result = $yourClass->get($uri);
$expected = json_decode($jsonObject);
$this->assertSame($expected, $result);
I prefer this way to mock a Client in PHP. In this example I am using Guzzle Client.
Clone the code or install it via composer
$ composer require doppiogancio/mocked-client
And then...
$builder = new HandlerStackBuilder();
// Add a route with a response via callback
$builder->addRoute(
'GET', '/country/IT', static function (ServerRequestInterface $request): Response {
return new Response(200, [], '{"id":"+39","code":"IT","name":"Italy"}');
}
);
// Add a route with a response in a text file
$builder->addRouteWithFile('GET', '/country/IT/json', __DIR__ . '/fixtures/country.json');
// Add a route with a response in a string
$builder->addRouteWithFile('GET', '{"id":"+39","code":"IT","name":"Italy"}');
// Add a route mocking directly the response
$builder->addRouteWithResponse('GET', '/admin/dashboard', new Response(401));
$client = new Client(['handler' => $builder->build()]);
Once you have mocked the client you can use it like this:
$response = $client->request('GET', '/country/DE/json');
$body = (string) $response->getBody();
$country = json_decode($body, true);
print_r($country);
// will return
Array
(
[id] => +49
[code] => DE
[name] => Germany
)
In addition to the current answer about using MockHandler, it's possible to process the request so that you can validate the calls.
The following example passes a callable which just tests the request method and throws an exception if not POST, if that is OK it returns the response. The principle can be expanded to test other details about the request...
$mock = new MockHandler([
function ($request) {
$this->assertEquals('POST', $request->getMethod());
return new Response(
200,
[],
json_encode([ "access_token" => '1234e' ])
);
},
new Response(
200,
[],
json_encode([ "details" =>
[
[
"orderID" => 229783,
],
[
"orderID" => 416270,
],
],
])
),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
So the first call to the client has the test included, the second call just returns a response.
Just noticed that any time you use a callable to process the request, you MUST return a Response object if you expect the process to continue.

how to compress(gzip) body of a request in guzzle 6

need to send compressed (gzip) body to a server
e.g.
protected function postOrPutData($method, $data, $type, $uri = null, array $options = [])
{
$requestBody = $this->serializer->serialize($data, 'json');
$request = new Request($method, $uri, [], $requestBody);
$response = $this->httpClient->send($request, $options);
return $this->serializer->deserialize((string) $response->getBody(), $type, 'json');
}
I think you can get inspiration also from similar question about pure cURL.
Try to use this custom setting with Guzzle (I assume that you are using it with cURL handler):
$options['curl'] = [CURLOPT_ENCODING => 'gzip'];
$request = new Request($method, $uri, [], $requestBody);
$response = $this->httpClient->send($request, $options);

GuzzlePHP mock response content

I want to mock a response to the Guzzle request:
$response = new Response(200, ['X-Foo' => 'Bar']);
//how do I set content of $response to--> "some mocked content"
$client = Mockery::mock('GuzzleHttp\Client');
$client->shouldReceive('get')->once()->andReturn($response);
I noticed I need to add as third parameter the interface:
GuzzleHttp\Stream\StreamInterface
but there are so many implementations of it, and I want to return a simple string. Any ideas?
Edit: now I use this:
$response = new Response(200, [], GuzzleHttp\Stream\Stream::factory('bad xml here'));
but when I check this:
$response->getBody()->getContents()
I get an empty string. Why is this?
Edit 2: this happened to me only when I used xdebug, when it runs normally it works great!
We'll just keep doing this. The previous answer is for Guzzle 5, this is for Guzzle 6:
use GuzzleHttp\Psr7;
$stream = Psr7\stream_for('{"data" : "test"}');
$response = new Response(200, ['Content-Type' => 'application/json'], $stream);
The previous answer is for Guzzle 3. Guzzle 5 uses the following:
<?php
$body = GuzzleHttp\Stream\Stream::factory('some mocked content');
$response = new Response(200, ['X-Foo' => 'Bar'], $body);
Using #tomvo answer and the comment from #Tim - this is what I did for testing Guzzle 6 inside my Laravel app:
use GuzzleHttp\Psr7\Response;
$string = json_encode(['data' => 'test']);
$response = new Response(200, ['Content-Type' => 'application/json'], $string);
$guzzle = Mockery::mock(GuzzleHttp\Client::class);
$guzzle->shouldReceive('get')->once()->andReturn($response);
Guzzle\Http\Message\Response allows you to specify the third parameter as a string.
$body = '<html><body>Hello world!</body></html>';
$response = new Response(200, ['X-Foo' => 'Bar'], $body);
If you'd prefer a solution that implements Guzzle\Stream\StreamInterface, then I recommend using Guzzle\Http\EntityBody for the most straightforward implementation:
$body = Guzzle\Http\EntityBody::fromString('<html><body>Hello world!</body></html>');
$response = new Response(200, ['X-Foo' => 'Bar'], $body);
For Guzzle 7, you can use the GuzzleHttp\Psr7\Utils::streamFor() method as follows:
$data = json_encode(['X-Foo' => 'Bar']);
$stream = Utils::streamFor($data);
And then you can pass the $stream object to the andReturn method of the mocked client.

Categories