require 'em-http'
require 'oauth/helper'
require 'oauth/client/helper'
require 'oauth/request_proxy/em_http_request'
# Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
# instance. This is purely syntactic sugar.
class EventMachine::HttpClient
attr_reader :oauth_helper
# Add the OAuth information to an HTTP request. Depending on the options[:scheme] setting
# this may add a header, additional query string parameters, or additional POST body parameters.
# The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
# header.
#
# * http - Configured Net::HTTP instance, ignored in this scenario except for getting host.
# * consumer - OAuth::Consumer instance
# * token - OAuth::Token instance
# * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
# +signature_method+, +nonce+, +timestamp+)
#
# This method also modifies the User-Agent header to add the OAuth gem version.
#
# See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1]
def oauth!(http, consumer = nil, token = nil, options = {})
options = { :request_uri => normalized_oauth_uri(http),
:consumer => consumer,
:token => token,
:scheme => 'header',
:signature_method => nil,
:nonce => nil,
:timestamp => nil }.merge(options)
@oauth_helper = OAuth::Client::Helper.new(self, options)
self.__send__(:"set_oauth_#{options[:scheme]}")
end
# Create a string suitable for signing for an HTTP request. This process involves parameter
# normalization as specified in the OAuth specification. The exact normalization also depends
# on the options[:scheme] being used so this must match what will be used for the request
# itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
# header.
#
# * http - Configured Net::HTTP instance
# * consumer - OAuth::Consumer instance
# * token - OAuth::Token instance
# * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
# +signature_method+, +nonce+, +timestamp+)
#
# See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
def signature_base_string(http, consumer = nil, token = nil, options = {})
options = { :request_uri => normalized_oauth_uri(http),
:consumer => consumer,
:token => token,
:scheme => 'header',
:signature_method => nil,
:nonce => nil,
:timestamp => nil }.merge(options)
OAuth::Client::Helper.new(self, options).signature_base_string
end
protected
# Since we expect to get the host etc details from the http instance (...),
# we create a fake url here. Surely this is a horrible, horrible idea?
def normalized_oauth_uri(http)
uri = URI.parse(normalize_uri.path)
uri.host = http.address
uri.port = http.port
if http.respond_to?(:use_ssl?) && http.use_ssl?
uri.scheme = "https"
else
uri.scheme = "http"
end
uri.to_s
end
def set_oauth_header
headers = (self.options[:head] ||= {})
headers['Authorization'] = @oauth_helper.header
end
def set_oauth_body
raise NotImplementedError, 'please use the set_oauth_header method instead'
end
def set_oauth_query_string
raise NotImplementedError, 'please use the set_oauth_header method instead'
end
end