POST Request works with Postman, but not with Guzzle - php

In my Laravel application, I periodically need to POST data to an API using Guzzle.
The API users a bearer token to authenticate, and requests and accepts raw json. To test, I accessed the API using Postman, and everything worked wonderfully.
Postman Headers:
Accept:application/json
Authorization:Bearer [token]
Content-Type:application/json
And Postman Body:
{
"request1" : "123456789",
"request2" : "2468",
"request3" : "987654321",
"name" : "John Doe"
}
Postman returns a 200, and a JSON object as a response.
Now, when I try the same with Guzzle, I get a 200 status code, but no JSON object gets returned. Here's my Guzzle implementation:
public function getClient($token)
{
return new Client([
'base_uri' => env('API_HOST'),
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
]);
}
$post = $client->request('POST', '/path/to/api', [
'json' => [
'request1' => 123456789,
'request2' => 2468,
'request3' => 987654321,
'name' => 'John Doe',
]
]);
Is there some trick to POSTing JSON with Guzzle? If not, is there a way to debug what's going on under the hood?
I cannot, for the life of me, understand what the difference is between the Postman POST and the Guzzle POST.

You have to use headers config sections for headers, not the root level.
return new Client([
'base_uri' => env('API_HOST'),
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json',
],
]);

Related

param is missing or the value is empty laravel

I am creating a user with the api provided. I am using Laravel and trying to store data to smartrmail and docs to create new subscriber is here https://docs.smartrmail.com/en/articles/636615-list-subscribers
Each time i send request i get following error:
Server error: `POST https://go.smartrmail.com/api/v1/lists/1sptso/list_subscribers` resulted in a `500 Internal Server Error` response: {"error":"param is missing or the value is empty: subscribers"}
{"error":"param is missing or the value is empty: subscribers"}
I am using Laravel and my code is here
Route::get('smartrmail',function(){
$headers = [
'Accept' => 'application/json',
'Authorization' => 'token f91715d5-3aac-4db3-a133-4b3a9493a9a4',
'Content-Type' => 'application/json',
];
$client = new GuzzleHttp\Client([
'headers' => $headers
]);
$data = [
"subscribers"=>[
[
"email"=> "vanhalen#example.com",
"first_name"=> "van",
"last_name"=> "halen",
"subscribed"=> true,
]
]
];
$res = $client->request('POST', 'https://go.smartrmail.com/api/v1/lists/1sptso/list_subscribers', [
'form_params' => [
$data
]
]);
return($res);
// echo $res->getStatusCode();
});
Anybody help me to figure out what is wrong here. I am following this docs
https://docs.smartrmail.com/en/articles/636615-list-subscribers
to create a new subscriber
Instead of
'form_params' => [
$data
]
use
'json' => $data
Explanation
You want to send json data (I assume that because you set header 'Content-Type' => 'application/json', which means that you are sending json), but form_params is used for application/x-www-form-urlencoded.
json sets header to application/json and sends data as json.
As you set proper header, this should work too:
'body' => $data
Proper name of param you can find in Guzzle docs, I used uploading data part.

How to fix "MethodNotAllowedHttpException" when I try to make a Post request with body and headers (guzzle)

I am trying to make a post on laravel using Guzzle. I already got one post working but that one doesn't have a header that I need. The problem is when I try to include that same header and raw JSON body I always get the error: MethodNotAllowedHttpException. From my understanding this is the post request function with some structural error (just my thinking).
My code is the following:
$response = $client->request('POST', $url, [
'headers' => [
'Content-Type' => 'application/json',
'x-auth-token' => $token,
],
'body' => $body
]);
The code above is returning the error.
The following code (from a different function with different goals) just doesn't have the 'x-auth-token' header and it is working just fine:
$response = $client->request('POST', $url, [
'headers' => [
'Content-Type' => 'application/json',
],
'body' => $body
]);
$token = $response->getHeader('X-Subject-Token')[0];
Update: The error that i get is: Expecting to find auth in request body. The server could not comply with the request sin.

How to use Guzzle to send API request to the Restful that supports only XML format?

