0

I am using this PHP Class for Instagram's API: https://github.com/cosenary/Instagram-PHP-API. It works perfectly but I can't seem to access the rate limit information for each call I make.

Inside the class, this is the method that makes the call:

protected function _makeCall($function, $auth = false, $params = null, $method = 'GET') {
        if (false === $auth) {
            $authMethod = '?client_id=' . $this->getApiKey();
        } else {
            if (true === isset($this->_accesstoken)) {
                $authMethod = '?access_token=' . $this->getAccessToken();
            } else {
                throw new \Exception("Error: _makeCall() | $function - This method requires an authenticated users access token.");
            }
        }

        if (isset($params) && is_array($params)) {
            $paramString = '&' . http_build_query($params);
        } else {
            $paramString = null;
        }

        $apiCall = self::API_URL . $function . $authMethod . (('GET' === $method) ? $paramString : null);

        $headerData = array('Accept: application/json');
        if (true === $this->_signedheader && 'GET' !== $method) {
            $headerData[] = 'X-Insta-Forwarded-For: ' . $this->_signHeader();
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $apiCall);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerData);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        if ('POST' === $method) {
            curl_setopt($ch, CURLOPT_POST, count($params));
            curl_setopt($ch, CURLOPT_POSTFIELDS, ltrim($paramString, '&'));
        } else if ('DELETE' === $method) {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
        }

        $jsonData = curl_exec($ch);

        if (false === $jsonData) {
            throw new \Exception("Error: _makeCall() - cURL error: " . curl_error($ch));
        }

        curl_close($ch);
        return json_decode($jsonData);
    }

The information I need to access from Instagram's API is:

  • X-Ratelimit-Limit
  • X-Ratelimit-Remaining

(http://instagram.com/developer/limits/ for more information about Instagram's limits).

For obvious reasons I need the app I'm creating to "shut itself down" before the rate limit kicks in. By accessing the rate limit information I can achieve this.

I have found a Gist that should work with this class but I can't seem to get it to work: https://gist.github.com/cosenary/6af4cf4b509518169b88

Also this topic here on Stackoverflow seems to be fruitless: Instagram API count limits using HTTP header

If anyone could help me out here that would be amazing!

Best regards, Peter de Leeuw

Community
  • 1
  • 1
  • Could you add some code snippets? Thanks. – C R Dec 21 '14 at 01:46
  • @rozkosz that seems undoable in this case. Normally I would add snippets but I have no idea what to add now. –  Dec 21 '14 at 01:47
  • @rozkosz I added a snippet of method inside the class that makes the call. I assume somewhere in there I should be able to retrieve the desired information. –  Dec 21 '14 at 02:06

1 Answers1

1

I have modified the function _makeCall and it is as follows by adding first curl_setopt($ch, CURLOPT_HEADER, true); and calling the function processHeader() as cosenary suggested on this gist cosenary/ratelimit.php:

protected function _makeCall($function, $auth = false, $params = null, $method = 'GET') {
if (false === $auth) {
  // if the call doesn't requires authentication
  $authMethod = '?client_id=' . $this->getApiKey();
} else {
  // if the call needs an authenticated user
  if (true === isset($this->_accesstoken)) {
    $authMethod = '?access_token=' . $this->getAccessToken();
  } else {
    throw new \Exception("Error: _makeCall() | $function - This method requires an authenticated users access token.");
  }
}

if (isset($params) && is_array($params)) {
  $paramString = '&' . http_build_query($params);
} else {
  $paramString = null;
}

$apiCall = self::API_URL . $function . $authMethod . (('GET' === $method) ? $paramString : null);

// signed header of POST/DELETE requests
$headerData = array('Accept: application/json');
if (true === $this->_signedheader && 'GET' !== $method) {
  $headerData[] = 'X-Insta-Forwarded-For: ' . $this->_signHeader();
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiCall);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerData);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

if ('POST' === $method) {
  curl_setopt($ch, CURLOPT_POST, count($params));
  curl_setopt($ch, CURLOPT_POSTFIELDS, ltrim($paramString, '&'));
} else if ('DELETE' === $method) {
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
}

$jsonData = curl_exec($ch);

// split header from JSON data
// and assign each to a variable
list($headerContent, $jsonData) = explode("\r\n\r\n", $jsonData, 2);

// convert header content into an array
$headers = $this->processHeaders($headerContent);

// get the 'X-Ratelimit-Remaining' header value
$ratelimitRemaining = $headers['X-Ratelimit-Remaining'];

$this->setHeaderLimit($ratelimitRemaining);


if (false === $jsonData) {
  throw new \Exception("Error: _makeCall() - cURL error: " . curl_error($ch));
}
curl_close($ch);

return json_decode($jsonData);
}

the processHeader() method which processes the header and the set and get methods for the $rateLimitRemaining are as follows :

private function processHeaders($headerContent){

$headers = array();

foreach (explode("\r\n", $headerContent) as $i => $line) {
  if($i===0){
    $headers['http_code'] = $line;
  }else{
    list($key,$value) = explode(':', $line);
    $headers[$key] = $value;
  }
}
return $headers;
}


private function setHeaderLimit($HeaderLimit){

  $this->HeaderLimit = $HeaderLimit;
}

public function getHeaderLimit(){

  return $this->HeaderLimit;
}

You can access the X-Ratelimit-Remaining now from another class just by calling the getHeaderLimit()

*Don't forget to declare the public field HeaderLimit within the class where _makeCall() resides, which in this case is Instagram.php.

**I have tested this solution and it works perfectly.

Hope this helps you guys :)

  • Great! That seems to work. I can now see how many global requests I have left (starting from 5000 per hour per token). Do you think it's also possible to see the limits of specific endpoints like media likes or follows(as shown here" http://instagram.com/developer/limits/)? –  Jan 04 '15 at 18:48
  • I have been using the API Console provided by Instagram on its developer page for debugging purposes and I added the X-Insta-Forwarded-For header,signed it with my ip+hmac but from what I can see there doesn't seem to be any extra special header field(other than the usual one with 5000) showing the X-Rate-Limit of signed api calls(in my case POST calls). Hope the above solution has helped you with your apps ;) – Gëzim Musliaj Jan 05 '15 at 21:29