escher 0.3.2 → 0.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d00625f53cdd3b7ad66a39b9cabcea43acb62c0e
4
- data.tar.gz: f7598ab91680f31be25a6e2e37f92f2cfc30a2eb
3
+ metadata.gz: bf5ca3954d669d4c1305dd98027a8b5d4fe37c49
4
+ data.tar.gz: 4a16a2338e1a81efade3a7bd9e01ac5bc888c453
5
5
  SHA512:
6
- metadata.gz: 7ee2cac687e5f94ed8caac6da7218c420f195416084a03ba8753c589df441cd7e24116e3ac089609f78314b3201c98b2ce0a57f397a33582caf2f43b8f1d8a63
7
- data.tar.gz: 0b506771ab44ad8bfc8f871cd61137a1b89e64028e492f27ca8d4275da80f35a5a2702c124dd88080ab131b7c2948199c6fdec9ac7b3d6825fefda7235efd108
6
+ metadata.gz: 7f121d4fc3afed7141855fc060e8a6f04af57f783d823b15a43f61bbad4dbcefc671514938b103d01e2fbbd605853aeb0cdb47a7d78762c2c86b5edf2820f133
7
+ data.tar.gz: 102ca5ed92167b8cfa9ddb9fca6d1cd54e5a6d32006a46e2965185cf575e91ff449012fa7e86be7578600687734adcfc9e6bc210d5ce81b25a409133d0b72c07
data/.travis.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 2.1.2
4
+ - 2.1.2
5
+ - 2.2.1
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Emarsys Technologies Kft.
3
+ Copyright (c) 2014-2015 Emarsys Technologies Kft.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -5,4 +5,4 @@ Escher helps you creating secure HTTP requests (for APIs) by signing HTTP(s) req
5
5
 
