1

I'm working with a third party API, and it returns 400 HTTP STATUS when you make a mistake. When using POSTMAN, the 400 HTTP error page shows as expected, but when using PHP's cURL, the page just loads for about a minute, then it gives me a "504 - Gateway timeout", and I need to close the browser to be able to access the page again. When the cURL request is valid (the API returns a 200 OK) it works normally.

My question is, why is cURL giving the 504 error instead of 400? And why is it ignoring CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT?

Below is my cURL code (both $token, $payload and $config variables are declared and valid):

$ch = curl_init("https://api.mercadolibre.com/items?access_token=$token");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    "User-Agent: Alcavie/" . $config['version'],
    "Accept: application/json",
    "Content-Type: application/json",
    //"Accept-Encoding: gzip, deflate, br",
    //"Connection: keep-alive"
));

$error = false;
try{
    $result = curl_exec($ch);
    $resultJson = json_decode($result);
}catch(\Exception $e){
    var_dump($e);
    $error = true;
    exit;
}
curl_close($ch);
Thiago Souza
  • 171
  • 3
  • 12
  • 504 Gateway Timeout is emmited by the backend server of this API not in the request, which is different, 408 Request Timeout. I guess the headers maybe be wrong, check the User-Agent, the token, or other config that Postman has and the curl isn't config with. – Eduardo Ramos Oct 06 '20 at 21:29

1 Answers1

3

The API probably sends HTTP302 in between and if so, you'd either need two requests or
tell cURL to follow the redirect with curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
HTTP504 means that the client didn't react in a timely manner upon the previous HTTP header;
there may be other causes for HTTP504, but it is one of the most common. Postman is insufficient to test this properly (I don't use it at all); better use a web-browser, hit F12 and tick the "preserve logs" checkbox... then you can clearly see which HTTP headers are being sent in succession.

Also useful to debug this would be: curl_setopt($ch, CURLOPT_HEADER, true);

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • Even after setting FOLLOWLOCATION, I get the same result: almost infinite loading, then a 504 error in my browser. And the CURLOPT_HEADER just makes the cURL fail btw – Thiago Souza Oct 07 '20 at 12:46
  • @Thiago This option should list all headers sent & received. Make sure you use a sane environment. https://curl.haxx.se/libcurl/c/CURLOPT_HEADER.html ...and "just makes it fail" is not an error description at all, because it barely fails without a reason. If you just take a simple HTML form and post that, it should be testable in a web-browser. Improving the cURL error handling might also make sense, because you don't follow the default procedure there; `var_dump($e)` is useless.... use `curl_error($ch)`, in order not to ignore eventual errors. – Martin Zeitler Oct 07 '20 at 15:03
  • Also see http://developers.mercadolibre.com/listing-introduction ...the payload may be wrongful. Sorry, but I don't understand any of this and can only refer to: https://api.mercadolibre.com/items#options ... GET `/items` just gives me `resource not found` (likely because it expects a POST). Generally cURL just emulates a web-browser, that's why one can use a web-browser to know for certain what to emulate. – Martin Zeitler Oct 07 '20 at 15:16
  • The point is that the code doesn't even hit the catch{ }, so the curl_error is useless as well; The "just makes if fail" happens when I add the CURLOPT_HEADER, it gives me the same loading forever then 504, even when the payload is right (by right I mean: works without the CURLOPT_HEADER) The documentation of the API is in portuguese, so its normal for you to not understand it. I need to catch those API errors because the client *may* commit mistakes sometimes, and giving 'em a "504 - Gateway timeout" page isn't good at all – Thiago Souza Oct 07 '20 at 16:26
  • Can you access any routes that use GET, eg. listing those items? An `Exception` is not necessary be thrown, but if there was an error, it can be obtained from the cURL handle. My code usually doesn't look much different (except the error handling), but I usually just call `curl_init()` and then set the URL along with the options. With option `CURLOPT_HEADER` enabled, you ordinary should get output similar to this: https://stackoverflow.com/a/3252889/549372 ...which is quite essential for debugging. – Martin Zeitler Oct 07 '20 at 17:29
  • I've added the CURLOPT_HEADER along with a check to see if curl_error($ch) is empty or not, and turns out it worked!? Even when the API gives errors the page continues smooth instead of the 504 gateway timed out, thanks! – Thiago Souza Oct 07 '20 at 20:42