drillbit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/LICENSE.txt +19 -0
- data/README.md +2 -0
- data/Rakefile +2 -0
- data/lib/drillbit.rb +19 -0
- data/lib/drillbit/accept_header.rb +50 -0
- data/lib/drillbit/authorizable_resource.rb +160 -0
- data/lib/drillbit/authorizers/parameters.rb +24 -0
- data/lib/drillbit/authorizers/parameters/filtering.rb +50 -0
- data/lib/drillbit/authorizers/parameters/resource.rb +11 -0
- data/lib/drillbit/authorizers/query.rb +40 -0
- data/lib/drillbit/authorizers/scope.rb +30 -0
- data/lib/drillbit/configuration.rb +36 -0
- data/lib/drillbit/errors/invalid_api_request.rb +29 -0
- data/lib/drillbit/errors/invalid_subdomain.rb +29 -0
- data/lib/drillbit/errors/invalid_token.rb +22 -0
- data/lib/drillbit/matchers/accept_header.rb +16 -0
- data/lib/drillbit/matchers/generic.rb +30 -0
- data/lib/drillbit/matchers/subdomain.rb +31 -0
- data/lib/drillbit/matchers/version.rb +30 -0
- data/lib/drillbit/middleware/api_request.rb +49 -0
- data/lib/drillbit/parameters.rb +22 -0
- data/lib/drillbit/parameters/filter.rb +57 -0
- data/lib/drillbit/parameters/index.rb +31 -0
- data/lib/drillbit/parameters/page.rb +28 -0
- data/lib/drillbit/parameters/sort.rb +32 -0
- data/lib/drillbit/requests/base.rb +114 -0
- data/lib/drillbit/requests/rack.rb +50 -0
- data/lib/drillbit/requests/rails.rb +44 -0
- data/lib/drillbit/resource.rb +14 -0
- data/lib/drillbit/resource/model.rb +41 -0
- data/lib/drillbit/resource/naming.rb +33 -0
- data/lib/drillbit/resource/processors/filtering.rb +66 -0
- data/lib/drillbit/resource/processors/indexing.rb +40 -0
- data/lib/drillbit/resource/processors/paging.rb +46 -0
- data/lib/drillbit/resource/processors/sorting.rb +42 -0
- data/lib/drillbit/responses/invalid_api_request.rb +18 -0
- data/lib/drillbit/responses/invalid_subdomain.rb +18 -0
- data/lib/drillbit/responses/invalid_token.rb +20 -0
- data/lib/drillbit/serializers/json_api.rb +10 -0
- data/lib/drillbit/tokens/base64.rb +45 -0
- data/lib/drillbit/tokens/base64s/invalid.rb +14 -0
- data/lib/drillbit/tokens/base64s/null.rb +14 -0
- data/lib/drillbit/tokens/invalid.rb +26 -0
- data/lib/drillbit/tokens/json_web_token.rb +112 -0
- data/lib/drillbit/tokens/json_web_tokens/invalid.rb +14 -0
- data/lib/drillbit/tokens/json_web_tokens/null.rb +14 -0
- data/lib/drillbit/tokens/null.rb +26 -0
- data/lib/drillbit/version.rb +4 -0
- data/spec/drillbit/accept_header_spec.rb +112 -0
- data/spec/drillbit/authorizers/parameters/filtering_spec.rb +71 -0
- data/spec/drillbit/authorizers/parameters/resource_spec.rb +12 -0
- data/spec/drillbit/authorizers/parameters_spec.rb +17 -0
- data/spec/drillbit/authorizers/query_spec.rb +21 -0
- data/spec/drillbit/authorizers/scope_spec.rb +20 -0
- data/spec/drillbit/errors/invalid_api_request_spec.rb +31 -0
- data/spec/drillbit/errors/invalid_subdomain_spec.rb +31 -0
- data/spec/drillbit/errors/invalid_token_spec.rb +24 -0
- data/spec/drillbit/invalid_subdomain_spec.rb +46 -0
- data/spec/drillbit/invalid_token_spec.rb +44 -0
- data/spec/drillbit/matchers/accept_header_spec.rb +114 -0
- data/spec/drillbit/matchers/subdomain_spec.rb +78 -0
- data/spec/drillbit/matchers/version_spec.rb +86 -0
- data/spec/drillbit/middleware/api_request_spec.rb +220 -0
- data/spec/drillbit/parameters_spec.rb +49 -0
- data/spec/drillbit/requests/base_spec.rb +37 -0
- data/spec/drillbit/requests/rack_spec.rb +253 -0
- data/spec/drillbit/requests/rails_spec.rb +264 -0
- data/spec/drillbit/resource/model_spec.rb +64 -0
- data/spec/drillbit/resource/processors/filtering_spec.rb +106 -0
- data/spec/drillbit/resource/processors/indexing_spec.rb +46 -0
- data/spec/drillbit/resource/processors/paging_spec.rb +74 -0
- data/spec/drillbit/resource/processors/sorting_spec.rb +66 -0
- data/spec/drillbit/tokens/base64_spec.rb +44 -0
- data/spec/drillbit/tokens/json_web_token_spec.rb +135 -0
- data/spec/fixtures/test_rsa_key +27 -0
- data/spec/fixtures/test_rsa_key.pub +9 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/private_keys.rb +42 -0
- metadata +244 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rspeckled'
|
3
|
+
require 'drillbit/authorizers/parameters'
|
4
|
+
|
5
|
+
module Drillbit
|
6
|
+
module Authorizers
|
7
|
+
RSpec.describe Parameters do
|
8
|
+
it 'defaults to nothing' do
|
9
|
+
parameters = Parameters.new(token: '123',
|
10
|
+
user: 'my_user',
|
11
|
+
params: { foo: 'bar' })
|
12
|
+
|
13
|
+
expect(parameters.call).to eql(foo: 'bar')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rspeckled'
|
3
|
+
require 'drillbit/authorizers/query'
|
4
|
+
|
5
|
+
module Drillbit
|
6
|
+
module Authorizers
|
7
|
+
RSpec.describe Query do
|
8
|
+
it 'does not authorize the resource by default' do
|
9
|
+
authorizer = Query.new(token: '123',
|
10
|
+
user: 'my_user',
|
11
|
+
resource: 'my_resource')
|
12
|
+
|
13
|
+
expect(authorizer).to be_able_to_index
|
14
|
+
expect(authorizer).not_to be_able_to_show
|
15
|
+
expect(authorizer).not_to be_able_to_create
|
16
|
+
expect(authorizer).not_to be_able_to_update
|
17
|
+
expect(authorizer).not_to be_able_to_destroy
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rspeckled'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'drillbit/authorizers/scope'
|
5
|
+
|
6
|
+
module Drillbit
|
7
|
+
module Authorizers
|
8
|
+
RSpec.describe Scope do
|
9
|
+
it 'defaults to nothing' do
|
10
|
+
scope = Scope.new(token: '123',
|
11
|
+
user: 'my_user',
|
12
|
+
scoped_user_id: '456',
|
13
|
+
params: {},
|
14
|
+
scope_root: OpenStruct.new(none: []))
|
15
|
+
|
16
|
+
expect(scope.call).to be_empty
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'drillbit/errors/invalid_api_request'
|
4
|
+
|
5
|
+
module Drillbit
|
6
|
+
module Errors
|
7
|
+
RSpec.describe InvalidApiRequest do
|
8
|
+
let(:error) { InvalidApiRequest.new }
|
9
|
+
|
10
|
+
it 'has a status of 400' do
|
11
|
+
expect(error.http_status).to eql 400
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has a code' do
|
15
|
+
expect(error.code).to eql 'errors.invalid_api_request'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'can output the detail' do
|
19
|
+
expect(error.detail).to eql 'The accept header that you passed in the ' \
|
20
|
+
'request cannot be parsed, please refer to ' \
|
21
|
+
'the documentation to verify.'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'can output the source' do
|
25
|
+
error = InvalidApiRequest.new accept_header: 'foo'
|
26
|
+
|
27
|
+
expect(error.source).to eql(accept_header: 'foo')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'drillbit/errors/invalid_subdomain'
|
4
|
+
|
5
|
+
module Drillbit
|
6
|
+
module Errors
|
7
|
+
RSpec.describe InvalidSubdomain do
|
8
|
+
let(:error) { InvalidSubdomain.new }
|
9
|
+
|
10
|
+
it 'has a status of 404' do
|
11
|
+
expect(error.http_status).to eql 404
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has a code' do
|
15
|
+
expect(error.code).to eql 'errors.invalid_subdomain'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'can output the detail' do
|
19
|
+
expect(error.detail).to eql \
|
20
|
+
'The resource you attempted to access is either not authorized for the ' \
|
21
|
+
'authenticated user or does not exist.'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'can output the source' do
|
25
|
+
error = InvalidSubdomain.new http_host: 'foo'
|
26
|
+
|
27
|
+
expect(error.source).to eql(http_host: 'foo')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'drillbit/errors/invalid_token'
|
4
|
+
|
5
|
+
module Drillbit
|
6
|
+
module Errors
|
7
|
+
RSpec.describe InvalidToken do
|
8
|
+
let(:error) { InvalidToken.new }
|
9
|
+
|
10
|
+
it 'has a status of 401' do
|
11
|
+
expect(error.http_status).to eql 401
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has a code' do
|
15
|
+
expect(error.code).to eql 'errors.invalid_token'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'can output the detail' do
|
19
|
+
expect(error.detail).to eql \
|
20
|
+
'Either the token you passed is invalid or is not allowed to perform this action.'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'drillbit/responses/invalid_subdomain'
|
4
|
+
|
5
|
+
# rubocop:disable Metrics/LineLength
|
6
|
+
module Drillbit
|
7
|
+
module Responses
|
8
|
+
RSpec.describe InvalidSubdomain, singletons: Erratum::Configuration do
|
9
|
+
it 'returns the proper response' do
|
10
|
+
Erratum.configuration.url_mappings = {
|
11
|
+
'external_documentation_urls' => {
|
12
|
+
'errors.responses.invalid_subdomain' => 'http://example.com/foo',
|
13
|
+
},
|
14
|
+
'developer_documentation_urls' => {
|
15
|
+
'errors.responses.invalid_subdomain' => 'http://example.com/foo',
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
request = { 'HTTP_HOST' => 'api.example.com' }
|
20
|
+
status, headers, response = InvalidSubdomain.call(request)
|
21
|
+
|
22
|
+
expect(status).to eql 404
|
23
|
+
expect(headers).to eql({})
|
24
|
+
expect(JSON.load(response[0])).to include(
|
25
|
+
'errors' => [
|
26
|
+
include(
|
27
|
+
'id' => match(/[a-f0-9\-]+/),
|
28
|
+
'links' => {
|
29
|
+
'about' => nil,
|
30
|
+
'documentation' => nil,
|
31
|
+
},
|
32
|
+
'status' => 404,
|
33
|
+
'code' => 'errors.invalid_subdomain',
|
34
|
+
'title' => 'Invalid Subdomain',
|
35
|
+
'detail' => 'The resource you attempted to access is either not authorized ' \
|
36
|
+
'for the authenticated user or does not exist.',
|
37
|
+
'source' => {
|
38
|
+
'http_host' => 'api.example.com',
|
39
|
+
},
|
40
|
+
),
|
41
|
+
],
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'drillbit/responses/invalid_token'
|
4
|
+
|
5
|
+
# rubocop:disable Metrics/LineLength
|
6
|
+
module Drillbit
|
7
|
+
module Responses
|
8
|
+
RSpec.describe InvalidToken, singletons: Erratum::Configuration do
|
9
|
+
it 'returns the proper response' do
|
10
|
+
Erratum.configuration.url_mappings = {
|
11
|
+
'external_documentation_urls' => {
|
12
|
+
'errors.responses.invalid_token' => 'http://example.com/foo',
|
13
|
+
},
|
14
|
+
'developer_documentation_urls' => {
|
15
|
+
'errors.responses.invalid_token' => 'http://example.com/foo',
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
request = { 'HTTP_HOST' => 'api.example.com' }
|
20
|
+
status, headers, response = InvalidToken.call(request, application_name: 'my_app')
|
21
|
+
|
22
|
+
expect(status).to eql 401
|
23
|
+
expect(headers).to eql('WWW-Authenticate' => 'Token realm="my_app"')
|
24
|
+
expect(JSON.load(response[0])).to include(
|
25
|
+
'errors' => [
|
26
|
+
include(
|
27
|
+
'id' => match(/[a-f0-9\-]+/),
|
28
|
+
'links' => {
|
29
|
+
'about' => nil,
|
30
|
+
'documentation' => nil,
|
31
|
+
},
|
32
|
+
'status' => 401,
|
33
|
+
'code' => 'errors.invalid_token',
|
34
|
+
'title' => 'Invalid or Unauthorized Token',
|
35
|
+
'detail' => 'Either the token you passed is invalid or is not allowed to ' \
|
36
|
+
'perform this action.',
|
37
|
+
'source' => {},
|
38
|
+
),
|
39
|
+
],
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'drillbit/requests/base'
|
4
|
+
require 'drillbit/matchers/accept_header'
|
5
|
+
|
6
|
+
# rubocop:disable Metrics/LineLength
|
7
|
+
module Drillbit
|
8
|
+
module Matchers
|
9
|
+
RSpec.describe AcceptHeader do
|
10
|
+
it 'matches if the subdomain is API and the accept header is valid' do
|
11
|
+
env = {
|
12
|
+
'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=1.0.0',
|
13
|
+
'HTTP_X_APPLICATION_NAME' => 'westeros',
|
14
|
+
}
|
15
|
+
request = Requests::Base.resolve(env)
|
16
|
+
|
17
|
+
matcher = AcceptHeader.new
|
18
|
+
|
19
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'matches if the subdomain is API and the accept header is passed in as ' \
|
23
|
+
'a parameter' do
|
24
|
+
|
25
|
+
env = {
|
26
|
+
'QUERY_STRING' => 'accept=application/vnd.westeros+redkeep;version=1.0.0',
|
27
|
+
'HTTP_X_APPLICATION_NAME' => 'westeros',
|
28
|
+
}
|
29
|
+
request = Requests::Base.resolve(env)
|
30
|
+
|
31
|
+
matcher = AcceptHeader.new
|
32
|
+
|
33
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'matches if the subdomain is API and the accept header is passed in as a ' \
|
37
|
+
'secondary parameter' do
|
38
|
+
|
39
|
+
env = {
|
40
|
+
'QUERY_STRING' => 'first=my_param&accept=application/vnd.westeros+redkeep;' \
|
41
|
+
'version=1.0.0',
|
42
|
+
'HTTP_X_APPLICATION_NAME' => 'westeros',
|
43
|
+
}
|
44
|
+
request = Requests::Base.resolve(env)
|
45
|
+
|
46
|
+
matcher = AcceptHeader.new
|
47
|
+
|
48
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'matches the header accept header if the subdomain is API and the accept header ' \
|
52
|
+
'is passed both as a valid header and as a parameter' do
|
53
|
+
|
54
|
+
env = {
|
55
|
+
'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=1.0.0',
|
56
|
+
'QUERY_STRING' => 'accept=application/vnd.westeros+redkeep;version=2.0.0',
|
57
|
+
'HTTP_X_APPLICATION_NAME' => 'westeros',
|
58
|
+
}
|
59
|
+
request = Requests::Base.resolve(env)
|
60
|
+
|
61
|
+
matcher = AcceptHeader.new
|
62
|
+
matcher.matches?(request)
|
63
|
+
|
64
|
+
expect(matcher.accept_header.version).to eql '1.0.0'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'matches the accept header parameter if the subdomain is API and the accept ' \
|
68
|
+
'header is passed both as an invalid header as well as as a parameter' do
|
69
|
+
|
70
|
+
env = {
|
71
|
+
'HTTP_ACCEPT' => 'application/vndwesteros+redkeep;version=1.0.0',
|
72
|
+
'QUERY_STRING' => 'accept=application/vnd.westeros+redkeep;version=2.0.0',
|
73
|
+
'HTTP_X_APPLICATION_NAME' => 'westeros',
|
74
|
+
}
|
75
|
+
request = Requests::Base.resolve(env)
|
76
|
+
|
77
|
+
matcher = AcceptHeader.new
|
78
|
+
matcher.matches?(request)
|
79
|
+
|
80
|
+
expect(matcher.accept_header.version).to eql '2.0.0'
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'matches the accept header parameter if the subdomain is API and the accept ' \
|
84
|
+
'header is passed both as an invalid header as well as as a parameter' do
|
85
|
+
|
86
|
+
env = {
|
87
|
+
'HTTP_ACCEPT' => 'application/vndwesteros+redkeep;version=1.0.0',
|
88
|
+
'QUERY_STRING' => '',
|
89
|
+
'HTTP_X_APPLICATION_NAME' => 'westeros',
|
90
|
+
}
|
91
|
+
request = Requests::Base.resolve(env)
|
92
|
+
|
93
|
+
matcher = AcceptHeader.new
|
94
|
+
matcher.matches?(request)
|
95
|
+
|
96
|
+
expect(matcher.accept_header.raw_accept_header).to eql \
|
97
|
+
'application/vndwesteros+redkeep;version=1.0.0'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'does not match if the subdomain is API but the accept header is invalid' do
|
101
|
+
env = {
|
102
|
+
'HTTP_ACCEPT' => 'application/vndwesteros+redkeep;version=1.0.0',
|
103
|
+
'QUERY_STRING' => '',
|
104
|
+
'HTTP_X_APPLICATION_NAME' => 'westeros',
|
105
|
+
}
|
106
|
+
request = Requests::Base.resolve(env)
|
107
|
+
|
108
|
+
matcher = AcceptHeader.new
|
109
|
+
|
110
|
+
expect(matcher.matches?(request)).to be_a FalseClass
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'drillbit/requests/base'
|
4
|
+
require 'drillbit/matchers/subdomain'
|
5
|
+
require 'drillbit/configuration'
|
6
|
+
|
7
|
+
module Drillbit
|
8
|
+
module Matchers
|
9
|
+
RSpec.describe Subdomain do
|
10
|
+
before(:each) do
|
11
|
+
Drillbit.configuration.allowed_subdomains = %w{api}
|
12
|
+
Drillbit.configuration.allowed_api_subdomains = %w{api}
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'matches if the subdomain is API' do
|
16
|
+
env = { 'HTTP_HOST' => 'api.example.com' }
|
17
|
+
request = Requests::Base.resolve(env)
|
18
|
+
matcher = Subdomain.new
|
19
|
+
|
20
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'matches if the first subdomain is API' do
|
24
|
+
env = { 'HTTP_HOST' => 'api.westeros.example.com' }
|
25
|
+
request = Requests::Base.resolve(env)
|
26
|
+
matcher = Subdomain.new
|
27
|
+
|
28
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'does not match if the first subdomain is not API' do
|
32
|
+
env = { 'HTTP_HOST' => 'westeros.example.com' }
|
33
|
+
request = Requests::Base.resolve(env)
|
34
|
+
matcher = Subdomain.new
|
35
|
+
|
36
|
+
expect(matcher.matches?(request)).to be_a FalseClass
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'allows the matched subdomain to be specified' do
|
40
|
+
env = { 'HTTP_HOST' => 'westeros.example.com' }
|
41
|
+
request = Requests::Base.resolve(env)
|
42
|
+
matcher = Subdomain.new(allowed_subdomains: 'westeros')
|
43
|
+
|
44
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows more than one subdomain to be matched' do
|
48
|
+
env = { 'HTTP_HOST' => 'westeros.example.com' }
|
49
|
+
request = Requests::Base.resolve(env)
|
50
|
+
matcher = Subdomain.new(allowed_subdomains: %w{api westeros})
|
51
|
+
|
52
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
53
|
+
|
54
|
+
env = { 'HTTP_HOST' => 'api.example.com' }
|
55
|
+
request = Requests::Base.resolve(env)
|
56
|
+
matcher = Subdomain.new(allowed_subdomains: %w{api westeros})
|
57
|
+
|
58
|
+
expect(matcher.matches?(request)).to be_a TrueClass
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'can match only the api subdomain' do
|
62
|
+
env = { 'HTTP_HOST' => 'westeros.example.com' }
|
63
|
+
request = Requests::Base.resolve(env)
|
64
|
+
matcher = Subdomain.new(allowed_api_subdomains: %w{westeros})
|
65
|
+
|
66
|
+
expect(matcher.matches_api_subdomain?(request)).to be_a TrueClass
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'matches "api" as an api subdomain by default' do
|
70
|
+
env = { 'HTTP_HOST' => 'api.example.com' }
|
71
|
+
request = Requests::Base.resolve(env)
|
72
|
+
matcher = Subdomain.new
|
73
|
+
|
74
|
+
expect(matcher.matches_api_subdomain?(request)).to be_a TrueClass
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|