0
votes

I am trying to send a post request using Guzzle 6 http client. I am sending two requests one with content type as application/x-www-form-urlencoded (form_params in Guzzle) and the other as application/json (json in Guzzle).

I initialise the client as below (forms_params and json respectively):

$data1 = array("c1" => "a", "c2" => null)
$client = new Client();
$response = $client->post(
  "http://localhost/callback",
  array(
    "form_params" => $data1,          // send as x-www-form-urlencoded
  )
);


$data2 = array("c1" => "a", "c2" => null)
$client = new Client();
$response = $client->post(
  "http://localhost/callback",
  array(
    "json" => $data2,                 // send as json
  )
);

The response that I receive does have not identical data/body:

Output for form_params : Data -> {"c1":"a"}

Output for json : Data -> {"c1":"a","c2":null}

I am not understanding why it does not send identical data for above requests. Could this be a bug in Guzzle? Is there any way to solve this (apart from removing nulls before sending request)?

UPDATE : As requested endpoint code (both requests are read using same code)

if ($$_SERVER["CONTENT_TYPE"] == "application/json") {
    $jsonstr = file_get_contents("php://input");
    $formData = json_decode($jsonstr, true);
} else {
    $formData = $_POST;
}
echo "Data -> " . json_encode($formData);

UPDATE 2 : I went through the links provided in comments about this being expected behaviour in Guzzle.

But why I asked this question in first place is because I faced an issue of signature mismatch.

When I send the request, I add a header with a signature which is nothing but hash_hmac("sha256", json_encode($data), "secret_key"). So I get different signatures when sending data as json and form_params (since the data received is different in case of form_params as null values are discarded/not sent). First, I thought it might be because of a bug in Guzzle but it isn't.

Is there anyway to solve this signature issue?

1
Why would it be a bug in Guzzle if you endpoint is returning different data? Show your endpoint code so we can get a better idea of what's going on.Jonnix
@JonStirling Updated question with endpoint codeAbubakkar
Aha, this isn't strictly a bug. Guzzle appears to use http_build_query which seems to filter out stuff with empty values. I.e. in the first request, c2 isn't actually getting sent.Jonnix
Its covered here: github.com/guzzle/guzzle/issues/973 and especially here: github.com/guzzle/guzzle/issues/1181 not a bug notice the last comment.Lawrence Cherone
@JonStirling Are u sure that's the case, I only found one occurrance in Guzzle code (class - UriTemplate - method expandMatch) which calls that function. I put a breakpoint there and it didn't reach it. Not sure if I am missing something.Abubakkar

1 Answers

0
votes

As Jon Stirling and Lawrence Cherone noticed already, it's not a bug according to Guzzle's authors.

So the solution for you is to cast values to a string for form_params. It makes sense, because URL encoded format (unlike JSON) doesn't have types (all is a string). And you everyone defines own conversion rules. In PHP (using http_build_query) it works like this, skipping nulls at all.