Skip to content

Commit

Permalink
🔀 Merge pull request #176 from oauth-xx/depfu/update/em-http-request-…
Browse files Browse the repository at this point in the history
…1.1.7

Upgrade em-http-request to version 1.1.7
  • Loading branch information
pboling committed Oct 31, 2021
2 parents 56a189b + 276733a commit 172b2a3
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 137 deletions.
192 changes: 96 additions & 96 deletions lib/oauth/client/em_http.rb
Expand Up @@ -4,116 +4,116 @@

# Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
# instance. This is purely syntactic sugar.
class EventMachine::HttpClient
module EventMachine
class HttpClient
attr_reader :oauth_helper

attr_reader :oauth_helper
# Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> 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 <tt>User-Agent</tt> 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)

# Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> 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 <tt>User-Agent</tt> 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
@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 <tt>options[:scheme]</tt> 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)
# 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 <tt>options[:scheme]</tt> 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
OAuth::Client::Helper.new(self, options).signature_base_string
end

# This code was lifted from the em-http-request because it was removed from
# the gem June 19, 2010
# see: http://github.com/igrigorik/em-http-request/commit/d536fc17d56dbe55c487eab01e2ff9382a62598b
def normalize_uri
@normalized_uri ||= begin
uri = @uri.dup
encoded_query = encode_query(@uri, @options[:query])
path, query = encoded_query.split("?", 2)
uri.query = query unless encoded_query.empty?
uri.path = path
uri
# This code was lifted from the em-http-request because it was removed from
# the gem June 19, 2010
# see: http://github.com/igrigorik/em-http-request/commit/d536fc17d56dbe55c487eab01e2ff9382a62598b
def normalize_uri
@normalized_uri ||= begin
uri = @conn.dup
encoded_query = encode_query(@conn, @req[:query])
path, query = encoded_query.split("?", 2)
uri.query = query unless encoded_query.empty?
uri.path = path
uri
end
end
end

protected
protected

def combine_query(path, query, uri_query)
combined_query = if query.kind_of?(Hash)
query.map { |k, v| encode_param(k, v) }.join('&')
else
query.to_s
def combine_query(path, query, uri_query)
combined_query = if query.kind_of?(Hash)
query.map { |k, v| encode_param(k, v) }.join('&')
else
query.to_s
end
if !uri_query.to_s.empty?
combined_query = [combined_query, uri_query].reject {|part| part.empty?}.join("&")
end
combined_query.to_s.empty? ? path : "#{path}?#{combined_query}"
end
if !uri_query.to_s.empty?
combined_query = [combined_query, uri_query].reject {|part| part.empty?}.join("&")
end
combined_query.to_s.empty? ? path : "#{path}?#{combined_query}"
end

# 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
# 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"
if http.respond_to?(:use_ssl?) && http.use_ssl?
uri.scheme = "https"
else
uri.scheme = "http"
end
uri.to_s
end
uri.to_s
end

def set_oauth_header
headers = (self.options[:head] ||= {})
headers['Authorization'] = @oauth_helper.header
end
def set_oauth_header
self.req[:head] ||= {}
self.req[:head].merge!('Authorization' => @oauth_helper.header)
end

def set_oauth_body
raise NotImplementedError, 'please use the set_oauth_header method instead'
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'
def set_oauth_query_string
raise NotImplementedError, 'please use the set_oauth_header method instead'
end
end

end
20 changes: 13 additions & 7 deletions lib/oauth/request_proxy/em_http_request.rb
Expand Up @@ -14,11 +14,11 @@ class HttpRequest < OAuth::RequestProxy::Base
# Request in this con

def method
request.method
request.req[:method]
end

def uri
request.normalize_uri.to_s
request.conn.normalize.to_s
end

def parameters
Expand All @@ -36,14 +36,20 @@ def all_parameters
end

