4

I'm using the Imgur API to upload images. They have detailed in their API docs that each request (when I upload an image via their API) also has response headers, which will tell me how much credit the account has left.

I need to return the HTTP response header X-RateLimit-ClientRemaining. Here is the code I am currently using to get the cURL body back:

$filename = dirname(realpath(__FILE__))."/images/$value";
$client_id = "f*************c";
$handle = fopen($filename, "r");
$data = fread($handle, filesize($filename));
$pvars   = array('image' => base64_encode($data));
$timeout = 30;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://api.imgur.com/3/image.json');
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Client-ID ' . $client_id));
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $pvars);
$out = curl_exec($curl);
curl_close ($curl);
$pms = json_decode($out,true);
$url=$pms['data']['link'];
if($url!=""){
    // add to success
    array_push($success, $url);
}
else {
    // add to fail
    $p = $value.' failed, error: '.$pms['data']['error'];
    array_push($fail, $p);
}

($value is coming from a loop I have not included)

James
  • 1,088
  • 3
  • 11
  • 29

1 Answers1

5

Why not try

curl_setopt($curl, CURLOPT_HEADER, 1);

To receive both headers and content. All you need to do is parse headers from the $out variable.

Here's fully working example while fetching from Google:

<?php

error_reporting(E_ALL);
ini_set('display_errors', 'On');
header('Content-Type: text/plain; charset=utf-8');

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://www.google.com/');
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
$out = curl_exec($curl);
curl_close ($curl);

$out = preg_split('/(\r?\n){2}/', $out, 2);
$headers = $out[0];
$headersArray = preg_split('/\r?\n/', $headers);
$headersArray = array_map(function($h) {
    return preg_split('/:\s{1,}/', $h, 2);
}, $headersArray);

$tmp = [];
foreach($headersArray as $h) {
    $tmp[strtolower($h[0])] = isset($h[1]) ? $h[1] : $h[0];
}
$headersArray = $tmp; $tmp = null;
// $headersArray contains your headers
print_r($headersArray);
?>

This produces:

Array
(
    [http/1.1 200 ok] => HTTP/1.1 200 OK
    [date] => Thu, 29 Oct 2015 13:26:39 GMT
    [expires] => -1
    [cache-control] => private, max-age=0
    [content-type] => text/html; charset=ISO-8859-1
    [p3p] => CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
    [server] => gws
    [x-xss-protection] => 1; mode=block
    [x-frame-options] => SAMEORIGIN
    [set-cookie] => NID=72=lw6pIMe05MoXu3aykbPi0BR9gZomWqTXBwsk6VG7xtLbLLeWc0I__CLGydE-auttR0G8VulKoZOTrv4eAZovJJi9QyB5hgxBue9pLWcX794Iv6gPlM2QaL9I2t6tjtrADtczAZpHhbnLvjmeDn_AmRj0xKkFPrMhYR84C5lNgzgo1iJpzr5qG2y6xg; expires=Fri, 29-Apr-2016 13:26:39 GMT; path=/; domain=.google.com; HttpOnly
    [alternate-protocol] => 443:quic,p=1
    [alt-svc] => quic="www.google.com:443"; p="1"; ma=600,quic=":443"; p="1"; ma=600
    [accept-ranges] => none
    [vary] => Accept-Encoding
    [transfer-encoding] => chunked
)

From your example above, you'd seek $headersArray['x-ratelimit-clientremaining'];

Hope that helps.

Edit: here's the quick way (because your response does not contain linefeeds):

$matches = null;
preg_match('/X-RateLimit-ClientRemaining:\s*(\d+)/i', $out, $matches);
echo sprintf('X-RateLimit-ClientRemaining: %u', $matches[1]);

Produces:

X-RateLimit-ClientRemaining: 11850
jpaljasma
  • 1,612
  • 16
  • 21
  • Doesn't work. I can see the headers being returned, however they aren't going into $headersArray; all there is is one element: [1]=>string(1) "1" – James Oct 29 '15 at 13:48
  • You may need to alter the functionality a bit to work with your code - the example works with www.google.com but probably not with your api. Can you send me the response from your API as text? Use gist if needed ... I'll adjust parsing function. – jpaljasma Oct 29 '15 at 14:04
  • Where are all the linefeeds gone from the API response? No wonder its hard to parse it... – jpaljasma Oct 29 '15 at 14:10
  • Who knows. I'm literally using your code, not familiar with the use of this API at all so I'm just stabbing in the dark here. Thanks for trying to help though :) – James Oct 29 '15 at 14:12
  • @James take a look now ... hope this helps. – jpaljasma Oct 29 '15 at 14:17
  • Where did $matches come from? – James Oct 29 '15 at 14:21
  • Take a look at the http://php.net/manual/en/function.preg-match.php - it explains in detail where $matches come from. – jpaljasma Oct 29 '15 at 14:58