endpoint-flux 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +36 -0
- data/CONTRIBUTING.md +18 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +37 -0
- data/README.md +607 -0
- data/circle.yml +14 -0
- data/endpoint_flux.gemspec +18 -0
- data/lib/endpoint_flux.rb +20 -0
- data/lib/endpoint_flux/class_loader.rb +58 -0
- data/lib/endpoint_flux/config.rb +85 -0
- data/lib/endpoint_flux/config/interceptor.rb +23 -0
- data/lib/endpoint_flux/config/middleware.rb +38 -0
- data/lib/endpoint_flux/config/rescue_from.rb +28 -0
- data/lib/endpoint_flux/endpoint.rb +81 -0
- data/lib/endpoint_flux/exceptions.rb +10 -0
- data/lib/endpoint_flux/exceptions/base.rb +21 -0
- data/lib/endpoint_flux/exceptions/forbidden.rb +12 -0
- data/lib/endpoint_flux/exceptions/not_found.rb +12 -0
- data/lib/endpoint_flux/exceptions/service_unavailable.rb +12 -0
- data/lib/endpoint_flux/exceptions/unauthorized.rb +12 -0
- data/lib/endpoint_flux/exceptions/validation.rb +13 -0
- data/lib/endpoint_flux/middlewares.rb +8 -0
- data/lib/endpoint_flux/middlewares/authenticator/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/authorizator/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/decorator/add_status.rb +12 -0
- data/lib/endpoint_flux/middlewares/decorator/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/policy/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/validator/empty.rb +12 -0
- data/lib/endpoint_flux/rails/concerns/endpoint_controller.rb +43 -0
- data/lib/endpoint_flux/request.rb +17 -0
- data/lib/endpoint_flux/response.rb +30 -0
- data/lib/endpoint_flux/version.rb +3 -0
- data/spec/lib/class_loader_spec.rb +31 -0
- data/spec/lib/config/default_middlewares_spec.rb +21 -0
- data/spec/lib/config/endpoints_namespace_spec.rb +13 -0
- data/spec/lib/config/flow_spec.rb +8 -0
- data/spec/lib/config/interceptor_spec.rb +34 -0
- data/spec/lib/config/middleware_spec.rb +62 -0
- data/spec/lib/config/rescue_from_spec.rb +45 -0
- data/spec/lib/endpoint/flow_spec.rb +43 -0
- data/spec/lib/endpoint/middlewares_spec.rb +110 -0
- data/spec/lib/endpoint/perform_spec.rb +61 -0
- data/spec/lib/endpoint/rescue_from_spec.rb +61 -0
- data/spec/lib/endpoint_flux/rails/concerns/endpoint_controller_spec.rb +75 -0
- data/spec/lib/endpoint_flux/request_spec.rb +44 -0
- data/spec/lib/exceptions/forbidden_spec.rb +12 -0
- data/spec/lib/exceptions/not_found_spec.rb +12 -0
- data/spec/lib/exceptions/service_unavailable_spec.rb +12 -0
- data/spec/lib/exceptions/unauthorized_spec.rb +12 -0
- data/spec/lib/exceptions/validation_spec.rb +14 -0
- data/spec/lib/middlewares/authenticator/skip_spec.rb +5 -0
- data/spec/lib/middlewares/authorizator/skip_spec.rb +5 -0
- data/spec/lib/middlewares/decorator/add_status_spec.rb +17 -0
- data/spec/lib/middlewares/decorator/skip_spec.rb +5 -0
- data/spec/lib/middlewares/policy/skip_spec.rb +5 -0
- data/spec/lib/middlewares/shared_examples.rb +19 -0
- data/spec/lib/middlewares/validator/empty_spec.rb +15 -0
- data/spec/lib/response_spec.rb +131 -0
- data/spec/spec_helper.rb +52 -0
- metadata +157 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Endpoint do
|
4
|
+
let(:klass) { class_double('Sample') }
|
5
|
+
|
6
|
+
before do
|
7
|
+
EndpointFlux.config EndpointFlux::Config.new
|
8
|
+
|
9
|
+
klass.include EndpointFlux::Endpoint
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'with exceptions' do
|
13
|
+
it 'fails with wrong string' do
|
14
|
+
klass.flow [:validator]
|
15
|
+
|
16
|
+
expect do
|
17
|
+
klass.validator 'some_not_existing_class'
|
18
|
+
end.to raise_error('You must provide block or existing klass')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'fails whit wrong class passed' do
|
22
|
+
stub_const 'EndpointFlux::Middlewares::Validator::SampleMiddleware', Class.new
|
23
|
+
|
24
|
+
klass.flow [:validator]
|
25
|
+
|
26
|
+
expect { klass.validator 'sample_middleware' }.to raise_error(
|
27
|
+
'The [EndpointFlux::Middlewares::Validator::SampleMiddleware] '\
|
28
|
+
'class should define perform class method'
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when wrong param passed' do
|
33
|
+
it do
|
34
|
+
klass.flow [:validator]
|
35
|
+
|
36
|
+
expect { klass.validator 1334 }.to raise_error(
|
37
|
+
'You must provide block or existing klass'
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
it do
|
42
|
+
stub_const 'SampleMiddleware', Class.new
|
43
|
+
|
44
|
+
klass.flow [:validator]
|
45
|
+
|
46
|
+
expect { klass.validator SampleMiddleware }.to raise_error(
|
47
|
+
'You must provide block or existing klass'
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'middlewares' do
|
54
|
+
before do
|
55
|
+
stub_const 'SomeNamespace::MiddlewareName::SampleMiddleware', Class.new
|
56
|
+
SomeNamespace::MiddlewareName::SampleMiddleware.class_eval do
|
57
|
+
def self.perform(*args)
|
58
|
+
args
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
EndpointFlux.config.middlewares_namespaces << 'some_namespace'
|
63
|
+
end
|
64
|
+
|
65
|
+
before do
|
66
|
+
klass.flow [:middleware_name]
|
67
|
+
end
|
68
|
+
|
69
|
+
let(:middleware) { klass.middleware_name.first }
|
70
|
+
|
71
|
+
it 'sets middleware with options' do
|
72
|
+
klass.middleware_name 'sample_middleware', some: :option
|
73
|
+
|
74
|
+
expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
|
75
|
+
expect(middleware.options).to eq(some: :option)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'sets middleware' do
|
79
|
+
klass.middleware_name 'sample_middleware'
|
80
|
+
|
81
|
+
expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'does not add twice' do
|
85
|
+
klass.middleware_name 'sample_middleware'
|
86
|
+
klass.middleware_name 'sample_middleware'
|
87
|
+
|
88
|
+
middleware = klass.middleware_name.first
|
89
|
+
|
90
|
+
expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'block' do
|
94
|
+
let(:block) { proc {} }
|
95
|
+
|
96
|
+
it 'sets middleware' do
|
97
|
+
klass.middleware_name(&block)
|
98
|
+
|
99
|
+
expect(middleware.handler).to be == block
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'does not adds twice' do
|
103
|
+
klass.middleware_name(&block)
|
104
|
+
klass.middleware_name(&block)
|
105
|
+
|
106
|
+
expect(middleware.handler).to be == block
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Endpoint do
|
4
|
+
let(:klass) { stub_const 'Sample', Class.new }
|
5
|
+
let(:middleware_request) { EndpointFlux::Request.new(headers: {}, params: params) }
|
6
|
+
let(:middleware_response) { EndpointFlux::Response.new }
|
7
|
+
|
8
|
+
before do
|
9
|
+
EndpointFlux.config EndpointFlux::Config.new
|
10
|
+
|
11
|
+
klass.include EndpointFlux::Endpoint
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#perform' do
|
15
|
+
before do
|
16
|
+
stub_const 'EndpointFlux::Middlewares::Validator::SampleValidator', Class.new
|
17
|
+
EndpointFlux::Middlewares::Validator::SampleValidator.class_eval do
|
18
|
+
def self.perform(request, response, _)
|
19
|
+
request.params = {}
|
20
|
+
[request, response, {}]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:params) { { some: :val } }
|
26
|
+
|
27
|
+
it 'checks if middleware exists' do
|
28
|
+
klass.flow [:validator]
|
29
|
+
|
30
|
+
expect { klass.perform(middleware_request) }
|
31
|
+
.to raise_error('No middleware registred for [:validator]')
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'middleware passed as string' do
|
35
|
+
it 'runs middleware passed as string' do
|
36
|
+
klass.flow [:validator]
|
37
|
+
klass.validator 'sample_validator'
|
38
|
+
|
39
|
+
request, response = klass.perform(middleware_request)
|
40
|
+
|
41
|
+
expect(request.params).to eq({})
|
42
|
+
expect(response.body).to eq({})
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'default middleware' do
|
47
|
+
before do
|
48
|
+
klass.flow [:validator]
|
49
|
+
|
50
|
+
EndpointFlux.config.default_middlewares :validator, 'sample_validator'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'uses default if not defined' do
|
54
|
+
request, response = klass.perform(middleware_request)
|
55
|
+
|
56
|
+
expect(request.params).to eq({})
|
57
|
+
expect(response.body).to eq({})
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Endpoint do
|
4
|
+
let(:klass) { stub_const 'Sample', Class.new }
|
5
|
+
let(:middleware_request) { EndpointFlux::Request.new(headers: {}, params: {}) }
|
6
|
+
let(:middleware_response) { EndpointFlux::Response.new }
|
7
|
+
|
8
|
+
before do
|
9
|
+
EndpointFlux.config EndpointFlux::Config.new
|
10
|
+
|
11
|
+
klass.include EndpointFlux::Endpoint
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#rescue_from' do
|
15
|
+
let(:sample_exception) { stub_const 'SampleException', Class.new(Exception) }
|
16
|
+
let!(:sample_validator) do
|
17
|
+
stub_const 'EndpointFlux::Middlewares::Validator::Sample', Class.new
|
18
|
+
EndpointFlux::Middlewares::Validator::Sample.class_eval do
|
19
|
+
def self.perform(*)
|
20
|
+
raise SampleException, 'bla bla'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
EndpointFlux::Middlewares::Validator::Sample
|
24
|
+
end
|
25
|
+
let!(:sample_decorator) do
|
26
|
+
stub_const 'EndpointFlux::Middlewares::Decorator::Sample', Class.new
|
27
|
+
EndpointFlux::Middlewares::Decorator::Sample.class_eval do
|
28
|
+
def self.perform(request, response, options)
|
29
|
+
response.body[:decorator] = true
|
30
|
+
[request, response, options]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
EndpointFlux::Middlewares::Decorator::Sample
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'fails if exception not found' do
|
37
|
+
expect do
|
38
|
+
EndpointFlux.config.rescue_from 'NonExsistingClasss' do |_, attrs|
|
39
|
+
# code
|
40
|
+
end
|
41
|
+
end.to raise_error('The [NonExsistingClasss] should be a string representing a class')
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'default middleware' do
|
45
|
+
before do
|
46
|
+
klass.flow %i[validator decorator]
|
47
|
+
klass.validator 'sample'
|
48
|
+
klass.decorator 'sample'
|
49
|
+
|
50
|
+
EndpointFlux.config.rescue_from sample_exception do |_, attrs|
|
51
|
+
[attrs[0], attrs[1], { status: false }]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'uses default if not defined' do
|
56
|
+
_, response = klass.perform(middleware_request)
|
57
|
+
expect(response.body[:status]).to be_falsey
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module Concern ; end
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'spec_helper'
|
6
|
+
require 'endpoint_flux/rails/concerns/endpoint_controller'
|
7
|
+
require 'ostruct'
|
8
|
+
|
9
|
+
class RemoteIpDummyClass
|
10
|
+
include EndpointFlux::Rails::Concerns::EndpointController
|
11
|
+
|
12
|
+
def headers
|
13
|
+
{}
|
14
|
+
end
|
15
|
+
|
16
|
+
def request
|
17
|
+
OpenStruct.new(
|
18
|
+
headers: { 'authorization' => 'authorization header' },
|
19
|
+
remote_ip: '172.18.0.1',
|
20
|
+
env: { 'HTTP_X_FORWARDED_FOR' => '172.18.0.2' }
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class LocalIpDummyClass
|
26
|
+
include EndpointFlux::Rails::Concerns::EndpointController
|
27
|
+
|
28
|
+
def headers
|
29
|
+
{}
|
30
|
+
end
|
31
|
+
|
32
|
+
def request
|
33
|
+
OpenStruct.new(
|
34
|
+
headers: { 'authorization' => 'authorization header' },
|
35
|
+
remote_ip: '127.0.0.1',
|
36
|
+
env: { 'HTTP_X_FORWARDED_FOR' => '172.18.0.2' }
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
RSpec.describe EndpointFlux::Rails::Concerns::EndpointController do
|
42
|
+
describe '#request_object' do
|
43
|
+
before do
|
44
|
+
allow(subject).to receive(:endpoint_params).and_return({})
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'remote ip' do
|
48
|
+
subject { RemoteIpDummyClass.new }
|
49
|
+
|
50
|
+
it 'sets property as remote_ip' do
|
51
|
+
expect(
|
52
|
+
::EndpointFlux::Request
|
53
|
+
).to receive(:new).with(headers: { 'Authorization' => 'authorization header' },
|
54
|
+
params: subject.endpoint_params,
|
55
|
+
remote_ip: subject.request.remote_ip)
|
56
|
+
|
57
|
+
subject.request_object
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'local ip' do
|
62
|
+
subject { LocalIpDummyClass.new }
|
63
|
+
|
64
|
+
it 'sets property as HTTP_X_FORWARDED_FOR' do
|
65
|
+
expect(
|
66
|
+
::EndpointFlux::Request
|
67
|
+
).to receive(:new).with(headers: { 'Authorization' => 'authorization header' },
|
68
|
+
params: subject.endpoint_params,
|
69
|
+
remote_ip: subject.request.env['HTTP_X_FORWARDED_FOR'])
|
70
|
+
|
71
|
+
subject.request_object
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Request do
|
4
|
+
it { should respond_to :headers }
|
5
|
+
it { should respond_to :remote_ip }
|
6
|
+
it { should respond_to :params }
|
7
|
+
it { should respond_to :namespace }
|
8
|
+
it { should respond_to :endpoint }
|
9
|
+
it { should respond_to :scope }
|
10
|
+
|
11
|
+
describe '#initialize' do
|
12
|
+
context 'when all params specified' do
|
13
|
+
let(:params) { { param: :val } }
|
14
|
+
let(:headers) { { header: :val } }
|
15
|
+
let(:remote_ip) { '127.0.0.1' }
|
16
|
+
let(:namespace) { 'namespace' }
|
17
|
+
|
18
|
+
it 'should set args' do
|
19
|
+
request = EndpointFlux::Request.new(
|
20
|
+
params: params,
|
21
|
+
headers: headers,
|
22
|
+
remote_ip: remote_ip,
|
23
|
+
namespace: namespace
|
24
|
+
)
|
25
|
+
|
26
|
+
expect(request.params).to eq params
|
27
|
+
expect(request.headers).to eq headers
|
28
|
+
expect(request.remote_ip).to eq remote_ip
|
29
|
+
expect(request.namespace).to eq namespace
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when params missed' do
|
33
|
+
it 'should set default values' do
|
34
|
+
request = EndpointFlux::Request.new
|
35
|
+
|
36
|
+
expect(request.params).to be_empty
|
37
|
+
expect(request.headers).to be_empty
|
38
|
+
expect(request.remote_ip).to eq ''
|
39
|
+
expect(request.namespace).to be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Exceptions::Validation do
|
4
|
+
describe '#to_hash' do
|
5
|
+
let(:messages) { {name: 'not valid'} }
|
6
|
+
it 'returns correct hash' do
|
7
|
+
expect(EndpointFlux::Exceptions::Validation.new(messages).to_hash).to eq(
|
8
|
+
status: 422,
|
9
|
+
message: 'validation errors',
|
10
|
+
errors: messages
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
RSpec.describe EndpointFlux::Middlewares::Decorator::AddStatus do
|
2
|
+
describe '#perform' do
|
3
|
+
let(:params) { { some: 'value' } }
|
4
|
+
let(:body) { { status: 200 } }
|
5
|
+
let(:request) { EndpointFlux::Request.new(headers: {}, params: params) }
|
6
|
+
let(:response) { EndpointFlux::Response.new(headers: {}, body: body) }
|
7
|
+
|
8
|
+
it 'returns response with status in body' do
|
9
|
+
middleware_request, middleware_response = subject.perform(request, response, {})
|
10
|
+
|
11
|
+
expect(middleware_request.headers).to eq({})
|
12
|
+
expect(middleware_request.params).to eq(params)
|
13
|
+
expect(middleware_response.headers).to eq({})
|
14
|
+
expect(middleware_response.body).to eq(body)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|