def query_parameters
CGI.parse(request.normalize_uri.query.to_s)
quer = request.req[:query]
hash_quer = if quer.respond_to?(:merge)
quer
else
CGI.parse(quer.to_s)
end
CGI.parse(request.conn.query.to_s).merge(hash_quer)
end

def post_parameters
headers = request.options[:head] || {}
headers = request.req[:head] || {}
form_encoded = headers['Content-Type'].to_s.downcase.start_with?("application/x-www-form-urlencoded")
if ['POST', 'PUT'].include?(method) && form_encoded
CGI.parse(request.normalize_body.to_s)
CGI.parse(request.normalize_body(request.req[:body]).to_s)
else
{}
end
Expand All @@ -53,9 +59,9 @@ def merged_parameters(params, *extra_params)
extra_params.compact.each do |params_pairs|
params_pairs.each_pair do |key, value|
if params.has_key?(key)
params[key] += value
params[key.to_s] += value
else
params[key] = [value].flatten
params[key.to_s] = [value].flatten
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion oauth.gemspec
Expand Up @@ -42,7 +42,7 @@ Gem::Specification.new do |spec|
spec.add_development_dependency("rack-test")
spec.add_development_dependency("mocha", ">= 0.9.12", "<=1.1.0")
spec.add_development_dependency("typhoeus", ">= 0.1.13")
spec.add_development_dependency("em-http-request", "0.2.11")
spec.add_development_dependency("em-http-request", "~> 1.1.7")
spec.add_development_dependency("curb")
spec.add_development_dependency("webmock", "< 2.0")
spec.add_development_dependency("codeclimate-test-reporter")
Expand Down
31 changes: 14 additions & 17 deletions test/units/test_em_http_client.rb
Expand Up @@ -20,10 +20,12 @@ def test_that_using_auth_headers_on_get_requests_works
request = create_client
request.oauth!(@http, @consumer, @token, {:nonce => @nonce, :timestamp => @timestamp})

assert_equal 'GET', request.method
assert_equal 'GET', request.req[:method]
assert_equal '/test', request.normalize_uri.path
assert_equal "key=value", request.normalize_uri.query
assert_equal_authz_headers "OAuth oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"1oO2izFav1GP4kEH2EskwXkCRFg%3D\", oauth_version=\"1.0\"", authz_header(request)
correct_headers = "OAuth oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"1oO2izFav1GP4kEH2EskwXkCRFg%3D\", oauth_version=\"1.0\""
generated_headers = authz_header(request)
assert_equal_authz_headers correct_headers, generated_headers
end

def test_that_using_auth_headers_on_get_requests_works_with_plaintext
Expand All @@ -34,37 +36,32 @@ def test_that_using_auth_headers_on_get_requests_works_with_plaintext
request = create_client
request.oauth!(@http, c, @token, {:nonce => @nonce, :timestamp => @timestamp, :signature_method => 'PLAINTEXT'})

assert_equal 'GET', request.method
assert_equal '/test', request.normalize_uri.path
assert_equal "key=value", request.normalize_uri.query
assert_equal 'GET', request.req[:method]
assert_equal '/test', request.conn.path
assert_equal "key=value", request.conn.query
assert_equal_authz_headers "OAuth oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"PLAINTEXT\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"5888bf0345e5d237%263196ffd991c8ebdb\", oauth_version=\"1.0\"", authz_header(request)
end

def test_that_using_auth_headers_on_post_requests_works
request = create_client(:uri => "http://example.com/test", :method => "POST", :body => @request_parameters, :head => {"Content-Type" => "application/x-www-form-urlencoded"})
request.oauth!(@http, @consumer, @token, {:nonce => @nonce, :timestamp => @timestamp})

assert_equal 'POST', request.method
assert_equal '/test', request.uri.path
assert_equal 'key=value', request.normalize_body
assert_equal 'POST', request.req[:method]
assert_equal '/test', request.conn.path
assert_equal_authz_headers "OAuth oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"26g7wHTtNO6ZWJaLltcueppHYiI%3D\", oauth_version=\"1.0\"", authz_header(request)
assert_equal 'key=value', request.normalize_body(request.req[:body])
end