6
6
  The algorithm is based on [Amazon's _AWS Signature Version 4_](http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html), but we have generalized and extended it.
7
7
 
8
- More details will be available at our [documentation site](https://documentation.emarsys.com/).
8
+ More details will be available at our [documentation site](http://escherauth.io/).
data/escher.gemspec CHANGED
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.required_ruby_version = '>= 1.9'
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rails"
25
+
24
26
  spec.add_development_dependency "rake", "~> 10"
25
27
  spec.add_development_dependency "rspec", "~> 2"
26
28
 
data/lib/escher/auth.rb CHANGED
@@ -176,12 +176,12 @@ module Escher
176
176
  canonicalized_request = canonicalize(method, path, query_parts, body, headers, signed_headers.uniq)
177
177
  string_to_sign = get_string_to_sign(canonicalized_request)
178
178
 
179
- signing_key = Digest::HMAC.digest(short_date(@current_time), @algo_prefix + api_secret, @algo)
179
+ signing_key = OpenSSL::HMAC.digest(@algo, @algo_prefix + api_secret, short_date(@current_time))
180
180
  @credential_scope.split('/').each { |data|
181
- signing_key = Digest::HMAC.digest(data, signing_key, @algo)
181
+ signing_key = OpenSSL::HMAC.digest(@algo, signing_key, data)
182
182
  }
183
183
 
184
- Digest::HMAC.hexdigest(string_to_sign, signing_key, @algo)
184
+ OpenSSL::HMAC.hexdigest(@algo, signing_key, string_to_sign)
185
185
  end
186
186
 
187
187
 
@@ -236,9 +236,9 @@ module Escher
236
236
  def create_algo
237
237
  case @hash_algo
238
238
  when 'SHA256'
239
- @algo = Digest::SHA2.new(256)
239
+ @algo = OpenSSL::Digest::SHA256.new
240
240
  when 'SHA512'
241
- @algo = Digest::SHA2.new(512)
241
+ @algo = OpenSSL::Digest::SHA521.new
242
242
  else
243
243
  raise EscherError, 'Unidentified hash algorithm'
244
244
  end
@@ -0,0 +1,42 @@
1
+ module Escher
2
+ module Request
3
+ class ActionDispatchRequest < Base
4
+
5
+ def headers
6
+ request.env.
7
+ select { |header_name, _| header_name.start_with? "HTTP_" }.
8
+ map { |header_name, value| [header_name[5..-1].tr('_', '-'), value] }
9
+ end
10
+
11
+
12
+
13
+ def method
14
+ request.request_method
15
+ end
16
+
17
+
18
+
19
+ def body
20
+ request.body or ''
21
+ end
22
+
23
+
24
+
25
+ def path
26
+ request.env['REQUEST_PATH']
27
+ end
28
+
29
+
30
+
31
+ def query_values
32
+ Addressable::URI.new(:query => request.env['QUERY_STRING']).query_values(Array) or []
33
+ end
34
+
35
+
36
+
37
+ def set_header(header_name, value)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -24,6 +24,39 @@ module Escher
24
24
  header[1]
25
25
  end
26
26
 
27
+
28
+
29
+ def method
30
+ raise("Implementation missing for #{__method__}")
31
+ end
32
+
33
+
34
+
35
+ def body
36
+ raise("Implementation missing for #{__method__}")
37
+ end
38
+
39
+
40
+
41
+ def headers
42
+ raise('Implementation missing, should return array of array with [key,value] pairs')
43
+ end
44
+
45
+
46
+
47
+ def path
48
+ raise("Implementation missing for #{__method__}")
49
+ end
50
+
51
+
52
+
53
+ def query_values
54
+ raise("Implementation missing for #{__method__}")
55
+ end
56
+
57
+
58
+
59
+
27
60
  end
28
61
  end
29
62
  end
@@ -1,8 +1,8 @@
1
- require_relative 'base'
2
-
3
- require_relative 'hash_request'
4
- require_relative 'legacy_request'
5
- require_relative 'rack_request'
1
+ require 'escher/request/base'
2
+ require 'escher/request/hash_request'
3
+ require 'escher/request/rack_request'
4
+ require 'escher/request/legacy_request'
5
+ require 'escher/request/action_dispatch_request'
6
6
 
7
7
  module Escher
8
8
  module Request
@@ -10,12 +10,19 @@ module Escher
10
10
 
11
11
  def self.from_request(request)
12
12
  case request
13
+
14
+ when defined?(ActionDispatch::Request) && ActionDispatch::Request
15
+ ActionDispatchRequest.new(request)
16
+
17
+ when defined?(Rack::Request) && Rack::Request
18
+ RackRequest.new(request)
19
+
13
20
  when Hash
14
- HashRequest.new request
15
- when lambda { |request| request.class.ancestors.map(&:to_s).include? "Rack::Request" }
16
- RackRequest.new request
21
+ HashRequest.new(request)
22
+
17
23
  else
18
- Escher::Request::LegacyRequest.new request
24
+ Escher::Request::LegacyRequest.new(request)
25
+
19
26
  end
20
27
  end
21
28
 
@@ -1,42 +1,62 @@
1
- module Escher
2
- module Request
3
- class RackRequest < Base
1
+ class Escher::Request::RackRequest < Escher::Request::Base
4
2
 
5
- def headers
6
- request.env.
7
- select { |header_name, _| header_name.start_with? "HTTP_" }.
8
- map { |header_name, value| [header_name[5..-1].tr('_', '-'), value] }
9
- end
3
+ def initialize(request_env)
4
+ super(request_env)
5
+ @rack_request = request_env
6
+ end
10
7
 
8
+ def env
9
+ @rack_request.env
10
+ end
11
11
 
12
+ def rack_request
13
+ @rack_request
14
+ end
12
15
 
13
- def method
14
- request.request_method
15
- end
16
+ def uri
17
+ @rack_request.env['REQUEST_URI']
18
+ end
16
19
 
20
+ def path
21
+ @rack_request.env['REQUEST_PATH']
22
+ end
17
23
 
24
+ def host
25
+ @rack_request.env['HTTP_HOST']
26
+ end
18
27
 
19
- def body
20
- request.body or ''
21
- end
28
+ def headers
29
+ @headers ||= @rack_request.env.select { |k, v| k =~ /^HTTP_/i }.map { |k, v| [k.sub(/^HTTP_/i, '').gsub('_', '-'), v] }
30
+ end
22
31
 
32
+ def method
33
+ @rack_request.request_method rescue @rack_request.env['REQUEST_METHOD']
34
+ end
23
35
 
36
+ def payload
37
+ @payload ||= fetch_payload
38
+ end
24
39
 
25
- def path
26
- request.env['REQUEST_PATH']
27
- end
40
+ alias body payload
28
41
 
42
+ def query_values
43
+ Addressable::URI.new(:query => request.env['QUERY_STRING']).query_values(Array) or []
44
+ end
29
45
 
46
+ def set_header(header_name, value)
47
+ end
30
48
 
31
- def query_values
32
- Addressable::URI.new(:query => request.env['QUERY_STRING']).query_values(Array) or []
33
- end
49
+ protected
34
50
 
51
+ def fetch_payload
52
+ rack_input = @rack_request.body
35
53
 
54
+ return rack_input.to_s if rack_input.nil? || rack_input.is_a?(String)
36
55
 
37
- def set_header(header_name, value)
38
- end
56
+ payload = rack_input.read
57
+ @rack_request.body.rewind
58
+ payload
39
59
 
40
- end
41
60
  end
42
- end
61
+
62
+ end
@@ -1,3 +1,3 @@
1
1
  module Escher
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
data/lib/escher.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'addressable/uri'
2
2
  require 'time'
3
- require 'digest'
3
+ require 'openssl'
4
4
 
5
5
  require 'escher/version'
6
6
  require 'escher/request/factory'
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ require 'action_dispatch'
4
+
5
+ describe Escher::Request::ActionDispatchRequest do
6
+
7
+ let(:request_params) { {"PATH_INFO" => "/", } }
8
+ let(:request) { ActionDispatch::Request.new(request_params) }
9
+
10
+ subject { described_class.new request }
11
+
12
+ describe "#request" do
13
+ it "should return the underlying request object" do
14
+ expect(subject.request).to eq request
15
+ end
16
+ end
17
+
18
+
19
+ describe "#headers" do
20
+ it "should return only the HTTP request headers" do
21
+ request_params.merge! 'HTTP_HOST' => 'some host',
22
+ 'SOME_HEADER' => 'some header'
23
+
24
+ expect(subject.headers).to eq [['HOST', 'some host']]
25
+ end
26
+
27
+ it "should replace underscores with dashes in the header name" do
28
+ request_params.merge! 'HTTP_HOST_NAME' => 'some host'
29
+
30
+ expect(subject.headers).to eq [['HOST-NAME', 'some host']]
31
+ end
32
+ end
33
+
34
+
35
+ describe "#has_header?" do
36
+ it "should return true if request has specified header, false otherwise" do
37
+ request_params.merge! 'HTTP_HOST_NAME' => 'some host'
38
+
39
+ expect(subject.has_header? 'host-name').to be_truthy
40
+ expect(subject.has_header? 'no-such-header').to be_falsey
41
+ end
42
+ end
43
+
44
+
45
+ describe "#header" do
46
+ it "should return the value for the requested header" do
47
+ request_params.merge! 'HTTP_HOST' => 'some host'
48
+
49
+ expect(subject.header 'host').to eq 'some host'
50
+ end
51
+
52
+ it "should return nil if no such header exists" do
53
+ expect(subject.header 'host').to be_nil
54
+ end
55
+ end
56
+
57
+
58
+ describe "#method" do
59
+ it "should return the request method" do
60
+ request_params.merge! 'REQUEST_METHOD' => 'GET'
61
+
62
+ expect(subject.method).to eq 'GET'
63
+ end
64
+ end
65
+
66
+
67
+ describe "#body" do
68
+ it "should return the request body" do
69
+ request_params.merge! 'rack.input' => 'request body'
70
+
71
+ expect(subject.body).to eq 'request body'
72
+ end
73
+
74
+ it "should return empty string for no body" do
75
+ expect(subject.body).to eq ''
76
+ end
77
+ end
78
+
79
+
80
+ describe "#path" do
81
+ it "should return the request path" do
82
+ request_params.merge! 'REQUEST_PATH' => '/resources/id///'
83
+
84
+ expect(subject.path).to eq '/resources/id///'
85
+ end
86
+ end
87
+
88
+
89
+ describe "#query_values" do
90
+ it "should return the request query parameters as an array of key-value pairs" do
91
+ request_params.merge! 'QUERY_STRING' => 'search=query&param=value'
92
+
93
+ expect(subject.query_values).to eq [['search', 'query'], ['param', 'value']]
94
+ end
95
+
96
+ it "should return the query parameters regardless of fragments" do
97
+ request_params.merge! 'QUERY_STRING' => "@\#$%^&+=/,?><`\";:\\|][{}"
98
+
99
+ expect(subject.query_values).to eq [["@\#$%^"], ["+", "/,?><`\";:\\|][{}"]]
100
+ end
101
+
102
+ it "should return an empty array if the request has no query parameters" do
103
+ expect(subject.query_values).to eq []
104
+ end
105
+ end
106
+
107
+
108
+ describe "#set_header" do
109
+ it "should ignore calls" do
110
+ expect { subject.set_header 'test-header', 'test value' }.not_to raise_error
111
+ end
112
+ end
113
+
114
+ end
@@ -1,12 +1,20 @@
1
1
  require 'spec_helper'
2
+
3
+ require 'rack'
2
4
  require 'rack/request'
5
+ require 'action_dispatch'
3
6
 
4
7
  describe Escher::Request::Factory do
5
8
 
6
9
  describe ".from_request" do
7
- {{uri: "request uri"} => Escher::Request::HashRequest,
8
- Struct.new(:uri) => Escher::Request::LegacyRequest,
9
- Rack::Request.new({}) => Escher::Request::RackRequest}.each do |request, expected_class|
10
+ {
11
+
12
+ {uri: "request uri"} => Escher::Request::HashRequest,
13
+ Struct.new(:uri) => Escher::Request::LegacyRequest,
14
+ Rack::Request.new({}) => Escher::Request::RackRequest,
15
+ ActionDispatch::Request.new({}) => Escher::Request::ActionDispatchRequest
16
+
17
+ }.each do |request, expected_class|
10
18
 
11
19
  it "should return a #{expected_class.name} when the request to be wrapped is a #{request.class.name}" do
12
20
  expect(expected_class).to receive(:new).with(request).and_return "#{expected_class.name} wrapping request"
@@ -1,4 +1,6 @@
1
1
  require 'spec_helper'
2
+
3
+ require 'rack'
2
4
  require 'rack/request'
3
5
 
4
6
  describe Escher::Request::RackRequest do
data/spec/spec_helper.rb CHANGED
@@ -1 +1,3 @@
1
- require 'escher'
1
+ lib = File.expand_path('../../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'escher'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: escher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andras Barthazi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-10 00:00:00.000000000 Z
11
+ date: 2015-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -97,6 +111,7 @@ files:
97
111
  - escher.gemspec
98
112
  - lib/escher.rb
99
113
  - lib/escher/auth.rb
114
+ - lib/escher/request/action_dispatch_request.rb
100
115
  - lib/escher/request/base.rb
101
116
  - lib/escher/request/factory.rb
102
117
  - lib/escher/request/hash_request.rb
@@ -280,6 +295,7 @@ files:
280
295
  - spec/emarsys_testsuite/post-header-value-spaces.sreq
281
296
  - spec/emarsys_testsuite/post-header-value-spaces.sts
282
297
  - spec/escher/auth_spec.rb
298
+ - spec/escher/request/action_dispatch_request_spec.rb
283
299
  - spec/escher/request/factory_spec.rb
284
300
  - spec/escher/request/hash_request_spec.rb
285
301
  - spec/escher/request/rack_request_spec.rb
@@ -486,6 +502,7 @@ test_files:
486
502
  - spec/emarsys_testsuite/post-header-value-spaces.sreq
487
503
  - spec/emarsys_testsuite/post-header-value-spaces.sts
488
504
  - spec/escher/auth_spec.rb
505
+ - spec/escher/request/action_dispatch_request_spec.rb
489
506
  - spec/escher/request/factory_spec.rb
490
507
  - spec/escher/request/hash_request_spec.rb
491
508
  - spec/escher/request/rack_request_spec.rb