escher 0.4.3 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +33 -0
- data/escher.gemspec +4 -4
- data/lib/escher/auth.rb +24 -21
- data/lib/escher/request/factory.rb +1 -1
- data/lib/escher/request.rb +0 -1
- data/lib/escher/version.rb +1 -1
- data/repo-info.json +7 -0
- data/spec/emarsys_test_suite_spec.rb +0 -6
- data/spec/escher/auth_spec.rb +2 -2
- data/spec/escher/request/factory_spec.rb +19 -7
- metadata +13 -16
- data/.travis.yml +0 -5
- data/lib/escher/request/action_dispatch_request.rb +0 -47
- data/spec/escher/request/action_dispatch_request_spec.rb +0 -120
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b18ad0e7492749391a2d41baab5ba09033def7a7c1399ce8f9725cd9786eab98
|
4
|
+
data.tar.gz: 6ac12253dbf9cab09ffb66b60539edb33f0648ebc0c0b4c9c2b746157236f9af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1d465e795dab3645b727748ff4a2b0f00e448a214986c0c36c5abc9671d64f5aec2c7ad7275f38a8cca7729ca01a38fde3421697be5d2c91bfbc55365777e05
|
7
|
+
data.tar.gz: 5601a61b35a0700c80bbab5a42cc2e524643ae7aced341ad7073d17cb3cb51f3f333b811326aa519c19bee6f91bda7550881dfda53a84ee3689fddc41b694146
|
@@ -0,0 +1,33 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
ruby-versions: ['2.6', '2.7', '3.0']
|
11
|
+
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v2
|
14
|
+
- uses: ruby/setup-ruby@v1
|
15
|
+
with:
|
16
|
+
ruby-version: ${{ matrix.ruby-versions }}
|
17
|
+
- name: Checkout testsuite
|
18
|
+
run: ./scripts/checkout_test_suite.sh
|
19
|
+
- name: Install dependencies
|
20
|
+
run: bundle install
|
21
|
+
- name: Run tests
|
22
|
+
run: bundle exec rake
|
23
|
+
- name: Deploy
|
24
|
+
if : github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
25
|
+
run: |
|
26
|
+
mkdir -p $HOME/.gem
|
27
|
+
touch $HOME/.gem/credentials
|
28
|
+
chmod 0600 $HOME/.gem/credentials
|
29
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
30
|
+
gem build *.gemspec
|
31
|
+
gem push *.gem
|
32
|
+
env:
|
33
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
data/escher.gemspec
CHANGED
@@ -20,14 +20,14 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.required_ruby_version = '>= 1.9'
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler", "~>
|
23
|
+
spec.add_development_dependency "bundler", "~> 2.2.20"
|
24
24
|
spec.add_development_dependency "rails"
|
25
25
|
|
26
|
-
spec.add_development_dependency "rake", "~>
|
27
|
-
spec.add_development_dependency "rspec", "~>
|
26
|
+
spec.add_development_dependency "rake", "~> 13.0.6"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3"
|
28
28
|
|
29
29
|
spec.add_development_dependency "rack"
|
30
30
|
spec.add_development_dependency "plissken"
|
31
31
|
|
32
|
-
spec.add_runtime_dependency "addressable", "~> 2.
|
32
|
+
spec.add_runtime_dependency "addressable", "~> 2.8.0"
|
33
33
|
end
|
data/lib/escher/auth.rb
CHANGED
@@ -6,7 +6,7 @@ module Escher
|
|
6
6
|
@algo_prefix = options[:algo_prefix] || 'ESR'
|
7
7
|
@vendor_key = options[:vendor_key] || 'Escher'
|
8
8
|
@hash_algo = options[:hash_algo] || 'SHA256'
|
9
|
-
@current_time = options[:current_time]
|
9
|
+
@current_time = options[:current_time]
|
10
10
|
@auth_header_name = options[:auth_header_name] || 'X-Escher-Auth'
|
11
11
|
@date_header_name = options[:date_header_name] || 'X-Escher-Date'
|
12
12
|
@clock_skew = options[:clock_skew] || 300
|
@@ -17,15 +17,17 @@ module Escher
|
|
17
17
|
|
18
18
|
|
19
19
|
def sign!(req, client, headers_to_sign = [])
|
20
|
+
current_time = @current_time || Time.now
|
21
|
+
|
20
22
|
headers_to_sign |= [@date_header_name.downcase, 'host']
|
21
23
|
|
22
24
|
request = wrap_request req
|
23
25
|
raise EscherError, 'The host header is missing' unless request.has_header? 'host'
|
24
26
|
|
25
|
-
request.set_header(@date_header_name.downcase, format_date_for_header) unless request.has_header? @date_header_name
|
27
|
+
request.set_header(@date_header_name.downcase, format_date_for_header(current_time)) unless request.has_header? @date_header_name
|
26
28
|
|
27
|
-
signature = generate_signature(client[:api_secret], request.body, request.headers, request.method, headers_to_sign, request.path, request.query_values)
|
28
|
-
request.set_header(@auth_header_name, "#{@algo_id} Credential=#{client[:api_key_id]}/#{short_date(
|
29
|
+
signature = generate_signature(client[:api_secret], request.body, request.headers, request.method, headers_to_sign, request.path, request.query_values, current_time)
|
30
|
+
request.set_header(@auth_header_name, "#{@algo_id} Credential=#{client[:api_key_id]}/#{short_date(current_time)}/#{@credential_scope}, SignedHeaders=#{prepare_headers_to_sign headers_to_sign}, Signature=#{signature}")
|
29
31
|
|
30
32
|
request.request
|
31
33
|
end
|
@@ -44,6 +46,7 @@ module Escher
|
|
44
46
|
|
45
47
|
|
46
48
|
def authenticate(req, key_db, mandatory_signed_headers = nil)
|
49
|
+
current_time = @current_time || Time.now
|
47
50
|
request = wrap_request req
|
48
51
|
method = request.method
|
49
52
|
body = request.body
|
@@ -78,10 +81,9 @@ module Escher
|
|
78
81
|
raise EscherError, 'Invalid Escher key' unless api_secret
|
79
82
|
raise EscherError, 'Invalid hash algorithm, only SHA256 and SHA512 are allowed' unless %w(SHA256 SHA512).include?(algorithm)
|
80
83
|
raise EscherError, 'The request method is invalid' unless valid_request_method?(method)
|
81
|
-
raise EscherError, "The request body shouldn't be empty if the request method is POST" if (method.upcase == 'POST' && body.empty?)
|
82
84
|
raise EscherError, "The request url shouldn't contains http or https" if path.match /^https?:\/\//
|
83
85
|
raise EscherError, 'Invalid date in authorization header, it should equal with date header' unless short_date(date) == short_date
|
84
|
-
raise EscherError, 'The request date is not within the accepted time range' unless is_date_within_range?(date, expires)
|
86
|
+
raise EscherError, 'The request date is not within the accepted time range' unless is_date_within_range?(date, expires, current_time)
|
85
87
|
raise EscherError, 'Invalid Credential Scope' unless credential_scope == @credential_scope
|
86
88
|
raise EscherError, 'The mandatorySignedHeaders parameter must be undefined or array of strings' unless mandatory_signed_headers_valid?(mandatory_signed_headers)
|
87
89
|
raise EscherError, 'The host header is not signed' unless signed_headers.include? 'host'
|
@@ -94,7 +96,7 @@ module Escher
|
|
94
96
|
raise EscherError, 'The date header is not signed' if !signature_from_query && !signed_headers.include?(@date_header_name.downcase)
|
95
97
|
|
96
98
|
escher = reconfig(algorithm, credential_scope, date)
|
97
|
-
expected_signature = escher.generate_signature(api_secret, body, headers, method, signed_headers, path, query_parts)
|
99
|
+
expected_signature = escher.generate_signature(api_secret, body, headers, method, signed_headers, path, query_parts, date)
|
98
100
|
raise EscherError, 'The signatures do not match' unless signature == expected_signature
|
99
101
|
api_key_id
|
100
102
|
end
|
@@ -116,6 +118,7 @@ module Escher
|
|
116
118
|
|
117
119
|
|
118
120
|
def generate_signed_url(url_to_sign, client, expires = 86400)
|
121
|
+
current_time = @current_time || Time.now
|
119
122
|
uri = Addressable::URI.parse(url_to_sign)
|
120
123
|
|
121
124
|
if (not uri.port.nil?) && (uri.port != uri.default_port)
|
@@ -137,13 +140,13 @@ module Escher
|
|
137
140
|
body = 'UNSIGNED-PAYLOAD'
|
138
141
|
query_parts += [
|
139
142
|
['Algorithm', @algo_id],
|
140
|
-
['Credentials', "#{client[:api_key_id]}/#{short_date(
|
141
|
-
['Date', long_date(
|
143
|
+
['Credentials', "#{client[:api_key_id]}/#{short_date(current_time)}/#{@credential_scope}"],
|
144
|
+
['Date', long_date(current_time)],
|
142
145
|
['Expires', expires.to_s],
|
143
146
|
['SignedHeaders', headers_to_sign.join(';')],
|
144
147
|
].map { |k, v| query_pair(k, v) }
|
145
148
|
|
146
|
-
signature = generate_signature(client[:api_secret], body, headers, 'GET', headers_to_sign, path, query_parts)
|
149
|
+
signature = generate_signature(client[:api_secret], body, headers, 'GET', headers_to_sign, path, query_parts, current_time)
|
147
150
|
query_parts_with_signature = (query_parts.map { |k, v| [uri_encode(k), uri_encode(v)] } << query_pair('Signature', signature))
|
148
151
|
"#{uri.scheme}://#{host}#{path}?#{query_parts_with_signature.map { |k, v| k + '=' + v }.join('&')}#{(fragment === nil ? '' : '#' + fragment)}"
|
149
152
|
end
|
@@ -189,11 +192,11 @@ module Escher
|
|
189
192
|
|
190
193
|
|
191
194
|
|
192
|
-
def generate_signature(api_secret, body, headers, method, signed_headers, path, query_parts)
|
195
|
+
def generate_signature(api_secret, body, headers, method, signed_headers, path, query_parts, current_time)
|
193
196
|
canonicalized_request = canonicalize(method, path, query_parts, body, headers, signed_headers.uniq)
|
194
|
-
string_to_sign = get_string_to_sign(canonicalized_request)
|
197
|
+
string_to_sign = get_string_to_sign(canonicalized_request, current_time)
|
195
198
|
|
196
|
-
signing_key = OpenSSL::HMAC.digest(@algo, @algo_prefix + api_secret, short_date(
|
199
|
+
signing_key = OpenSSL::HMAC.digest(@algo, @algo_prefix + api_secret, short_date(current_time))
|
197
200
|
@credential_scope.split('/').each { |data|
|
198
201
|
signing_key = OpenSSL::HMAC.digest(@algo, signing_key, data)
|
199
202
|
}
|
@@ -203,8 +206,8 @@ module Escher
|
|
203
206
|
|
204
207
|
|
205
208
|
|
206
|
-
def format_date_for_header
|
207
|
-
@date_header_name.downcase == 'date' ?
|
209
|
+
def format_date_for_header(current_time)
|
210
|
+
@date_header_name.downcase == 'date' ? current_time.utc.rfc2822.sub('-0000', 'GMT') : long_date(current_time)
|
208
211
|
end
|
209
212
|
|
210
213
|
|
@@ -239,11 +242,11 @@ module Escher
|
|
239
242
|
|
240
243
|
|
241
244
|
|
242
|
-
def get_string_to_sign(canonicalized_request)
|
245
|
+
def get_string_to_sign(canonicalized_request, current_time)
|
243
246
|
[
|
244
247
|
@algo_id,
|
245
|
-
long_date(
|
246
|
-
short_date(
|
248
|
+
long_date(current_time),
|
249
|
+
short_date(current_time) + '/' + @credential_scope,
|
247
250
|
@algo.new.hexdigest(canonicalized_request)
|
248
251
|
].join("\n")
|
249
252
|
end
|
@@ -255,7 +258,7 @@ module Escher
|
|
255
258
|
when 'SHA256'
|
256
259
|
@algo = OpenSSL::Digest::SHA256.new
|
257
260
|
when 'SHA512'
|
258
|
-
@algo = OpenSSL::Digest::
|
261
|
+
@algo = OpenSSL::Digest::SHA512.new
|
259
262
|
else
|
260
263
|
raise EscherError, 'Unidentified hash algorithm'
|
261
264
|
end
|
@@ -275,8 +278,8 @@ module Escher
|
|
275
278
|
|
276
279
|
|
277
280
|
|
278
|
-
def is_date_within_range?(request_date, expires)
|
279
|
-
(request_date - @clock_skew .. request_date + expires + @clock_skew).cover?
|
281
|
+
def is_date_within_range?(request_date, expires, current_time)
|
282
|
+
(request_date - @clock_skew .. request_date + expires + @clock_skew).cover? current_time
|
280
283
|
end
|
281
284
|
|
282
285
|
|
@@ -6,7 +6,7 @@ module Escher
|
|
6
6
|
case request
|
7
7
|
|
8
8
|
when defined?(ActionDispatch::Request) && ActionDispatch::Request
|
9
|
-
|
9
|
+
RackRequest.new(Rack::Request.new(request.env))
|
10
10
|
|
11
11
|
when defined?(Rack::Request) && Rack::Request
|
12
12
|
RackRequest.new(request)
|
data/lib/escher/request.rb
CHANGED
data/lib/escher/version.rb
CHANGED
data/repo-info.json
ADDED
@@ -35,11 +35,5 @@ module Escher
|
|
35
35
|
expect(request).to eq(test_case.expected_request)
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
|
40
|
-
xspecify "every case in the test suite is being used" do
|
41
|
-
expect(::EmarsysTestSuiteHelpers::TestSuite.in_use_size).to eq ::EmarsysTestSuiteHelpers::TestSuite.size
|
42
|
-
end
|
43
|
-
|
44
38
|
end
|
45
39
|
end
|
data/spec/escher/auth_spec.rb
CHANGED
@@ -101,7 +101,7 @@ module Escher
|
|
101
101
|
headers_to_sign = headers.map { |k| k[0].downcase }
|
102
102
|
path, query_parts = escher.parse_uri(request_uri)
|
103
103
|
canonicalized_request = escher.canonicalize(method, path, query_parts, body, headers, headers_to_sign)
|
104
|
-
string_to_sign = escher.get_string_to_sign(canonicalized_request)
|
104
|
+
string_to_sign = escher.get_string_to_sign(canonicalized_request, Time.parse(date))
|
105
105
|
expect(string_to_sign).to eq(fixture(suite, test, 'sts'))
|
106
106
|
end
|
107
107
|
end
|
@@ -484,7 +484,7 @@ module Escher
|
|
484
484
|
|
485
485
|
it 'should convert dates' do
|
486
486
|
date_str = 'Fri, 09 Sep 2011 23:36:00 GMT'
|
487
|
-
expect(described_class.new('irrelevant', date_header_name: 'date', current_time: Time.parse(date_str)).format_date_for_header).to eq date_str
|
487
|
+
expect(described_class.new('irrelevant', date_header_name: 'date', current_time: Time.parse(date_str)).format_date_for_header(Time.parse(date_str))).to eq date_str
|
488
488
|
end
|
489
489
|
|
490
490
|
|
@@ -7,19 +7,31 @@ require 'action_dispatch'
|
|
7
7
|
describe Escher::Request::Factory do
|
8
8
|
|
9
9
|
describe ".from_request" do
|
10
|
+
request_env = {Rack::PATH_INFO.to_s => "request-path"}
|
11
|
+
|
10
12
|
{
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
{uri: "request-path"} => Escher::Request::HashRequest,
|
15
|
+
Struct.new("Request", :uri).new("request-path") => Escher::Request::LegacyRequest,
|
16
|
+
Rack::Request.new(request_env) => Escher::Request::RackRequest,
|
17
|
+
ActionDispatch::Request.new(request_env) => Escher::Request::RackRequest
|
16
18
|
|
17
19
|
}.each do |request, expected_class|
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
context "the request to be wrapped is a #{request.class.name}" do
|
22
|
+
|
23
|
+
it "returns a #{expected_class.name}" do
|
24
|
+
wrapped_request = described_class.from_request request
|
25
|
+
|
26
|
+
expect(wrapped_request).to be_an_instance_of expected_class
|
27
|
+
end
|
28
|
+
|
29
|
+
it "wraps the path from the original request" do
|
30
|
+
wrapped_request = described_class.from_request request
|
31
|
+
|
32
|
+
expect(wrapped_request.path).to eq "request-path"
|
33
|
+
end
|
21
34
|
|
22
|
-
expect(described_class.from_request request).to eq "#{expected_class.name} wrapping request"
|
23
35
|
end
|
24
36
|
|
25
37
|
end
|
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.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andras Barthazi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.20
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.20
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,28 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 13.0.6
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 13.0.6
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '3'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '3'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rack
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: 2.8.0
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 2.8.0
|
111
111
|
description: Escher helps you creating secure HTTP requests (for APIs) by signing
|
112
112
|
HTTP(s) requests.
|
113
113
|
email:
|
@@ -116,8 +116,8 @@ executables: []
|
|
116
116
|
extensions: []
|
117
117
|
extra_rdoc_files: []
|
118
118
|
files:
|
119
|
+
- ".github/workflows/ruby.yml"
|
119
120
|
- ".gitignore"
|
120
|
-
- ".travis.yml"
|
121
121
|
- Gemfile
|
122
122
|
- LICENSE
|
123
123
|
- README.md
|
@@ -127,7 +127,6 @@ files:
|
|
127
127
|
- lib/escher/auth.rb
|
128
128
|
- lib/escher/escher_error.rb
|
129
129
|
- lib/escher/request.rb
|
130
|
-
- lib/escher/request/action_dispatch_request.rb
|
131
130
|
- lib/escher/request/base.rb
|
132
131
|
- lib/escher/request/dci.rb
|
133
132
|
- lib/escher/request/dci/rack_env.rb
|
@@ -136,6 +135,7 @@ files:
|
|
136
135
|
- lib/escher/request/legacy_request.rb
|
137
136
|
- lib/escher/request/rack_request.rb
|
138
137
|
- lib/escher/version.rb
|
138
|
+
- repo-info.json
|
139
139
|
- scripts/checkout_test_suite.sh
|
140
140
|
- spec/aws4_testsuite/get-header-key-duplicate.authz
|
141
141
|
- spec/aws4_testsuite/get-header-key-duplicate.creq
|
@@ -315,7 +315,6 @@ files:
|
|
315
315
|
- spec/emarsys_testsuite/post-header-value-spaces.sreq
|
316
316
|
- spec/emarsys_testsuite/post-header-value-spaces.sts
|
317
317
|
- spec/escher/auth_spec.rb
|
318
|
-
- spec/escher/request/action_dispatch_request_spec.rb
|
319
318
|
- spec/escher/request/factory_spec.rb
|
320
319
|
- spec/escher/request/hash_request_spec.rb
|
321
320
|
- spec/escher/request/rack_request_spec.rb
|
@@ -342,8 +341,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
342
341
|
- !ruby/object:Gem::Version
|
343
342
|
version: '0'
|
344
343
|
requirements: []
|
345
|
-
|
346
|
-
rubygems_version: 2.5.1
|
344
|
+
rubygems_version: 3.2.22
|
347
345
|
signing_key:
|
348
346
|
specification_version: 4
|
349
347
|
summary: Library for HTTP request signing (Ruby implementation)
|
@@ -526,7 +524,6 @@ test_files:
|
|
526
524
|
- spec/emarsys_testsuite/post-header-value-spaces.sreq
|
527
525
|
- spec/emarsys_testsuite/post-header-value-spaces.sts
|
528
526
|
- spec/escher/auth_spec.rb
|
529
|
-
- spec/escher/request/action_dispatch_request_spec.rb
|
530
527
|
- spec/escher/request/factory_spec.rb
|
531
528
|
- spec/escher/request/hash_request_spec.rb
|
532
529
|
- spec/escher/request/rack_request_spec.rb
|
data/.travis.yml
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Escher
|
2
|
-
module Request
|
3
|
-
class ActionDispatchRequest < Base
|
4
|
-
|
5
|
-
include Escher::Request::DCI::RackEnv
|
6
|
-
|
7
|
-
def headers
|
8
|
-
get_headers_by_rack_env(request.env)
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def method
|
14
|
-
request.request_method
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def body
|
20
|
-
case request.body
|
21
|
-
when StringIO
|
22
|
-
request.body.string
|
23
|
-
else
|
24
|
-
request.body.to_s
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def path
|
31
|
-
request.env['REQUEST_PATH'] || request.path
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def query_values
|
37
|
-
Addressable::URI.new(:query => request.env['QUERY_STRING']).query_values(Array) or []
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def set_header(header_name, value)
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,120 +0,0 @@
|
|
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
|
-
|
33
|
-
it 'should add the content-type and content-length to the headers' do
|
34
|
-
request_params.merge!( 'CONTENT_LENGTH' => '123', 'CONTENT_TYPE' => 'text/plain' )
|
35
|
-
|
36
|
-
expect(subject.headers).to eq [%w(CONTENT-LENGTH 123), %w(CONTENT-TYPE text/plain)]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
describe "#has_header?" do
|
42
|
-
it "should return true if request has specified header, false otherwise" do
|
43
|
-
request_params.merge! 'HTTP_HOST_NAME' => 'some host'
|
44
|
-
|
45
|
-
expect(subject.has_header? 'host-name').to be_truthy
|
46
|
-
expect(subject.has_header? 'no-such-header').to be_falsey
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
describe "#header" do
|
52
|
-
it "should return the value for the requested header" do
|
53
|
-
request_params.merge! 'HTTP_HOST' => 'some host'
|
54
|
-
|
55
|
-
expect(subject.header 'host').to eq 'some host'
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should return nil if no such header exists" do
|
59
|
-
expect(subject.header 'host').to be_nil
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
describe "#method" do
|
65
|
-
it "should return the request method" do
|
66
|
-
request_params.merge! 'REQUEST_METHOD' => 'GET'
|
67
|
-
|
68
|
-
expect(subject.method).to eq 'GET'
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
|
73
|
-
describe "#body" do
|
74
|
-
it "should return the request body" do
|
75
|
-
request_params.merge! 'rack.input' => 'request body'
|
76
|
-
|
77
|
-
expect(subject.body).to eq 'request body'
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should return empty string for no body" do
|
81
|
-
expect(subject.body).to eq ''
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
|
86
|
-
describe "#path" do
|
87
|
-
it "should return the request path" do
|
88
|
-
request_params.merge! 'REQUEST_PATH' => '/resources/id///'
|
89
|
-
|
90
|
-
expect(subject.path).to eq '/resources/id///'
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
|
95
|
-
describe "#query_values" do
|
96
|
-
it "should return the request query parameters as an array of key-value pairs" do
|
97
|
-
request_params.merge! 'QUERY_STRING' => 'search=query¶m=value'
|
98
|
-
|
99
|
-
expect(subject.query_values).to eq [['search', 'query'], ['param', 'value']]
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should return the query parameters regardless of fragments" do
|
103
|
-
request_params.merge! 'QUERY_STRING' => "@\#$%^&+=/,?><`\";:\\|][{}"
|
104
|
-
|
105
|
-
expect(subject.query_values).to eq [["@\#$%^"], ["+", "/,?><`\";:\\|][{}"]]
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should return an empty array if the request has no query parameters" do
|
109
|
-
expect(subject.query_values).to eq []
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
|
114
|
-
describe "#set_header" do
|
115
|
-
it "should ignore calls" do
|
116
|
-
expect { subject.set_header 'test-header', 'test value' }.not_to raise_error
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
end
|