protected

def create_client(options = {})
method = options.delete(:method) || "GET"
uri = options.delete(:uri) || @request_uri.to_s
client = EventMachine::HttpClient.new("")
client.uri = URI.parse(uri)
client.method = method.to_s.upcase
client.options = options
client
options[:method] = options.key?(:method) ? options[:method].upcase : "GET"
uri = options.delete(:uri) || @request_uri.to_s
EventMachine::HttpClient.new(URI.parse(uri), options)
end

def authz_header(request)
headers = request.options[:head] || {}
headers['Authorization'].to_s
request.req[:head]['Authorization']
end

def assert_equal_authz_headers(expected, actual)
Expand Down
26 changes: 10 additions & 16 deletions test/units/test_em_http_request_proxy.rb
Expand Up @@ -5,7 +5,6 @@
require 'em-http'
require 'oauth/request_proxy/em_http_request'


class EmHttpRequestProxyTest < Minitest::Test

def test_request_proxy_works_with_simple_request
Expand Down Expand Up @@ -70,7 +69,7 @@ def test_request_proxy_works_with_argument_params
end

def test_request_proxy_works_with_mixed_params
proxy = create_request_proxy(:proxy_options => {:parameters => {"a" => "1"}},:query => {"c" => "1"}, :uri => "http://example.com/test?b=1")
proxy = create_request_proxy(:proxy_options => {:parameters => {"a" => "1"}}, :query => {"c" => "1"}, :uri => "http://example.com/test?b=1")
assert_equal({"a" => ["1"], "b" => ["1"], "c" => ["1"]}, proxy.parameters)
proxy = create_request_proxy(:proxy_options => {:parameters => {"a" => "1"}}, :body => {"b" => "1"}, :query => {"c" => "1"},
:uri => "http://example.com/test?d=1", :method => "POST", :head => {"Content-Type" => "application/x-www-form-urlencoded"})
Expand All @@ -79,28 +78,23 @@ def test_request_proxy_works_with_mixed_params

def test_request_has_the_correct_uri
assert_equal "http://example.com/", create_request_proxy.uri
assert_equal "http://example.com/?a=1", create_request_proxy(:query => "a=1").uri
assert_equal "http://example.com/?a=1", create_request_proxy(:query => {"a" => "1"}).uri

assert_equal "http://example.com/?a=1", create_request_proxy(:query => "a=1").request.normalize_uri.to_s
assert_equal "http://example.com/?a=1", create_request_proxy(:query => {"a" => "1"}).request.normalize_uri.to_s
end

def test_request_proxy_has_correct_method
assert_equal "GET", create_request_proxy(:method => "GET").method
assert_equal "PUT", create_request_proxy(:method => "PUT").method
assert_equal "POST", create_request_proxy(:method => "POST").method
assert_equal "DELETE", create_request_proxy(:method => "DELETE").method
assert_equal "GET", create_request_proxy(:method => "GET").request.req[:method]
assert_equal "PUT", create_request_proxy(:method => "PUT").request.req[:method]
assert_equal "POST", create_request_proxy(:method => "POST").request.req[:method]
assert_equal "DELETE", create_request_proxy(:method => "DELETE").request.req[:method]
end

protected

def create_client(options = {})
method = options.delete(:method) || "GET"
uri = options.delete(:uri) || "http://example.com/"
client = EventMachine::HttpClient.new("")
client.uri = URI.parse(uri)
client.method = method.to_s.upcase
client.options = options
client
options[:method] = options.key?(:method) ? options[:method].upcase : "GET"
uri = options.delete(:uri) || "http://example.com/"
EventMachine::HttpClient.new(URI.parse(uri), options)
end

def create_request_proxy(opts = {})
Expand Down

0 comments on commit 172b2a3

Please sign in to comment.