Friday, June 10, 2011

Using Facebook's Batch API...

If you've built any type of Facebook API integration, chances are that you will gravitate towards batching up your API network requests. Since you are allowed a maximum of 20 requests per batch, you can effectively speed-up your overall performance by 14-15x (my own basic measurements) There may also be overall throttle limits to consider, but in general, the performance is a huge boost from sending individual network calls for each request.

While the API documentation is posted at http://developers.facebook.com/docs/api/batch/, there are several things that aren't well documented.

    1. You must provide some type of access token to issue Facebook Batch API requests. Even if you have access_token within the query strings of each individual request, Facebook still expects you to provide some type of access_token= in the POST request. You may encounter 404 errors without providing the access_token parameter. The access_token= parameter can either be a user OR application token. While there may be situations where you want to use a user token, what if you wanted to fetch multiple pages with different user tokens? What if the user's token has expired or he/she has changed the password, invalidating this token? For these situations, you can use the application token (http://developers.facebook.com/docs/authentication/), using the technique described in the "App Login" section. The code in Python looks like the following:
    def fb_get_app_token():
        """ For Facebook API requests, we need to get an app token to make Graph API calls.  We can't                                                                                                                       
        use fb_get_with_params() since it expects either/and a user/asset, which we don't use.  Also,                                                                                                                       
        the response from Facebook isn't in JSON format so we have to regex parse it."""
        try:
            token_request = urllib.urlencode({ 'client_id': settings.FACEBOOK_APP_ID,
                                               'client_secret': settings.FACEBOOK_SECRET_KEY,
                                               'grant_type': 'client_credentials'
                                               })
    
            token = urllib2.urlopen("https://graph.facebook.com/oauth/access_token?%s" % token_request).read()
        except urllib2.HTTPError, e:
            logging.debug("Exception trying to grab Facebook App token (%s)" % e)
            return None
    
        matches = re.match(r"access_token=(?P.*)", token).groupdict()
        return matches.get('token', '')
    
    You can then use this access_token as the fallback access token. 2. Buried within the Batch API section is the "Specifying different access tokens for different operations". The documentation states that the "access_token should be query string or form post parameter". There isn't an example of how to use it, but basically the access_token should be set in the relative_url path.
    curl -F ‘access_token=…’ \
         -F ‘batch=[{ “method”: ”GET”, \
                      "relative_url": "me?access_token=ACCESS_TOKEN1", \
                    }, \
                    { "method": "GET", \
                      "relative_url": "124456?access_token=ACCESS_TOKEN2", \
                    }]'
    
    If you try to put a separate "access_token" : "ABC", Facebook won't recognize the token. You must put it in the query string for GET requests:
    { "method": "GET", \
                      "access_token" : ACCESS_TOKEN,
                      "relative_url": "124456?access_token=ACCESS_TOKEN2", \
                    }]'
    
    3. The JSON dictionary that is returned must be JSON-decoded twice: once to retrieve the overall response, and then another to decode the 'body' key. The JSON decoder in Python doesn't seem to know how to decode nested dictionaries.

No comments:

Post a Comment