apill 1.6.0 → 2.0.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 +4 -4
- data/lib/apill/configuration.rb +24 -0
- data/lib/apill/errors/invalid_subdomain_error.rb +26 -0
- data/lib/apill/matchers/accept_header_matcher.rb +0 -1
- data/lib/apill/matchers/generic_matcher.rb +11 -8
- data/lib/apill/matchers/subdomain_matcher.rb +6 -4
- data/lib/apill/matchers/version_matcher.rb +1 -5
- data/lib/apill/middleware/api_request.rb +32 -0
- data/lib/apill/responses/invalid_subdomain_response.rb +17 -0
- data/lib/apill/version.rb +1 -1
- data/spec/{lib/apill → apill}/accept_header_spec.rb +0 -0
- data/spec/{lib/apill → apill}/errors/invalid_api_request_error_spec.rb +0 -0
- data/spec/apill/errors/invalid_subdomain_error_spec.rb +39 -0
- data/spec/apill/invalid_subdomain_response_spec.rb +45 -0
- data/spec/apill/matchers/accept_header_matcher_spec.rb +103 -0
- data/spec/apill/matchers/invalid_api_request_matcher_spec.rb +21 -0
- data/spec/apill/matchers/subdomain_matcher_spec.rb +46 -0
- data/spec/apill/matchers/version_matcher_spec.rb +66 -0
- data/spec/apill/middleware/api_request_spec.rb +114 -0
- metadata +48 -26
- data/spec/lib/apill/matchers/accept_header_matcher_spec.rb +0 -92
- data/spec/lib/apill/matchers/invalid_api_request_matcher_spec.rb +0 -19
- data/spec/lib/apill/matchers/subdomain_matcher_spec.rb +0 -41
- data/spec/lib/apill/matchers/version_matcher_spec.rb +0 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 974dc18ca764506d1a544244dfb65b70ce344ec7
|
4
|
+
data.tar.gz: a74c5b8c216e451a7d25015e623363b2b0348b2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e248544358f6cf0a0559504b360ca48ba560fdb88a59b23e6007acfddbe67c1c30e7e5de9abcfa3a2191c8d55065af654f4f685151d7c1cce61edc540e7afee
|
7
|
+
data.tar.gz: 0cd92dc06458725f440594001bce76f56a00625f88ee2d9afe56981972ac54c4d838ed50eaa1bdbfdbe8f008646bcf02c3614fe2bbe0d2fd4e8f6b99c898eb7b
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Apill
|
2
|
+
class Configuration
|
3
|
+
attr_accessor \
|
4
|
+
:allowed_subdomains,
|
5
|
+
:application_name,
|
6
|
+
:default_api_version
|
7
|
+
|
8
|
+
def to_h
|
9
|
+
{
|
10
|
+
allowed_subdomains: allowed_subdomains,
|
11
|
+
application_name: application_name,
|
12
|
+
default_api_version: api_version,
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.configure
|
18
|
+
yield configuration
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.configuration
|
22
|
+
@configuration ||= Configuration.new
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'human_error'
|
2
|
+
|
3
|
+
module Apill
|
4
|
+
module Errors
|
5
|
+
class InvalidSubdomainError < HumanError::Errors::RequestError
|
6
|
+
attr_accessor :http_host
|
7
|
+
|
8
|
+
def http_status
|
9
|
+
404
|
10
|
+
end
|
11
|
+
|
12
|
+
def developer_message
|
13
|
+
'The resource you attempted to access is either not authorized for the ' \
|
14
|
+
'authenticated user or does not exist.'
|
15
|
+
end
|
16
|
+
|
17
|
+
def developer_details
|
18
|
+
{ http_host: http_host }
|
19
|
+
end
|
20
|
+
|
21
|
+
def friendly_message
|
22
|
+
'Sorry! The resource you tried to access does not exist.'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -13,28 +13,31 @@ module GenericMatcher
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def matches?(request)
|
16
|
-
self.
|
17
|
-
|
16
|
+
self.application = request['API_APPLICATION_NAME']
|
17
|
+
self.accept_header = get_accept_header(raw_header_from_headers: request['HTTP_ACCEPT'],
|
18
|
+
raw_header_from_params: request['QUERY_STRING'])
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
23
|
def get_accept_header(raw_header_from_headers:, raw_header_from_params:)
|
23
|
-
header_from_header =
|
24
|
+
header_from_header = accept_header_from_string(raw_header_from_headers)
|
24
25
|
|
25
|
-
return header_from_header if header_from_header.valid? ||
|
26
|
+
return header_from_header if header_from_header.valid? ||
|
27
|
+
raw_header_from_params.to_s.empty?
|
26
28
|
|
27
|
-
|
29
|
+
accept_header_from_params(raw_header_from_params)
|
28
30
|
end
|
29
31
|
|
30
|
-
def
|
32
|
+
def accept_header_from_string(raw_header_from_headers='')
|
31
33
|
Apill::AcceptHeader.new(application: application,
|
32
34
|
header: raw_header_from_headers)
|
33
35
|
end
|
34
36
|
|
35
37
|
def accept_header_from_params(raw_header_from_params='')
|
36
|
-
|
37
|
-
|
38
|
+
header_from_params = raw_header_from_params[%r{(?:\A|&)accept=(.+?)(?=\z|&)}, 1]
|
39
|
+
|
40
|
+
accept_header_from_string(header_from_params)
|
38
41
|
end
|
39
42
|
end
|
40
43
|
end
|
@@ -1,17 +1,19 @@
|
|
1
1
|
module Apill
|
2
2
|
module Matchers
|
3
3
|
class SubdomainMatcher
|
4
|
-
def initialize(
|
5
|
-
self.
|
4
|
+
def initialize(allowed_subdomains: ['api'])
|
5
|
+
self.allowed_subdomains = Array(allowed_subdomains)
|
6
6
|
end
|
7
7
|
|
8
8
|
def matches?(request)
|
9
|
-
request
|
9
|
+
request_subdomain = request['HTTP_HOST'][/\A([a-z\-]+)/i, 1]
|
10
|
+
|
11
|
+
allowed_subdomains.include? request_subdomain
|
10
12
|
end
|
11
13
|
|
12
14
|
protected
|
13
15
|
|
14
|
-
attr_accessor :
|
16
|
+
attr_accessor :allowed_subdomains
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'apill/matchers/generic_matcher'
|
2
|
-
require 'apill/errors/invalid_api_request_error'
|
3
2
|
|
4
3
|
module Apill
|
5
4
|
module Matchers
|
@@ -12,10 +11,7 @@ class VersionMatcher
|
|
12
11
|
def matches?(request)
|
13
12
|
super
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
request.subdomains.first == 'api' &&
|
18
|
-
requested_version == version_constraint
|
14
|
+
requested_version == version_constraint
|
19
15
|
end
|
20
16
|
|
21
17
|
private
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'apill/configuration'
|
3
|
+
require 'apill/matchers/subdomain_matcher'
|
4
|
+
require 'apill/matchers/invalid_api_request_matcher'
|
5
|
+
require 'apill/responses/invalid_api_request_response'
|
6
|
+
require 'apill/responses/invalid_subdomain_response'
|
7
|
+
|
8
|
+
module Apill
|
9
|
+
module Middleware
|
10
|
+
class ApiRequest
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
env['API_APPLICATION_NAME'] = Apill.configuration.application_name
|
17
|
+
|
18
|
+
if Matchers::SubdomainMatcher.new(allowed_subdomains: Apill.configuration.allowed_subdomains).
|
19
|
+
matches?(env)
|
20
|
+
|
21
|
+
if Matchers::AcceptHeaderMatcher.new.matches?(env)
|
22
|
+
@app.call(env)
|
23
|
+
else
|
24
|
+
Responses::InvalidApiRequestResponse.call(env)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
Responses::InvalidSubdomainResponse.call(env)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'apill/errors/invalid_subdomain_error'
|
2
|
+
|
3
|
+
module Apill
|
4
|
+
module Responses
|
5
|
+
class InvalidSubdomainResponse
|
6
|
+
def self.call(env)
|
7
|
+
error = Apill::Errors::InvalidSubdomainError.new(http_host: env['HTTP_HOST'])
|
8
|
+
|
9
|
+
[
|
10
|
+
error.http_status, # HTTP Status Code
|
11
|
+
{}, # Response Headers
|
12
|
+
[ error.to_json ], # Message
|
13
|
+
]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/apill/version.rb
CHANGED
File without changes
|
File without changes
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'apill/errors/invalid_subdomain_error'
|
3
|
+
|
4
|
+
module Apill
|
5
|
+
module Errors
|
6
|
+
describe InvalidSubdomainError do
|
7
|
+
let(:error) { InvalidSubdomainError.new }
|
8
|
+
|
9
|
+
it 'has a status of 404' do
|
10
|
+
expect(error.http_status).to eql 404
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has a code of 1010' do
|
14
|
+
expect(error.code).to eql 1010
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'has a knowledgebase article ID of 1234567890' do
|
18
|
+
expect(error.knowledgebase_article_id).to eql '1234567890'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'can output the developer message' do
|
22
|
+
expect(error.developer_message).to eql \
|
23
|
+
'The resource you attempted to access is either not authorized for the ' \
|
24
|
+
'authenticated user or does not exist.'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'can output the developer details' do
|
28
|
+
error = InvalidSubdomainError.new http_host: 'foo'
|
29
|
+
|
30
|
+
expect(error.developer_details).to eql(http_host: 'foo')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'can output the friendly message' do
|
34
|
+
expect(error.friendly_message).to eql \
|
35
|
+
'Sorry! The resource you tried to access does not exist.'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'apill/responses/invalid_subdomain_response'
|
3
|
+
|
4
|
+
module Apill
|
5
|
+
module Responses
|
6
|
+
describe InvalidSubdomainResponse do
|
7
|
+
before(:each) do
|
8
|
+
HumanError.configuration.api_error_documentation_url = 'http://error.com'
|
9
|
+
HumanError.configuration.knowledgebase_url = 'http://knowledge.com'
|
10
|
+
HumanError.configuration.api_version = '1'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns the proper response' do
|
14
|
+
request = { 'HTTP_HOST' => 'api.example.com' }
|
15
|
+
response = InvalidSubdomainResponse.call(request)
|
16
|
+
|
17
|
+
expect(response).to eql(
|
18
|
+
[
|
19
|
+
404,
|
20
|
+
{},
|
21
|
+
[
|
22
|
+
'{' \
|
23
|
+
'"error":' \
|
24
|
+
'{' \
|
25
|
+
'"status":404,' \
|
26
|
+
'"code":1010,' \
|
27
|
+
'"developer_documentation_uri":"http://error.com/1010?version=1",' \
|
28
|
+
'"customer_support_uri":"http://knowledge.com/1234567890",' \
|
29
|
+
'"developer_message_key":"errors.invalid.subdomain.error.developer",' \
|
30
|
+
'"developer_message":"The resource you attempted to access is either not authorized for the authenticated user or does not exist.",' \
|
31
|
+
'"developer_details":' \
|
32
|
+
'{' \
|
33
|
+
'"http_host":"api.example.com"' \
|
34
|
+
'},' \
|
35
|
+
'"friendly_message_key":"errors.invalid.subdomain.error.friendly",' \
|
36
|
+
'"friendly_message":"Sorry! The resource you tried to access does not exist."' \
|
37
|
+
'}' \
|
38
|
+
'}'
|
39
|
+
]
|
40
|
+
]
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'apill/matchers/accept_header_matcher'
|
3
|
+
|
4
|
+
module Apill
|
5
|
+
module Matchers
|
6
|
+
describe AcceptHeaderMatcher do
|
7
|
+
it 'matches if the subdomain is API and the accept header is valid' do
|
8
|
+
request = {
|
9
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion;version=1.0.0',
|
10
|
+
'API_APPLICATION_NAME' => 'matrix',
|
11
|
+
}
|
12
|
+
|
13
|
+
matcher = AcceptHeaderMatcher.new
|
14
|
+
|
15
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'matches if the subdomain is API and the accept header is passed in as ' \
|
19
|
+
'a parameter' do
|
20
|
+
|
21
|
+
request = {
|
22
|
+
'QUERY_STRING' => 'accept=application/vnd.matrix+zion;version=1.0.0',
|
23
|
+
'API_APPLICATION_NAME' => 'matrix',
|
24
|
+
}
|
25
|
+
|
26
|
+
matcher = AcceptHeaderMatcher.new
|
27
|
+
|
28
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'matches if the subdomain is API and the accept header is passed in as a ' \
|
32
|
+
'secondary parameter' do
|
33
|
+
|
34
|
+
request = {
|
35
|
+
'QUERY_STRING' => 'first=my_param&accept=application/vnd.matrix+zion;version=1.0.0',
|
36
|
+
'API_APPLICATION_NAME' => 'matrix',
|
37
|
+
}
|
38
|
+
|
39
|
+
matcher = AcceptHeaderMatcher.new
|
40
|
+
|
41
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'matches the header accept header if the subdomain is API and the accept header ' \
|
45
|
+
'is passed both as a valid header and as a parameter' do
|
46
|
+
|
47
|
+
request = {
|
48
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion;version=1.0.0',
|
49
|
+
'QUERY_STRING' => 'accept=application/vnd.matrix+zion;version=2.0.0',
|
50
|
+
'API_APPLICATION_NAME' => 'matrix',
|
51
|
+
}
|
52
|
+
|
53
|
+
matcher = AcceptHeaderMatcher.new
|
54
|
+
matcher.matches?(request)
|
55
|
+
|
56
|
+
expect(matcher.accept_header.version).to eql '1.0.0'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'matches the accept header parameter if the subdomain is API and the accept ' \
|
60
|
+
'header is passed both as an invalid header as well as as a parameter' do
|
61
|
+
|
62
|
+
request = {
|
63
|
+
'HTTP_ACCEPT' => 'application/vndmatrix+zion;version=1.0.0',
|
64
|
+
'QUERY_STRING' => 'accept=application/vnd.matrix+zion;version=2.0.0',
|
65
|
+
'API_APPLICATION_NAME' => 'matrix',
|
66
|
+
}
|
67
|
+
|
68
|
+
matcher = AcceptHeaderMatcher.new
|
69
|
+
matcher.matches?(request)
|
70
|
+
|
71
|
+
expect(matcher.accept_header.version).to eql '2.0.0'
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'matches the accept header parameter if the subdomain is API and the accept ' \
|
75
|
+
'header is passed both as an invalid header as well as as a parameter' do
|
76
|
+
|
77
|
+
request = {
|
78
|
+
'HTTP_ACCEPT' => 'application/vndmatrix+zion;version=1.0.0',
|
79
|
+
'QUERY_STRING' => '',
|
80
|
+
'API_APPLICATION_NAME' => 'matrix',
|
81
|
+
}
|
82
|
+
|
83
|
+
matcher = AcceptHeaderMatcher.new
|
84
|
+
matcher.matches?(request)
|
85
|
+
|
86
|
+
expect(matcher.accept_header.raw_accept_header).to eql \
|
87
|
+
'application/vndmatrix+zion;version=1.0.0'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'does not match if the subdomain is API but the accept header is invalid' do
|
91
|
+
request = {
|
92
|
+
'HTTP_ACCEPT' => 'application/vndmatrix+zion;version=1.0.0',
|
93
|
+
'QUERY_STRING' => '',
|
94
|
+
'API_APPLICATION_NAME' => 'matrix',
|
95
|
+
}
|
96
|
+
|
97
|
+
matcher = AcceptHeaderMatcher.new
|
98
|
+
|
99
|
+
expect(matcher.matches?(request)).to be_a FalseClass
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'rspectacular'
|
3
|
+
require 'apill/matchers/invalid_api_request_matcher'
|
4
|
+
|
5
|
+
module Apill
|
6
|
+
module Matchers
|
7
|
+
describe InvalidApiRequestMatcher do
|
8
|
+
it 'is the inverse of whether the accept header matches' do
|
9
|
+
request = {
|
10
|
+
'HTTP_HOST' => 'api.example.com',
|
11
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion;version=1.0.0',
|
12
|
+
'API_APPLICATION_NAME' => 'matrix',
|
13
|
+
}
|
14
|
+
|
15
|
+
matcher = InvalidApiRequestMatcher.new
|
16
|
+
|
17
|
+
expect(matcher.matches?(request)).to be_a FalseClass
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'apill/matchers/subdomain_matcher'
|
3
|
+
|
4
|
+
module Apill
|
5
|
+
module Matchers
|
6
|
+
describe SubdomainMatcher do
|
7
|
+
it 'matches if the subdomain is API' do
|
8
|
+
matcher = SubdomainMatcher.new
|
9
|
+
request = { 'HTTP_HOST' => 'api.example.com' }
|
10
|
+
|
11
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'matches if the first subdomain is API' do
|
15
|
+
matcher = SubdomainMatcher.new
|
16
|
+
request = { 'HTTP_HOST' => 'api.matrix.example.com' }
|
17
|
+
|
18
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'does not match if the first subdomain is not API' do
|
22
|
+
matcher = SubdomainMatcher.new
|
23
|
+
request = { 'HTTP_HOST' => 'matrix.example.com' }
|
24
|
+
|
25
|
+
expect(matcher.matches?(request)).to be_a FalseClass
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'allows the matched subdomain to be specified' do
|
29
|
+
matcher = SubdomainMatcher.new(allowed_subdomains: 'matrix')
|
30
|
+
request = { 'HTTP_HOST' => 'matrix.example.com' }
|
31
|
+
|
32
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'allows more than one subdomain to be matched' do
|
36
|
+
matcher = SubdomainMatcher.new(allowed_subdomains: %w{api matrix})
|
37
|
+
|
38
|
+
request = { 'HTTP_HOST' => 'matrix.example.com' }
|
39
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
40
|
+
|
41
|
+
request = { 'HTTP_HOST' => 'api.example.com' }
|
42
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'apill/matchers/version_matcher'
|
3
|
+
|
4
|
+
module Apill
|
5
|
+
module Matchers
|
6
|
+
describe VersionMatcher do
|
7
|
+
context 'when the version is passed in the accept header' do
|
8
|
+
it 'does not match if the subdomain is API but the requested version does not ' \
|
9
|
+
'equal the version constraint' do
|
10
|
+
|
11
|
+
request = {
|
12
|
+
'API_APPLICATION_NAME' => 'matrix',
|
13
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion;version=10.0',
|
14
|
+
}
|
15
|
+
|
16
|
+
matcher = VersionMatcher.new(version_constraint: '10.1')
|
17
|
+
|
18
|
+
expect(matcher.matches?(request)).to be_a FalseClass
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'does match if the subdomain is API and the requested version equals the ' \
|
22
|
+
'version constraint' do
|
23
|
+
|
24
|
+
request = {
|
25
|
+
'API_APPLICATION_NAME' => 'matrix',
|
26
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion;version=10.0',
|
27
|
+
}
|
28
|
+
|
29
|
+
matcher = VersionMatcher.new(version_constraint: '10.0')
|
30
|
+
|
31
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when the version is not passed in the accept header' do
|
36
|
+
it 'does not match if the subdomain is API but the requested version does not ' \
|
37
|
+
'equal the version constraint' do
|
38
|
+
|
39
|
+
request = {
|
40
|
+
'API_APPLICATION_NAME' => 'matrix',
|
41
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion',
|
42
|
+
}
|
43
|
+
|
44
|
+
matcher = VersionMatcher.new(version_constraint: '10.1',
|
45
|
+
default_version: '10.0')
|
46
|
+
|
47
|
+
expect(matcher.matches?(request)).to be_a FalseClass
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'does match if the subdomain is API and the requested version equals the ' \
|
51
|
+
'version constraint' do
|
52
|
+
|
53
|
+
request = {
|
54
|
+
'API_APPLICATION_NAME' => 'matrix',
|
55
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion',
|
56
|
+
}
|
57
|
+
|
58
|
+
matcher = VersionMatcher.new(version_constraint: '10.0',
|
59
|
+
default_version: '10.0')
|
60
|
+
|
61
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'rspectacular'
|
2
|
+
require 'apill/middleware/api_request'
|
3
|
+
|
4
|
+
HumanError.configure do |config|
|
5
|
+
config.api_error_documentation_url = 'http://error.com'
|
6
|
+
config.knowledgebase_url = 'http://knowledge.com'
|
7
|
+
config.api_version = '1'
|
8
|
+
end
|
9
|
+
|
10
|
+
Apill.configure do |config|
|
11
|
+
config.allowed_subdomains = %w{api}
|
12
|
+
config.application_name = 'matrix'
|
13
|
+
end
|
14
|
+
|
15
|
+
module Apill
|
16
|
+
module Middleware
|
17
|
+
describe ApiRequest do
|
18
|
+
let(:app) { lambda { |env| [200, {}, 'response'] } }
|
19
|
+
|
20
|
+
it 'does not allow requests if they are not for an allowed subdomain' do
|
21
|
+
api_request_middleware = ApiRequest.new(app)
|
22
|
+
|
23
|
+
request = {
|
24
|
+
'HTTP_HOST' => 'notvalid.example.com',
|
25
|
+
'HTTP_ACCEPT' => '',
|
26
|
+
'QUERY_STRING' => 'first=my_param&accept=application/vnd.silent+zion;version=1.0.0',
|
27
|
+
'API_APPLICATION_NAME' => 'matrix',
|
28
|
+
}
|
29
|
+
|
30
|
+
status, headers, response = api_request_middleware.call(request)
|
31
|
+
|
32
|
+
expect(status).to eql 404
|
33
|
+
expect(headers).to eql Hash.new
|
34
|
+
expect(response).to eql(
|
35
|
+
[
|
36
|
+
'{' \
|
37
|
+
'"error":' \
|
38
|
+
'{' \
|
39
|
+
'"status":404,' \
|
40
|
+
'"code":1010,' \
|
41
|
+
'"developer_documentation_uri":"http://error.com/1010?version=1",' \
|
42
|
+
'"customer_support_uri":"http://knowledge.com/1234567890",' \
|
43
|
+
'"developer_message_key":"errors.invalid.subdomain.error.developer",' \
|
44
|
+
'"developer_message":"The resource you attempted to access is either not authorized for the authenticated user or does not exist.",' \
|
45
|
+
'"developer_details":' \
|
46
|
+
'{' \
|
47
|
+
'"http_host":"notvalid.example.com"' \
|
48
|
+
'},' \
|
49
|
+
'"friendly_message_key":"errors.invalid.subdomain.error.friendly",' \
|
50
|
+
'"friendly_message":"Sorry! The resource you tried to access does not exist."' \
|
51
|
+
'}' \
|
52
|
+
'}'
|
53
|
+
]
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'does not allow requests if they are for an allowed subdomain but does ' \
|
58
|
+
'not have a valid accept header' do
|
59
|
+
|
60
|
+
api_request_middleware = ApiRequest.new(app)
|
61
|
+
|
62
|
+
request = {
|
63
|
+
'HTTP_HOST' => 'api.example.com',
|
64
|
+
'HTTP_ACCEPT' => '',
|
65
|
+
'QUERY_STRING' => 'first=my_param&accept=application/vnd.silent+zion;version=1.0.0',
|
66
|
+
'API_APPLICATION_NAME' => 'matrix',
|
67
|
+
}
|
68
|
+
|
69
|
+
status, headers, response = api_request_middleware.call(request)
|
70
|
+
|
71
|
+
expect(status).to eql 400
|
72
|
+
expect(headers).to eql Hash.new
|
73
|
+
expect(response).to eql(
|
74
|
+
[
|
75
|
+
'{' \
|
76
|
+
'"error":' \
|
77
|
+
'{' \
|
78
|
+
'"status":400,' \
|
79
|
+
'"code":1007,' \
|
80
|
+
'"developer_documentation_uri":"http://error.com/1007?version=1",' \
|
81
|
+
'"customer_support_uri":"http://knowledge.com/1234567890",' \
|
82
|
+
'"developer_message_key":"errors.invalid.api.request.error.developer",' \
|
83
|
+
'"developer_message":"The accept header that you passed in the request cannot be parsed, please refer to the documentation to verify.",' \
|
84
|
+
'"developer_details":' \
|
85
|
+
'{' \
|
86
|
+
'"accept_header":""' \
|
87
|
+
'},' \
|
88
|
+
'"friendly_message_key":"errors.invalid.api.request.error.friendly",' \
|
89
|
+
'"friendly_message":"Sorry! We couldn\'t understand what you were trying to ask us to do."' \
|
90
|
+
'}' \
|
91
|
+
'}'
|
92
|
+
]
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'does allow requests if both the subdomain and the accept header are valid' do
|
97
|
+
api_request_middleware = ApiRequest.new(app)
|
98
|
+
|
99
|
+
request = {
|
100
|
+
'HTTP_HOST' => 'api.example.com',
|
101
|
+
'HTTP_ACCEPT' => 'application/vnd.matrix+zion;version=1.0.0',
|
102
|
+
'QUERY_STRING' => 'first=my_param&accept=application/vnd.matrix+zion;version=1.0.0',
|
103
|
+
'API_APPLICATION_NAME' => 'matrix',
|
104
|
+
}
|
105
|
+
|
106
|
+
status, headers, response = api_request_middleware.call(request)
|
107
|
+
|
108
|
+
expect(status).to eql 200
|
109
|
+
expect(headers).to eql Hash.new
|
110
|
+
expect(response).to eql 'response'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jfelchner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06
|
11
|
+
date: 2014-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: human_error
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.13'
|
20
20
|
type: :runtime
|
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: '1.
|
26
|
+
version: '1.13'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,47 +44,66 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
47
|
+
version: '0.50'
|
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: '0.
|
54
|
+
version: '0.50'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: codeclimate-test-reporter
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.3.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.3.0
|
55
69
|
description: ''
|
56
70
|
email: accounts+git@thekompanee.com
|
57
71
|
executables: []
|
58
72
|
extensions: []
|
59
|
-
extra_rdoc_files:
|
60
|
-
- README.md
|
61
|
-
- LICENSE
|
73
|
+
extra_rdoc_files: []
|
62
74
|
files:
|
63
75
|
- LICENSE
|
64
76
|
- README.md
|
65
77
|
- Rakefile
|
66
78
|
- lib/apill.rb
|
67
79
|
- lib/apill/accept_header.rb
|
80
|
+
- lib/apill/configuration.rb
|
68
81
|
- lib/apill/errors/invalid_api_request_error.rb
|
82
|
+
- lib/apill/errors/invalid_subdomain_error.rb
|
69
83
|
- lib/apill/matchers/accept_header_matcher.rb
|
70
84
|
- lib/apill/matchers/generic_matcher.rb
|
71
85
|
- lib/apill/matchers/invalid_api_request_matcher.rb
|
72
86
|
- lib/apill/matchers/subdomain_matcher.rb
|
73
87
|
- lib/apill/matchers/version_matcher.rb
|
88
|
+
- lib/apill/middleware/api_request.rb
|
74
89
|
- lib/apill/responses/invalid_api_request_response.rb
|
90
|
+
- lib/apill/responses/invalid_subdomain_response.rb
|
75
91
|
- lib/apill/version.rb
|
76
|
-
- spec/
|
77
|
-
- spec/
|
78
|
-
- spec/
|
79
|
-
- spec/
|
80
|
-
- spec/
|
81
|
-
- spec/
|
92
|
+
- spec/apill/accept_header_spec.rb
|
93
|
+
- spec/apill/errors/invalid_api_request_error_spec.rb
|
94
|
+
- spec/apill/errors/invalid_subdomain_error_spec.rb
|
95
|
+
- spec/apill/invalid_subdomain_response_spec.rb
|
96
|
+
- spec/apill/matchers/accept_header_matcher_spec.rb
|
97
|
+
- spec/apill/matchers/invalid_api_request_matcher_spec.rb
|
98
|
+
- spec/apill/matchers/subdomain_matcher_spec.rb
|
99
|
+
- spec/apill/matchers/version_matcher_spec.rb
|
100
|
+
- spec/apill/middleware/api_request_spec.rb
|
82
101
|
homepage: https://github.com/jfelchner/apill
|
83
|
-
licenses:
|
102
|
+
licenses:
|
103
|
+
- MIT
|
84
104
|
metadata: {}
|
85
105
|
post_install_message:
|
86
|
-
rdoc_options:
|
87
|
-
- "--charset = UTF-8"
|
106
|
+
rdoc_options: []
|
88
107
|
require_paths:
|
89
108
|
- lib
|
90
109
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -98,16 +117,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
117
|
- !ruby/object:Gem::Version
|
99
118
|
version: '0'
|
100
119
|
requirements: []
|
101
|
-
rubyforge_project:
|
102
|
-
rubygems_version: 2.
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.4.2
|
103
122
|
signing_key:
|
104
123
|
specification_version: 4
|
105
124
|
summary: Common API functionality
|
106
125
|
test_files:
|
107
|
-
- spec/
|
108
|
-
- spec/
|
109
|
-
- spec/
|
110
|
-
- spec/
|
111
|
-
- spec/
|
112
|
-
- spec/
|
126
|
+
- spec/apill/accept_header_spec.rb
|
127
|
+
- spec/apill/errors/invalid_api_request_error_spec.rb
|
128
|
+
- spec/apill/errors/invalid_subdomain_error_spec.rb
|
129
|
+
- spec/apill/invalid_subdomain_response_spec.rb
|
130
|
+
- spec/apill/matchers/accept_header_matcher_spec.rb
|
131
|
+
- spec/apill/matchers/invalid_api_request_matcher_spec.rb
|
132
|
+
- spec/apill/matchers/subdomain_matcher_spec.rb
|
133
|
+
- spec/apill/matchers/version_matcher_spec.rb
|
134
|
+
- spec/apill/middleware/api_request_spec.rb
|
113
135
|
has_rdoc:
|
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
require 'rspectacular'
|
3
|
-
require 'apill/matchers/accept_header_matcher'
|
4
|
-
|
5
|
-
module Apill
|
6
|
-
module Matchers
|
7
|
-
describe AcceptHeaderMatcher do
|
8
|
-
it 'matches if the subdomain is API and the accept header is valid' do
|
9
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion;version=1.0.0' },
|
10
|
-
params: {},
|
11
|
-
subdomains: [ 'api' ])
|
12
|
-
|
13
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
14
|
-
|
15
|
-
expect(matcher.matches?(request)).to be_truthy
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'matches if the subdomain is API and the accept header is passed in as a parameter' do
|
19
|
-
request = OpenStruct.new(headers: {},
|
20
|
-
params: { 'accept' => 'application/vnd.matrix+zion;version=1.0.0' },
|
21
|
-
subdomains: [ 'api' ])
|
22
|
-
|
23
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
24
|
-
|
25
|
-
expect(matcher.matches?(request)).to be_truthy
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'matches the header accept header if the subdomain is API and the accept header is passed both as a valid header and as a parameter' do
|
29
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion;version=1.0.0' },
|
30
|
-
params: { 'accept' => 'application/vnd.matrix+zion;version=2.0.0' },
|
31
|
-
subdomains: [ 'api' ])
|
32
|
-
|
33
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
34
|
-
matcher.matches?(request)
|
35
|
-
|
36
|
-
expect(matcher.accept_header.version).to eql '1.0.0'
|
37
|
-
end
|
38
|
-
|
39
|
-
it "matches the parameter's accept header if the subdomain is API and the accept header is passed both as an invalid header as well as as a parameter" do
|
40
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vndmatrix+zion;version=1.0.0' },
|
41
|
-
params: { 'accept' => 'application/vnd.matrix+zion;version=2.0.0' },
|
42
|
-
subdomains: [ 'api' ])
|
43
|
-
|
44
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
45
|
-
matcher.matches?(request)
|
46
|
-
|
47
|
-
expect(matcher.accept_header.version).to eql '2.0.0'
|
48
|
-
end
|
49
|
-
|
50
|
-
it "matches the parameter's accept header if the subdomain is API and the accept header is passed both as an invalid header as well as as a parameter" do
|
51
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vndmatrix+zion;version=1.0.0' },
|
52
|
-
params: {},
|
53
|
-
subdomains: [ 'api' ])
|
54
|
-
|
55
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
56
|
-
matcher.matches?(request)
|
57
|
-
|
58
|
-
expect(matcher.accept_header.raw_accept_header).to eql 'application/vndmatrix+zion;version=1.0.0'
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'does not match if the subdomain is not API but the accept header is valid' do
|
62
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion' },
|
63
|
-
params: {},
|
64
|
-
subdomains: [ 'not-api' ])
|
65
|
-
|
66
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
67
|
-
|
68
|
-
expect(matcher.matches?(request)).to be_falsey
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'does not match if the subdomain is API but the accept header is invalid' do
|
72
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.' },
|
73
|
-
params: {},
|
74
|
-
subdomains: [ 'api' ])
|
75
|
-
|
76
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
77
|
-
|
78
|
-
expect(matcher.matches?(request)).to be_falsey
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'does not match if neither the subdomain is API nor the accept header is valid' do
|
82
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.' },
|
83
|
-
params: {},
|
84
|
-
subdomains: [ 'not-api' ])
|
85
|
-
|
86
|
-
matcher = AcceptHeaderMatcher.new(application: 'matrix')
|
87
|
-
|
88
|
-
expect(matcher.matches?(request)).to be_falsey
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
require 'rspectacular'
|
3
|
-
require 'apill/matchers/invalid_api_request_matcher'
|
4
|
-
|
5
|
-
module Apill
|
6
|
-
module Matchers
|
7
|
-
describe InvalidApiRequestMatcher do
|
8
|
-
it 'is the inverse of whether the accept header matches' do
|
9
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion;version=1.0.0' },
|
10
|
-
subdomains: [ 'api' ],
|
11
|
-
params: {})
|
12
|
-
|
13
|
-
matcher = InvalidApiRequestMatcher.new(application: 'matrix')
|
14
|
-
|
15
|
-
expect(matcher.matches?(request)).to be_falsey
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
require 'rspectacular'
|
3
|
-
require 'apill/matchers/subdomain_matcher'
|
4
|
-
|
5
|
-
module Apill
|
6
|
-
module Matchers
|
7
|
-
describe SubdomainMatcher do
|
8
|
-
it 'matches if the subdomain is API' do
|
9
|
-
request = OpenStruct.new(subdomains: [ 'api' ])
|
10
|
-
|
11
|
-
matcher = SubdomainMatcher.new
|
12
|
-
|
13
|
-
expect(matcher.matches?(request)).to be_truthy
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'matches if the first subdomain is API' do
|
17
|
-
request = OpenStruct.new(subdomains: [ 'api', 'matrix' ])
|
18
|
-
|
19
|
-
matcher = SubdomainMatcher.new
|
20
|
-
|
21
|
-
expect(matcher.matches?(request)).to be_truthy
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'does not match if the first subdomain is not API' do
|
25
|
-
request = OpenStruct.new(subdomains: [ 'matrix' ])
|
26
|
-
|
27
|
-
matcher = SubdomainMatcher.new
|
28
|
-
|
29
|
-
expect(matcher.matches?(request)).to be_falsey
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'allows the matched subdomain to be specified' do
|
33
|
-
request = OpenStruct.new(subdomains: [ 'matrix' ])
|
34
|
-
|
35
|
-
matcher = SubdomainMatcher.new(subdomain: 'matrix')
|
36
|
-
|
37
|
-
expect(matcher.matches?(request)).to be_truthy
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
require 'rspectacular'
|
3
|
-
require 'apill/matchers/version_matcher'
|
4
|
-
|
5
|
-
module Apill
|
6
|
-
module Matchers
|
7
|
-
describe VersionMatcher do
|
8
|
-
it 'raises an error when the accept header is not valid' do
|
9
|
-
request = OpenStruct.new(headers: { 'Accept' => 'matrix' },
|
10
|
-
subdomains: [ 'api' ],
|
11
|
-
params: {})
|
12
|
-
|
13
|
-
matcher = VersionMatcher.new
|
14
|
-
|
15
|
-
expect { matcher.matches?(request) }.to raise_error Apill::Errors::InvalidApiRequestError
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'when the version is passed in the accept header' do
|
19
|
-
it 'does not match if the subdomain is not API but the request version is equal to the version constraint' do
|
20
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion;version=10.0' },
|
21
|
-
subdomains: [ 'not-api' ],
|
22
|
-
params: {})
|
23
|
-
|
24
|
-
matcher = VersionMatcher.new(application: 'matrix',
|
25
|
-
version_constraint: '10.0')
|
26
|
-
|
27
|
-
expect(matcher.matches?(request)).to be_falsey
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'does not match if the subdomain is API but the requested version does not equal the version constraint' do
|
31
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion;version=10.0' },
|
32
|
-
subdomains: [ 'api' ],
|
33
|
-
params: {})
|
34
|
-
|
35
|
-
matcher = VersionMatcher.new(application: 'matrix',
|
36
|
-
version_constraint: '10.1')
|
37
|
-
|
38
|
-
expect(matcher.matches?(request)).to be_falsey
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'does match if the subdomain is API and the requested version equals the version constraint' do
|
42
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion;version=10.0' },
|
43
|
-
subdomains: [ 'api' ],
|
44
|
-
params: {})
|
45
|
-
|
46
|
-
matcher = VersionMatcher.new(application: 'matrix',
|
47
|
-
version_constraint: '10.0')
|
48
|
-
|
49
|
-
expect(matcher.matches?(request)).to be_truthy
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'when the version is not passed in the accept header' do
|
54
|
-
it 'does not match if the subdomain is not API but the request version is equal to the version constraint' do
|
55
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion' },
|
56
|
-
subdomains: [ 'not-api' ],
|
57
|
-
params: {})
|
58
|
-
|
59
|
-
matcher = VersionMatcher.new(application: 'matrix',
|
60
|
-
version_constraint: '10.0',
|
61
|
-
default_version: '10.0')
|
62
|
-
|
63
|
-
expect(matcher.matches?(request)).to be_falsey
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'does not match if the subdomain is API but the requested version does not equal the version constraint' do
|
67
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion' },
|
68
|
-
subdomains: [ 'api' ],
|
69
|
-
params: {})
|
70
|
-
|
71
|
-
matcher = VersionMatcher.new(application: 'matrix',
|
72
|
-
version_constraint: '10.1',
|
73
|
-
default_version: '10.0')
|
74
|
-
|
75
|
-
expect(matcher.matches?(request)).to be_falsey
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'does match if the subdomain is API and the requested version equals the version constraint' do
|
79
|
-
request = OpenStruct.new(headers: { 'Accept' => 'application/vnd.matrix+zion' },
|
80
|
-
subdomains: [ 'api' ],
|
81
|
-
params: {})
|
82
|
-
|
83
|
-
matcher = VersionMatcher.new(application: 'matrix',
|
84
|
-
version_constraint: '10.0',
|
85
|
-
default_version: '10.0')
|
86
|
-
|
87
|
-
expect(matcher.matches?(request)).to be_truthy
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|