I have been using Guzzle for a while within my Laravel 5.8 project. It has been working with Restful API that supports JSON format.
Now that there is a new Restful API that supports only XML format. I don't know how to do that using Guzzle. Below is an example of what the HTTP request might look like.
POST: http://api.url_endpoint.com/my_api.ashx HTTP/1.1
Content-Type: application/x-www-form-url encoded
Host: http://api.url_endpoint.com
Content-Length: 467
Expect: 100-continue
Connection: Close
<Section>
<LoginDetails>
<Login>ABC</Login>
<Password>ABCDE</Password>
</LoginDetails>
</Section>
In the documentation, it says: The XML should be in the body of the request.
Question 1. How do I put XML in the body of the request?
Question 2. Note the HTTP/1.1, should it be concatenated as suffix of the API URL endpoint?
This is how I have tried.
$header_options = [
'headers' => [
'Accept' => 'application/xml',
'Content-Type' => 'application/x-www-form-url encoded',
'Host' => 'http://api.url_endpoint.com',
'Content-Length' => 467,
'Expect' => '100-continue',
'Connection' => 'Close',
],
'body' => '<Section><LoginDetails><Login>ABC</Login><Password>ABCDE</Password></LoginDetails></Section>',
];
$response = $client->request('POST', 'http://api.url_endpoint.com/my_api.ashx', $header_options);
dump($response->xml());
But I still get 400 Bad Request as response back.
First of all, try with just the fix of the Content-Type header value : application/x-www-form-urlencoded (not application/x-www-form urlencoded).
If this does not work, also try to parse the body like that :
$header_options = [
'headers' => [
...
'Content-Type' => 'application/x-www-form-urlencoded'
...
],
...
'body' => urlencode('<Section><LoginDetails><Login>ABC</Login><Password>ABCDE</Password></LoginDetails></Section>'),
];
If this does not work, could you try to change the header set that way :
$header_options = [
'headers' => [
...
'Content-Type' => 'text/xml', // also try 'application/xml'
...
],
...
];
Let me know if one of these ideas helped you :)

Guzzle 6 PUT request not sending form params

I have the following code that I use whenever I want to make POST requests using Guzzle:
$request = $client->request('POST', $url, [
'form_params' => $params,
'headers' => [
'Referer' => '(intentionally removed)',
'Accept' => 'application/json',
]
]);
The code works without any issues and the information within $params is always sent, however when I change the request type from POST to PUT so that the request becomes:
$request = $client->request('PUT', $url, [
'form_params' => $params,
'headers' => [
'Referer' => '(intentionally removed)',
'Accept' => 'application/json',
]
]);
The request suddenly stops sending the data contained within $params.
I have tested the endpoint the request is send to with Insomnia with both POST and PUT requests and both types are processed as expected, so I am certain the issue is not there.
What can be causing the data from Guzzle to be send using the POST method but not when using the PUT?
This behaviour described in guzzle documentation form-params
form_params - Used to send an application/x-www-form-urlencoded POST request.
Probably, you enough pass the parameters in json format:
$request = $client->request('PUT', $url, [
'json' => $params,
'headers' => [
'Referer' => '(intentionally removed)',
'Accept' => 'application/json',
]
]);

Can you include raw JSON in Guzzle POST Body?

This should be soo simple but I have spent hours searching for the answer and am truly stuck. I am building a basic Laravel application and am using Guzzle to replace the CURL request I am making at the moment. All the CURL functions utilise raw JSON variables in the body.
I am trying to create a working Guzzle client but the server is respsonding with 'invalid request' and I am just wondering if something fishy is going on with the JSON I am posting. I am starting to wonder if you can not use raw JSON in the Guzzle POST request body? I know the headers are working as I am receiving a valid response from the server and I know the JSON is valid as it is currently working in a CURL request. So I am stuck :-(
Any help would be sooo greatly appreciated.
$headers = array(
'NETOAPI_KEY' => env('NETO_API_KEY'),
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'NETOAPI_ACTION' => 'GetOrder'
);
// JSON Data for API post
$GetOrder = '{
"Filter": {
"OrderID": "N10139",
"OutputSelector": [
"OrderStatus"
]
}
}';
$client = new client();
$res = $client->post(env('NETO_API_URL'), [ 'headers' => $headers ], [ 'body' => $GetOrder ]);
return $res->getBody();
You can send a regular array as JSON via the 'json' request option; this will also automatically set the right headers:
$headers = [
'NETOAPI_KEY' => env('NETO_API_KEY'),
'Accept' => 'application/json',
'NETOAPI_ACTION' => 'GetOrder'
];
$GetOrder = [
'Filter' => [
'OrderID' => 'N10139',
'OutputSelector' => ['OrderStatus'],
],
];
$client = new client();
$res = $client->post(env('NETO_API_URL'), [
'headers' => $headers,
'json' => $GetOrder,
]);
Note that Guzzle applies json_encode() without any options behind the scenes; if you need any customisation, you're advised to do some of the work yourself
$res = $client->post(env('NETO_API_URL'), [
'headers' => $headers + ['Content-Type' => 'application/json'],
'body' => json_encode($getOrders, ...),
]);
Guzzle 7 Here
The below worked for me with raw json input
$data = array(
'customer' => '89090',
'username' => 'app',
'password' => 'pwd'
);
$url = "http://someendpoint/API/Login";
$client = new \GuzzleHttp\Client();
$response = $client->post($url, [
'headers' => ['Content-Type' => 'application/json', 'Accept' => 'application/json'],
'body' => json_encode($data)
]);
print_r(json_decode($response->getBody(), true));
For some reasons until I used the json_decode on the response, the output wasn't formatted.
You probably need to set the body mime type. This can be done easily using the setBody() method.
$request = $client->post(env('NETO_API_URL'), ['headers' => $headers]);
$request->setBody($GetOrder, 'application/json');

Categories