Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade em-http-request to version 1.1.7 #176

Merged
merged 2 commits into from Oct 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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