How do I encode the & symbol for batch requests?
-
25-01-2021 - |
Question
I have a Facebook batch request that looks like this:
https://graph.facebook.com/?access_token=ACCESS_TOKEN&batch=[{"method": "GET", "relative_url": "search?q=EMAIL@ADDRESS.COM&type=user"}]
Sending this across the wire returns:
{"error"=>0, "error_description"=>"batch parameter must be a JSON array"}
If I remove the &type=user
, it works fine (sends back an empty data array). I am absolutely certain that Facebook is not parsing the & character correctly. I read online somewhere that I could try encoding the & symbol to %26, however using that replacement seems to instead do a query for "EMAIL@ADDRESS.COM%26type=user". If you reverse the order of the parameters, you will see what I mean.
Any ideas how I can get the batch request parser on Facebook to recognize the & symbol without filing a bug report that will never be fixed?
EDIT:
I am using URI.encode. Here is the exact code:
queries = email_array.map { |email| { :method => "GET", :relative_url => "search?q=#{email}&type=user" } }
route = "https://graph.facebook.com/?access_token=#{token}&batch=#{URI.encode(queries.to_json)}"
res = HTTParty.post(route)
Solution
After actually playing around with this some more, I managed to reproduce the same behavior, even with a careful check and double-check that I was following the api specs correctly. This looks like a bug in facebook's batch method -- it doesn't understand ampersands in param values correctly.
OTHER TIPS
Don't use a string literal to construct the json. Use to_json
, like below. (Also, as an aside, don't use {}
notation across more than one line, use do
/end
).
queries = []
email_array.each do |email|
queries << {:method => 'GET', :relative_url => "search?q=#{email}&type=user"}
end
route = "https://graph.facebook.com/?access_token=#{token}&batch=#{URI.encode(queries.to_json)}"
res = HTTParty.post(route)
Also, you can use Array#map
to simply the code, like this:
queries = email_array.map { |email| {:method => 'GET', :relative_url => "search?q=#{email}&type=user"} }
route = "https://graph.facebook.com/?access_token=#{token}&batch=#{URI.encode(queries.to_json)}"
res = HTTParty.post(route)
EDIT: below is my original answer before the question was edited, for reference.
Try properly url encoding the whole parameter:
https://graph.facebook.com/?access_token=ACCESS_TOKEN&batch=[%7B%22method%22:%20%22GET%22,%20%22relative_url%22:%20%22search?q=EMAIL@ADDRESS.COM&type=user%22%7D]
In practice, you'd use URI.encode
from the uri
library to do this. Example:
irb(main):001:0> require 'uri'
=> true
irb(main):002:0> URI.encode('[{"method": "GET", "relative_url": "search?q=EMAIL@ADDRESS.COM&type=user"}]')
=> "[%7B%22method%22:%20%22GET%22,%20%22relative_url%22:%20%22search?q=EMAIL@ADDRESS.COM&type=user%22%7D]"
Or even better, use to_json
to create your json string in the first place. Example:
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'json'
=> true
irb(main):003:0> require 'uri'
=> true
irb(main):004:0> URI.encode([{:method => 'GET', :relative_url => 'search?q=EMAIL@ADDRESS.COM&type=user'}].to_json)
=> "[%7B%22method%22:%22GET%22,%22relative_url%22:%22search?q=EMAIL@ADDRESS.COM&type=user%22%7D]"
If this helps anyone, when my AdSet batch update failed because there was an "&" in one of the interests name:
{u'id': u'6003531450398', u'name': u'Dolce & Gabbana'}
I learned that the name can be anything, and as long as the id is correct, FB will populate the name itself.