Skip to content

Instantly share code, notes, and snippets.

@blasterpal
Created January 17, 2013 18:58
Show Gist options
  • Select an option

  • Save blasterpal/4558577 to your computer and use it in GitHub Desktop.

Select an option

Save blasterpal/4558577 to your computer and use it in GitHub Desktop.
Modified version of Encoding Error https://gist.github.com/4534675 Gist. That emulates FbGraph 2.6.2 fix.
#!/usr/bin/env ruby
#
# How to make Ruby httpclient throw Encoding::CompatibilityError with Image/IO object on EY Server.
# Use case is update a Facebook object with a parameter containing UTF-8 escaped strings and a file upload.
# Execute with 'bundle exec <script>' on a Gemfile containing httpclient or use system gem
# The problem lies in Encoding and the request.dump method used by FbGraph debug.
# On Engine Yard servers the POSTing with httpclient with multipart Content-Types ( a file upload + the UTF-8 body content) causes
# issue when reading the image from disk. If the image is a string, no problem.
# So the root cause is Encoding + File IO + the dump method of httpclient.
# Adding a magic utf quote to httpclient-2.3.2/lib/httpclient/http.rb fixes problem.
# Likely this stems from the fact that File#read method is stated in API "The resulted string is always ASCII-8BIT encoding."
# So the ASCII result is combined with a UTF-8 string that it attempts to concatenate in the dump_file method and viola!
# Encoding::CompatibilityError is thrown.
# This class is practically 1:1 to how FbGraph implements it's debugging/logging.
# https://github.com/nov/fb_graph/blob/master/lib/fb_graph/debugger.rb
class HTTPRequestFilter
# Callback called in HTTPClient (before sending a request)
# request:: HTTP::Message
def self.filter_request(request)
ascii_buffer = ''.force_encoding(Encoding.find('ASCII'))
started = "======= [FbGraph] API REQUEST STARTED ======="
log started, request.dump
end
# Callback called in HTTPClient (after received a response)
# request:: HTTP::Message
# response:: HTTP::Message
def self.filter_response(request, response)
finished = "======= [FbGraph] API REQUEST FINISHED ======="
log '-' * 50, response.dump, finished
end
private
def self.log(*outputs)
outputs.each do |output|
puts output
end
end
end
# Let's make a simple POST to FB with an image upload.
require 'httpclient'
client = HTTPClient.new
image_string = "GIF89a\u0004\u0000\a\u0000\x80\u0001\u0000\x99\x99\x99\u0000\u0000\u0000!\xF9\u0004\u0001\u0000\u0000\u0001\u0000,\u0000\u0000\u0000\u0000\u0004\u0000\a\u0000\u0000\u0002\bD\u000E\u0016i\xEC\xABT(\u0000;"
client.request_filter << HTTPRequestFilter
token = "NOT_A_VALID_TOKEN_THATS_COOL_THIS_TEST_FAILS_BEFORE_GETTING_TO_FB"
# This body has a UTF-8 code point in it and thus forces UTF-8 on the body.
body_field = "We\u2019re giving away a widget every day in September! "
post_body = {"body" => body_field, "campaign_id" => "12345", 'upload' => image_string}
#Works fine!
puts "--------------------------->"
puts "Posting with Image string..."
client.post("https://graph.facebook.com/act_#{1234556}/adgroups?access_token=#{token}", post_body)
#let's make a real file object instead
File.open('/tmp/temp_image_file','w'){|f| f << image_string}
# Uh oh, it must be File IO that's the problem with Encoding on this system
post_body = {"body" => body_field, "campaign_id" => "1234556", 'upload' => File.open('/tmp/temp_image_file','r')}
puts "--------------------------->"
puts "Posting with image/IO object in httpclient *args hash, should blow up..."
client.post("https://graph.facebook.com/act_#{1234556}/adgroups?access_token=#{token}", post_body)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment