Reputation: 1298
I am making the following request using Zend\Http\Request and Zend\Http\Client
//Creating request and client objects
$request = new Request();
$client = new Client();
//Preparing Request Object
$request->setMethod('POST');
$request->setUri('https://my.api.address.com/apiendpointurl1234');
$request->getHeaders()->addHeaders(array(
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'client_secret' => 'asdfasdfasdfasdfasdf',
'client_id' => 'asdfasdfasdfasdfasdf',
'accept' => 'application/json',
'authorization' => 'Basic MTIzNDoxMjM0',
));
$request->getPost()->set(json_encode(array(
'student_id' => '123456',
'short_description' => 'this is short description',
'description' => 'this is detailed description of the question',
)));
//Sending Request
$response = $client->send($request);
var_dump( $response->getBody() );
However the response comes with this error:
"error": "headers: client_id required"
When I poke the API via Postman, it works fine. But when I call it from the PHP application, it turns out that the headers are not being sent correctly, which is giving the above error. Anyone would know why the headers aren't being sent?
Upvotes: 4
Views: 3199
Reputation: 11242
Here is what worked for me:
//Creating request and client objects
$request = new Request();
$client = new Client();
//Preparing Request Object
$request->setMethod('POST');
$request->setUri('https://my.api.address.com/apiendpointurl1234');
$request->getHeaders()->addHeaders(array(
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'client_secret' => 'asdfasdfasdfasdfasdf',
'client_id' => 'asdfasdfasdfasdfasdf',
'accept' => 'application/json',
'authorization' => 'Basic MTIzNDoxMjM0'
));
$client->setOptions(['strictredirects' => true]);
$request->setContent(json_encode(array(
'student_id' => '123456',
'short_description' => 'this is short description',
'description' => 'this is detailed description of the question',
)));
//Sending Request
$response = $client->send($request);
echo ($response->getBody());
My assumption is that there is a redirect from your api to another url and the headers get reset. You can see that at line 943 of Client.php where
$this->resetParameters(false, false);
is called. This does not happen in Postman since Postman reuses the same headers for the redirect.
Actually, you can test this by adding just adding
$client->setOptions(['strictredirects' => true]);
which should allow headers to be kept between redirects.
PS: I tried the code above with the latest stable version of zend http and it throw me some errors at the "$request->getPost()->set" line. Anyway, this is not the source of the issue.
EDIT: My 2nd assumption is that "client_id" header name is queried case-sensitive by the api, which causes the error, because the request is sent by Zend\Http\Client, it uses "Zend\Http\Client\Adapter\Socket" which makes the first character of each header uppercase(line 361). So "Client_id" is actual sent. Edit line 361 of Zend\Http\Client\Adapter\Socket":
$v = ucfirst($k) . ": $v";
to
$v = $k . ": $v";
and test if the header is received.
Upvotes: 1
Reputation: 1298
Turns out that Zend\Http\Request
and Zend\Http\Client
libraries converts underscores to hyphen (-) at the time of making the call. However, cURL behaves a bit differently. Still if you supply headers array in key value format, you won't be able to make the call as cURL will convert client-id
to client-id
. However, if you supply an standard array of values only by concatenating the headers, the call is successful. So here is my replacement code that worked:
// Get cURL resource
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://my.api.address.com/apiendpointurl1234',
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => [
'client_id: ' . 'asdfasdfasdfasdf',
'client_secret: ' . 'asdfasdfasdfasdfasdf',
'Authorization: ' . 'Basic MTIzNDoxMjM0',
'Content-Type: ' . 'application/json',
],
CURLOPT_POSTFIELDS => [
'student_id' => '111',
'short_description' => 'this is the short description',
'description' => 'this is the long description this is the long description this is the long description'
],
]);
// Send the request & save response to $resp
$response = curl_exec($curl);
var_dump("Service call id is: " . $response);
// Close request to clear up some resources
curl_close($curl);
Hope that helps.
Upvotes: 0
Reputation: 6842
If i remember correctly it's been a while since i used Zend Framework for Requests but the getHeaders
method returns the Headers object so you need to use and set.
So your code
$request->getHeaders()->addHeaders(array(
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'client_secret' => 'asdfasdfasdfasdfasdf',
'client_id' => 'asdfasdfasdfasdfasdf',
'accept' => 'application/json',
'authorization' => 'Basic MTIzNDoxMjM0',
));
Will need to become
$headers = $request->getHeaders();
$headers->addHeaders(array(
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'client_secret' => 'asdfasdfasdfasdfasdf',
'client_id' => 'asdfasdfasdfasdfasdf',
'accept' => 'application/json',
'authorization' => 'Basic MTIzNDoxMjM0',
));
$request->setHeaders($headers);
As said in one of the others Answers:
you will need to set the URI and method as Post before you do this as you will need the other headers
$request->setUri('https://my.api.address.com/apiendpointurl1234');
// Performing a POST request
$request->setMethod(Request::METHOD_POST);
And Lastly you will need to set your post data before you do this as it will affect your headers as Content-Length header needs to be set before you start messing with them
$request->setContent(json_encode(array(
'student_id' => '123456',
'short_description' => 'this is short description',
'description' => 'this is detailed description of the question',
)));
So all together you script should be
//Creating request and client objects
$request = new Request();
$client = new Client();
$request->setUri('https://my.api.address.com/apiendpointurl1234');
// Performing a POST request
$request->setMethod(Request::METHOD_POST);
$client->setOptions(['strictredirects' => true]);
$request->setContent(json_encode(array(
'student_id' => '123456',
'short_description' => 'this is short description',
'description' => 'this is detailed description of the question',
)));
$headers = $request->getHeaders();
$headers->addHeaders(array(
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'client_secret' => 'asdfasdfasdfasdfasdf',
'client_id' => 'asdfasdfasdfasdfasdf',
'accept' => 'application/json',
'authorization' => 'Basic MTIzNDoxMjM0',
));
$request->setHeaders($headers);
Upvotes: 1
Reputation: 231
I bet you'd need to store the reference to Headers object in a variable right after you getHeaders
, manipulate that object, and then use setHeaders
to update headers on a Request object.
$headers = $request->getHeaders();
$headers->addHeaders([ ... ... ]);
$request->setHeaders($headers);
Upvotes: 1
Reputation: 1597
If you want to use Request
object, you have use setRequest
and dispatch
methods:
use Zend\Http\Client;
use Zend\Http\Request;
$request = new Request();
$request->setUri('https://my.api.address.com/apiendpointurl1234');
// Performing a POST request
$request->setMethod(Request::METHOD_POST);
$request->getHeaders()->addHeaders(array(
'cache-control' => 'no-cache',
'content-type' => 'application/json',
'client_secret' => 'asdfasdfasdfasdfasdf',
'client_id' => 'asdfasdfasdfasdfasdf',
'accept' => 'application/json',
'authorization' => 'Basic MTIzNDoxMjM0',
));
$client = new Client();
$client->setRequest($request);
$response = $client->dispatch();
Upvotes: 1
Reputation: 1430
try without addHeaders method
// Setting multiple headers, overwriting any previous value
$client->setHeaders(array(
'Host' => 'www.example.com',
'Accept-encoding' => 'gzip,deflate',
'X-Powered-By' => 'Zend Framework'));
and maybe you have some confuse with client and request objects.
$client = new Zend_Http_Client('http://example.org');
$client->setHeaders(array(
'Host' => 'www.example.com',
'Accept-encoding' => 'gzip,deflate',
'X-Powered-By' => 'Zend Framework'));
$response = $client->request();
and you can inspect your query in firebug for example and check what headers are sent in server
Upvotes: 2