bixby-auth 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +245 -0
- data/LICENSE.txt +20 -0
- data/README.md +19 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/bixby-auth.gemspec +129 -0
- data/lib/api-auth.rb +2 -0
- data/lib/api_auth/base.rb +105 -0
- data/lib/api_auth/errors.rb +12 -0
- data/lib/api_auth/headers.rb +82 -0
- data/lib/api_auth/helpers.rb +39 -0
- data/lib/api_auth/railtie.rb +129 -0
- data/lib/api_auth/request_drivers/action_controller.rb +84 -0
- data/lib/api_auth/request_drivers/action_dispatch.rb +17 -0
- data/lib/api_auth/request_drivers/bixby_request.rb +65 -0
- data/lib/api_auth/request_drivers/curb.rb +72 -0
- data/lib/api_auth/request_drivers/httpi.rb +82 -0
- data/lib/api_auth/request_drivers/net_http.rb +98 -0
- data/lib/api_auth/request_drivers/rack.rb +88 -0
- data/lib/api_auth/request_drivers/rest_client.rb +98 -0
- data/lib/api_auth/request_drivers.rb +21 -0
- data/lib/api_auth.rb +10 -0
- data/lib/bixby-auth.rb +3 -0
- data/spec/api_auth_spec.rb +660 -0
- data/spec/application_helper.rb +2 -0
- data/spec/fixtures/upload.png +0 -0
- data/spec/headers_spec.rb +356 -0
- data/spec/helpers_spec.rb +14 -0
- data/spec/railtie_spec.rb +134 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/test_helper.rb +2 -0
- data/test/helper.rb +35 -0
- data/test/test_bixby-auth.rb +7 -0
- metadata +346 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
# Builds the canonical string given a request object.
|
4
|
+
class Headers
|
5
|
+
|
6
|
+
include RequestDrivers
|
7
|
+
|
8
|
+
def initialize(request)
|
9
|
+
@original_request = request
|
10
|
+
@request = initialize_request_driver(request)
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize_request_driver(request)
|
15
|
+
clazz = request.class.to_s
|
16
|
+
if RequestDrivers.drivers.include?(clazz) then
|
17
|
+
return RequestDrivers.drivers[clazz].new(request)
|
18
|
+
|
19
|
+
elsif clazz == "ActionController::TestRequest" then
|
20
|
+
# special handling for rails 3 vs 4
|
21
|
+
if defined?(ActionDispatch) then
|
22
|
+
return ActionDispatchRequest.new(request)
|
23
|
+
else
|
24
|
+
return ActionControllerRequest.new(request)
|
25
|
+
end
|
26
|
+
|
27
|
+
elsif Module.const_defined?(:Rack) && Rack.const_defined?(:Request) && request.kind_of?(Rack::Request) then
|
28
|
+
# this goes last because TestRequest is also a subclass of Rack::Request
|
29
|
+
return RackRequest.new(request)
|
30
|
+
end
|
31
|
+
|
32
|
+
raise UnknownHTTPRequest, "#{clazz} is not yet supported."
|
33
|
+
end
|
34
|
+
private :initialize_request_driver
|
35
|
+
|
36
|
+
# Returns the request timestamp
|
37
|
+
def timestamp
|
38
|
+
@request.timestamp
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the canonical string computed from the request's headers
|
42
|
+
def canonical_string
|
43
|
+
[ @request.content_type,
|
44
|
+
@request.content_md5,
|
45
|
+
@request.request_uri.gsub(/https?:\/\/[^(,|\?|\/)]*/,''), # remove host
|
46
|
+
@request.timestamp
|
47
|
+
].join(",")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the authorization header from the request's headers
|
51
|
+
def authorization_header
|
52
|
+
@request.authorization_header
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_date
|
56
|
+
@request.set_date if @request.timestamp.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
def calculate_md5
|
60
|
+
@request.populate_content_md5 if @request.content_md5.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
def md5_mismatch?
|
64
|
+
if @request.content_md5.empty?
|
65
|
+
false
|
66
|
+
else
|
67
|
+
@request.md5_mismatch?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Sets the request's authorization header with the passed in value.
|
72
|
+
# The header should be the ApiAuth HMAC signature.
|
73
|
+
#
|
74
|
+
# This will return the original request object with the signed Authorization
|
75
|
+
# header already in place.
|
76
|
+
def sign_header(header)
|
77
|
+
@request.set_auth_header header
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
module Helpers # :nodoc:
|
4
|
+
|
5
|
+
def b64_encode(string)
|
6
|
+
if Base64.respond_to?(:strict_encode64)
|
7
|
+
Base64.strict_encode64(string)
|
8
|
+
else
|
9
|
+
# Fall back to stripping out newlines on Ruby 1.8.
|
10
|
+
Base64.encode64(string).gsub(/\n/, '')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def md5_base64digest(string)
|
15
|
+
if Digest::MD5.respond_to?(:base64digest)
|
16
|
+
Digest::MD5.base64digest(string)
|
17
|
+
else
|
18
|
+
b64_encode(Digest::MD5.digest(string))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Capitalizes the keys of a hash
|
23
|
+
def capitalize_keys(hsh)
|
24
|
+
capitalized_hash = {}
|
25
|
+
hsh.each_pair {|k,v| capitalized_hash[k.to_s.upcase] = v }
|
26
|
+
capitalized_hash
|
27
|
+
end
|
28
|
+
|
29
|
+
def time_as_httpdate
|
30
|
+
Helpers.time_as_httpdate
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.time_as_httpdate
|
34
|
+
Time.now.utc.strftime("%a, %d %b %Y %T GMT")
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
# Integration with Rails
|
4
|
+
#
|
5
|
+
class Rails # :nodoc:
|
6
|
+
|
7
|
+
module ControllerMethods # :nodoc:
|
8
|
+
|
9
|
+
module InstanceMethods # :nodoc:
|
10
|
+
|
11
|
+
def get_api_access_id_from_request
|
12
|
+
ApiAuth.access_id(request)
|
13
|
+
end
|
14
|
+
|
15
|
+
def api_authenticated?(secret_key)
|
16
|
+
ApiAuth.authentic?(request, secret_key)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
unless defined?(ActionController)
|
22
|
+
begin
|
23
|
+
require 'rubygems'
|
24
|
+
gem 'actionpack'
|
25
|
+
gem 'activesupport'
|
26
|
+
require 'action_controller'
|
27
|
+
require 'active_support'
|
28
|
+
rescue LoadError
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if defined?(ActionController::Base)
|
34
|
+
ActionController::Base.send(:include, ControllerMethods::InstanceMethods)
|
35
|
+
end
|
36
|
+
|
37
|
+
end # ControllerMethods
|
38
|
+
|
39
|
+
module ActiveResourceExtension # :nodoc:
|
40
|
+
|
41
|
+
module ActiveResourceApiAuth # :nodoc:
|
42
|
+
|
43
|
+
def self.included(base)
|
44
|
+
base.extend(ClassMethods)
|
45
|
+
|
46
|
+
if base.respond_to?('class_attribute')
|
47
|
+
base.class_attribute :hmac_access_id
|
48
|
+
base.class_attribute :hmac_secret_key
|
49
|
+
base.class_attribute :use_hmac
|
50
|
+
else
|
51
|
+
base.class_inheritable_accessor :hmac_access_id
|
52
|
+
base.class_inheritable_accessor :hmac_secret_key
|
53
|
+
base.class_inheritable_accessor :use_hmac
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
module ClassMethods
|
59
|
+
|
60
|
+
def with_api_auth(access_id, secret_key)
|
61
|
+
self.hmac_access_id = access_id
|
62
|
+
self.hmac_secret_key = secret_key
|
63
|
+
self.use_hmac = true
|
64
|
+
|
65
|
+
class << self
|
66
|
+
alias_method_chain :connection, :auth
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def connection_with_auth(refresh = false)
|
71
|
+
c = connection_without_auth(refresh)
|
72
|
+
c.hmac_access_id = self.hmac_access_id
|
73
|
+
c.hmac_secret_key = self.hmac_secret_key
|
74
|
+
c.use_hmac = self.use_hmac
|
75
|
+
c
|
76
|
+
end
|
77
|
+
|
78
|
+
end # class methods
|
79
|
+
|
80
|
+
module InstanceMethods
|
81
|
+
end
|
82
|
+
|
83
|
+
end # BaseApiAuth
|
84
|
+
|
85
|
+
module Connection
|
86
|
+
|
87
|
+
def self.included(base)
|
88
|
+
base.send :alias_method_chain, :request, :auth
|
89
|
+
base.class_eval do
|
90
|
+
attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def request_with_auth(method, path, *arguments)
|
95
|
+
if use_hmac && hmac_access_id && hmac_secret_key
|
96
|
+
h = arguments.last
|
97
|
+
tmp = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(path, h)
|
98
|
+
tmp.body = arguments[0] if arguments.length > 1
|
99
|
+
ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key)
|
100
|
+
arguments.last['Content-MD5'] = tmp['Content-MD5'] if tmp['Content-MD5']
|
101
|
+
arguments.last['DATE'] = tmp['DATE']
|
102
|
+
arguments.last['Authorization'] = tmp['Authorization']
|
103
|
+
end
|
104
|
+
|
105
|
+
request_without_auth(method, path, *arguments)
|
106
|
+
end
|
107
|
+
|
108
|
+
end # Connection
|
109
|
+
|
110
|
+
unless defined?(ActiveResource)
|
111
|
+
begin
|
112
|
+
require 'rubygems'
|
113
|
+
gem 'activeresource'
|
114
|
+
require 'active_resource'
|
115
|
+
rescue LoadError
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
if defined?(ActiveResource)
|
121
|
+
ActiveResource::Base.send(:include, ActiveResourceApiAuth)
|
122
|
+
ActiveResource::Connection.send(:include, Connection)
|
123
|
+
end
|
124
|
+
|
125
|
+
end # ActiveResourceExtension
|
126
|
+
|
127
|
+
end # Rails
|
128
|
+
|
129
|
+
end # ApiAuth
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
module RequestDrivers # :nodoc:
|
4
|
+
|
5
|
+
class ActionControllerRequest # :nodoc:
|
6
|
+
|
7
|
+
include ApiAuth::Helpers
|
8
|
+
|
9
|
+
def initialize(request)
|
10
|
+
@request = request
|
11
|
+
@headers = fetch_headers
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_auth_header(header)
|
16
|
+
@request.env["Authorization"] = header
|
17
|
+
@headers = fetch_headers
|
18
|
+
@request
|
19
|
+
end
|
20
|
+
|
21
|
+
def calculated_md5
|
22
|
+
body = @request.raw_post
|
23
|
+
md5_base64digest(body)
|
24
|
+
end
|
25
|
+
|
26
|
+
def populate_content_md5
|
27
|
+
if @request.put? || @request.post?
|
28
|
+
@request.env["Content-MD5"] = calculated_md5
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def md5_mismatch?
|
33
|
+
if @request.put? || @request.post?
|
34
|
+
calculated_md5 != content_md5
|
35
|
+
else
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def fetch_headers
|
41
|
+
capitalize_keys @request.env
|
42
|
+
end
|
43
|
+
|
44
|
+
def content_type
|
45
|
+
value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
|
46
|
+
value.nil? ? "" : value
|
47
|
+
end
|
48
|
+
|
49
|
+
def content_md5
|
50
|
+
value = find_header(%w(CONTENT-MD5 CONTENT_MD5 HTTP_CONTENT_MD5))
|
51
|
+
value.nil? ? "" : value
|
52
|
+
end
|
53
|
+
|
54
|
+
def request_uri
|
55
|
+
@request.request_uri
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_date
|
59
|
+
@request.env['HTTP_DATE'] = time_as_httpdate
|
60
|
+
end
|
61
|
+
|
62
|
+
def timestamp
|
63
|
+
value = find_header(%w(DATE HTTP_DATE))
|
64
|
+
value.nil? ? "" : value
|
65
|
+
end
|
66
|
+
|
67
|
+
def authorization_header
|
68
|
+
find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def find_header(keys)
|
74
|
+
keys.map {|key| @headers[key] }.compact.first
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
drivers["ActionController::Request"] = ActionControllerRequest
|
80
|
+
drivers["ActionController::CgiRequest"] = ActionControllerRequest
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
module RequestDrivers # :nodoc:
|
4
|
+
|
5
|
+
class ActionDispatchRequest < ActionControllerRequest # :nodoc:
|
6
|
+
|
7
|
+
def request_uri
|
8
|
+
@request.fullpath
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
drivers["ActionDispatch::Request"] = ActionDispatchRequest
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
module ApiAuth
|
3
|
+
module RequestDrivers
|
4
|
+
|
5
|
+
class BixbyRequest
|
6
|
+
|
7
|
+
include ApiAuth::Helpers
|
8
|
+
|
9
|
+
def initialize(request)
|
10
|
+
@request = request
|
11
|
+
@headers = request.headers
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_auth_header(header)
|
16
|
+
@headers["Authorization"] = header
|
17
|
+
@request
|
18
|
+
end
|
19
|
+
|
20
|
+
def calculated_md5
|
21
|
+
Digest::MD5.base64digest(@request.body || '')
|
22
|
+
end
|
23
|
+
|
24
|
+
def populate_content_md5
|
25
|
+
# Should *always* be a POST!
|
26
|
+
@headers["Content-MD5"] = calculated_md5
|
27
|
+
end
|
28
|
+
|
29
|
+
def md5_mismatch?
|
30
|
+
calculated_md5 != content_md5
|
31
|
+
end
|
32
|
+
|
33
|
+
def content_type
|
34
|
+
value = @headers["Content-Type"]
|
35
|
+
value.nil? ? "" : value
|
36
|
+
end
|
37
|
+
|
38
|
+
def content_md5
|
39
|
+
value = @headers["Content-MD5"]
|
40
|
+
value.nil? ? "" : value
|
41
|
+
end
|
42
|
+
|
43
|
+
def request_uri
|
44
|
+
@request.path
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_date
|
48
|
+
@request.headers["Date"] = time_as_httpdate
|
49
|
+
end
|
50
|
+
|
51
|
+
def timestamp
|
52
|
+
value = @headers["Date"]
|
53
|
+
value.nil? ? "" : value
|
54
|
+
end
|
55
|
+
|
56
|
+
def authorization_header
|
57
|
+
@headers["Authorization"]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
drivers["Bixby::SignedJsonRequest"] = BixbyRequest
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
module RequestDrivers # :nodoc:
|
4
|
+
|
5
|
+
class CurbRequest # :nodoc:
|
6
|
+
|
7
|
+
include ApiAuth::Helpers
|
8
|
+
|
9
|
+
def initialize(request)
|
10
|
+
@request = request
|
11
|
+
@headers = fetch_headers
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_auth_header(header)
|
16
|
+
@request.headers.merge!({ "Authorization" => header })
|
17
|
+
@headers = fetch_headers
|
18
|
+
@request
|
19
|
+
end
|
20
|
+
|
21
|
+
def populate_content_md5
|
22
|
+
nil #doesn't appear to be possible
|
23
|
+
end
|
24
|
+
|
25
|
+
def md5_mismatch?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch_headers
|
30
|
+
capitalize_keys @request.headers
|
31
|
+
end
|
32
|
+
|
33
|
+
def content_type
|
34
|
+
value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
|
35
|
+
value.nil? ? "" : value
|
36
|
+
end
|
37
|
+
|
38
|
+
def content_md5
|
39
|
+
value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
|
40
|
+
value.nil? ? "" : value
|
41
|
+
end
|
42
|
+
|
43
|
+
def request_uri
|
44
|
+
@request.url
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_date
|
48
|
+
@request.headers.merge!({ "DATE" => time_as_httpdate })
|
49
|
+
end
|
50
|
+
|
51
|
+
def timestamp
|
52
|
+
value = find_header(%w(DATE HTTP_DATE))
|
53
|
+
value.nil? ? "" : value
|
54
|
+
end
|
55
|
+
|
56
|
+
def authorization_header
|
57
|
+
find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def find_header(keys)
|
63
|
+
keys.map {|key| @headers[key] }.compact.first
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
drivers["Curl::Easy"] = CurbRequest
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
module RequestDrivers # :nodoc:
|
4
|
+
|
5
|
+
class HttpiRequest # :nodoc:
|
6
|
+
|
7
|
+
include ApiAuth::Helpers
|
8
|
+
|
9
|
+
def initialize(request)
|
10
|
+
@request = request
|
11
|
+
@headers = fetch_headers
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_auth_header(header)
|
16
|
+
@request.headers["Authorization"] = header
|
17
|
+
@headers = fetch_headers
|
18
|
+
@request
|
19
|
+
end
|
20
|
+
|
21
|
+
def calculated_md5
|
22
|
+
md5_base64digest(@request.body || '')
|
23
|
+
end
|
24
|
+
|
25
|
+
def populate_content_md5
|
26
|
+
if @request.body
|
27
|
+
@request.headers["Content-MD5"] = calculated_md5
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def md5_mismatch?
|
32
|
+
if @request.body
|
33
|
+
calculated_md5 != content_md5
|
34
|
+
else
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def fetch_headers
|
40
|
+
capitalize_keys @request.headers
|
41
|
+
end
|
42
|
+
|
43
|
+
def content_type
|
44
|
+
value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
|
45
|
+
value.nil? ? "" : value
|
46
|
+
end
|
47
|
+
|
48
|
+
def content_md5
|
49
|
+
value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
|
50
|
+
value.nil? ? "" : value
|
51
|
+
end
|
52
|
+
|
53
|
+
def request_uri
|
54
|
+
@request.url.request_uri
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_date
|
58
|
+
@request.headers["DATE"] = time_as_httpdate
|
59
|
+
end
|
60
|
+
|
61
|
+
def timestamp
|
62
|
+
value = find_header(%w(DATE HTTP_DATE))
|
63
|
+
value.nil? ? "" : value
|
64
|
+
end
|
65
|
+
|
66
|
+
def authorization_header
|
67
|
+
find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def find_header(keys)
|
73
|
+
keys.map {|key| @headers[key] }.compact.first
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
drivers["HTTPI::Request"] = HttpiRequest
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module ApiAuth
|
2
|
+
|
3
|
+
module RequestDrivers # :nodoc:
|
4
|
+
|
5
|
+
class NetHttpRequest # :nodoc:
|
6
|
+
|
7
|
+
include ApiAuth::Helpers
|
8
|
+
|
9
|
+
def initialize(request)
|
10
|
+
@request = request
|
11
|
+
@headers = fetch_headers
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_auth_header(header)
|
16
|
+
@request["Authorization"] = header
|
17
|
+
@headers = fetch_headers
|
18
|
+
@request
|
19
|
+
end
|
20
|
+
|
21
|
+
def calculated_md5
|
22
|
+
if @request.respond_to?(:body_stream) && @request.body_stream
|
23
|
+
body = @request.body_stream.read
|
24
|
+
@request.body_stream.rewind
|
25
|
+
else
|
26
|
+
body = @request.body
|
27
|
+
end
|
28
|
+
|
29
|
+
md5_base64digest(body || '')
|
30
|
+
end
|
31
|
+
|
32
|
+
def populate_content_md5
|
33
|
+
if @request.class::REQUEST_HAS_BODY
|
34
|
+
@request["Content-MD5"] = calculated_md5
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def md5_mismatch?
|
39
|
+
if @request.class::REQUEST_HAS_BODY
|
40
|
+
calculated_md5 != content_md5
|
41
|
+
else
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_headers
|
47
|
+
@request
|
48
|
+
end
|
49
|
+
|
50
|
+
def content_type
|
51
|
+
value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
|
52
|
+
value.nil? ? "" : value
|
53
|
+
end
|
54
|
+
|
55
|
+
def content_md5
|
56
|
+
value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
|
57
|
+
value.nil? ? "" : value
|
58
|
+
end
|
59
|
+
|
60
|
+
def request_uri
|
61
|
+
@request.path
|
62
|
+
end
|
63
|
+
|
64
|
+
def set_date
|
65
|
+
@request["DATE"] = time_as_httpdate
|
66
|
+
end
|
67
|
+
|
68
|
+
def timestamp
|
69
|
+
value = find_header(%w(DATE HTTP_DATE))
|
70
|
+
value.nil? ? "" : value
|
71
|
+
end
|
72
|
+
|
73
|
+
def authorization_header
|
74
|
+
find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def find_header(keys)
|
80
|
+
keys.map {|key| @headers[key] }.compact.first
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
drivers["Net::HTTP"] = NetHttpRequest
|
86
|
+
drivers["Net::HTTP::Put::Multipart"] = NetHttpRequest
|
87
|
+
drivers["Net::HTTP::Post::Multipart"] = NetHttpRequest
|
88
|
+
|
89
|
+
Net::HTTP.constants.each do |c|
|
90
|
+
c = Net::HTTP.const_get(c)
|
91
|
+
if c.kind_of?(Class) && c.ancestors.include?(Net::HTTPRequest) then
|
92
|
+
drivers[c.to_s] = NetHttpRequest
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|