shark-on-lambda 0.6.10 → 1.0.0.rc1
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/.github/workflows/push-gem.yml +67 -0
- data/.github/workflows/tests.yml +32 -0
- data/README.md +10 -12
- data/changelog.md +11 -0
- data/gems.locked +73 -23
- data/lib/shark_on_lambda/api_gateway_handler.rb +61 -0
- data/lib/shark_on_lambda/application.rb +17 -0
- data/lib/shark_on_lambda/base_controller.rb +50 -0
- data/lib/shark_on_lambda/configuration.rb +9 -1
- data/lib/shark_on_lambda/dispatcher.rb +26 -0
- data/lib/shark_on_lambda/errors/base.rb +47 -0
- data/lib/shark_on_lambda/errors/base_serializer.rb +18 -0
- data/lib/shark_on_lambda/jsonapi_controller.rb +29 -0
- data/lib/shark_on_lambda/jsonapi_parameters.rb +66 -0
- data/lib/shark_on_lambda/jsonapi_renderer.rb +115 -0
- data/lib/shark_on_lambda/middleware/base.rb +23 -0
- data/lib/shark_on_lambda/middleware/jsonapi_rescuer.rb +31 -0
- data/lib/shark_on_lambda/middleware/rescuer.rb +38 -0
- data/lib/shark_on_lambda/query.rb +67 -0
- data/lib/shark_on_lambda/rack_adapters/api_gateway.rb +127 -0
- data/lib/shark_on_lambda/request.rb +9 -0
- data/lib/shark_on_lambda/response.rb +6 -0
- data/lib/shark_on_lambda/rspec/env_builder.rb +64 -0
- data/lib/shark_on_lambda/rspec/helpers.rb +84 -0
- data/lib/shark_on_lambda/rspec/jsonapi_helpers.rb +27 -0
- data/lib/shark_on_lambda/version.rb +1 -1
- data/lib/shark_on_lambda.rb +25 -28
- data/shark-on-lambda.gemspec +8 -3
- metadata +104 -24
- data/.gitlab-ci.yml +0 -39
- data/.travis.yml +0 -14
- data/lib/shark_on_lambda/api_gateway/base_controller.rb +0 -76
- data/lib/shark_on_lambda/api_gateway/base_handler.rb +0 -82
- data/lib/shark_on_lambda/api_gateway/concerns/http_response_validation.rb +0 -61
- data/lib/shark_on_lambda/api_gateway/errors.rb +0 -49
- data/lib/shark_on_lambda/api_gateway/headers.rb +0 -37
- data/lib/shark_on_lambda/api_gateway/jsonapi_controller.rb +0 -77
- data/lib/shark_on_lambda/api_gateway/jsonapi_parameters.rb +0 -68
- data/lib/shark_on_lambda/api_gateway/jsonapi_renderer.rb +0 -105
- data/lib/shark_on_lambda/api_gateway/parameters.rb +0 -18
- data/lib/shark_on_lambda/api_gateway/query.rb +0 -69
- data/lib/shark_on_lambda/api_gateway/request.rb +0 -148
- data/lib/shark_on_lambda/api_gateway/response.rb +0 -82
- data/lib/shark_on_lambda/api_gateway/serializers/base_error_serializer.rb +0 -20
- data/lib/shark_on_lambda/concerns/filter_actions.rb +0 -93
- data/lib/shark_on_lambda/tasks/build.rake +0 -146
- data/lib/shark_on_lambda/tasks.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9de95366ac135aebf072c6ecdbb5cae42b25f072bffdd1e01bee446e8262f17b
|
4
|
+
data.tar.gz: a09d5288e281447de50cfbbd8f97a18c023d9750e5d5b5ab456f4d6187b229a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz: '
|
6
|
+
metadata.gz: 9643f2cb448d20396f43ab9fd124e0aca1ae436773f1b29626ce44a644f12f6bd1477deb5c468a30b1992d824d1bf6049f8340705c11dde6a65432f1104bba38
|
7
|
+
data.tar.gz: '09d2eb6a2ffb09b969f3cd383a0f9a19ee6bd68fbf32b37ba1fc0acab488144dcf38d516788b421b601158d390e4eee162500c65efcb25e89f979ac4bb487c21'
|
@@ -0,0 +1,67 @@
|
|
1
|
+
name: Push Gem
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
tags:
|
5
|
+
- 'v*'
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
rspec:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
steps:
|
11
|
+
- uses: actions/checkout@v1
|
12
|
+
- name: Set up Ruby 2.5
|
13
|
+
uses: actions/setup-ruby@v1
|
14
|
+
with:
|
15
|
+
ruby-version: 2.5.x
|
16
|
+
- name: Run RSpec
|
17
|
+
run: |
|
18
|
+
gem install bundler
|
19
|
+
bundle install --jobs 4 --retry 3
|
20
|
+
bundle exec rspec
|
21
|
+
|
22
|
+
rubocop:
|
23
|
+
runs-on: ubuntu-latest
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v1
|
26
|
+
- name: Set up Ruby 2.5
|
27
|
+
uses: actions/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: 2.5.x
|
30
|
+
- name: Run rubocop
|
31
|
+
run: |
|
32
|
+
gem install bundler
|
33
|
+
bundle install --jobs 4 --retry 3
|
34
|
+
bundle exec rubocop
|
35
|
+
|
36
|
+
push-gem:
|
37
|
+
runs-on: ubuntu-latest
|
38
|
+
steps:
|
39
|
+
- uses: actions/checkout@master
|
40
|
+
- name: Set up Ruby 2.5
|
41
|
+
uses: actions/setup-ruby@v1
|
42
|
+
with:
|
43
|
+
ruby-version: 2.5.x
|
44
|
+
- name: Build gem
|
45
|
+
run: |
|
46
|
+
gem install bundler
|
47
|
+
bundle install --jobs 4 --retry 3
|
48
|
+
bundle exec rake build
|
49
|
+
- name: Push to GitHub Package Repository
|
50
|
+
run: |
|
51
|
+
mkdir -p $HOME/.gem
|
52
|
+
echo ":github: Bearer $GEM_HOST_API_KEY" >> $HOME/.gem/credentials
|
53
|
+
chmod 0600 $HOME/.gem/credentials
|
54
|
+
bundle exec rake build
|
55
|
+
gem push --key github --host https://rubygems.pkg.github.com/Skudo pkg/`ls -1t pkg | head -1`
|
56
|
+
env:
|
57
|
+
GEM_HOST_API_KEY: ${{secrets.GITHUB_AUTH_TOKEN}}
|
58
|
+
OWNER: username
|
59
|
+
- name: Push to RubyGems
|
60
|
+
run: |
|
61
|
+
mkdir -p $HOME/.gem
|
62
|
+
echo ":rubygems_api_key: $GEM_HOST_API_KEY" >> ~/.gem/credentials
|
63
|
+
chmod 0600 $HOME/.gem/credentials
|
64
|
+
bundle exec rake build
|
65
|
+
gem push pkg/`ls -1t pkg | head -1`
|
66
|
+
env:
|
67
|
+
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: Tests
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
rspec:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
steps:
|
9
|
+
- uses: actions/checkout@v1
|
10
|
+
- name: Set up Ruby 2.5
|
11
|
+
uses: actions/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: 2.5.x
|
14
|
+
- name: Run RSpec
|
15
|
+
run: |
|
16
|
+
gem install bundler
|
17
|
+
bundle install --jobs 4 --retry 3
|
18
|
+
bundle exec rspec
|
19
|
+
|
20
|
+
rubocop:
|
21
|
+
runs-on: ubuntu-latest
|
22
|
+
steps:
|
23
|
+
- uses: actions/checkout@v1
|
24
|
+
- name: Set up Ruby 2.5
|
25
|
+
uses: actions/setup-ruby@v1
|
26
|
+
with:
|
27
|
+
ruby-version: 2.5.x
|
28
|
+
- name: Run rubocop
|
29
|
+
run: |
|
30
|
+
gem install bundler
|
31
|
+
bundle install --jobs 4 --retry 3
|
32
|
+
bundle exec rubocop
|
data/README.md
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# shark-on-lambda
|
2
|
-
|
3
|
-
[](https://travis-ci.org/Skudo/shark-on-lambda)
|
2
|
+
[](https://github.com/Skudo/shark-on-lambda/actions)
|
4
3
|
[](https://codeclimate.com/github/Skudo/shark-on-lambda/maintainability)
|
5
4
|
|
6
5
|
`shark-on-lambda` provides a lightweight framework to write Ruby on AWS Lambda
|
@@ -24,8 +23,7 @@ maintaining a smaller memory footprint.
|
|
24
23
|
|
25
24
|
## Changelog
|
26
25
|
|
27
|
-
|
28
|
-
* Supports events from the API Gateway.
|
26
|
+
Have a look at the [actual changelog](changelog.md).
|
29
27
|
|
30
28
|
## Installation
|
31
29
|
|
@@ -50,11 +48,11 @@ are triggered by HTTP requests on the API Gateway. They also are responsible for
|
|
50
48
|
responding with a well-formed response to the caller.
|
51
49
|
|
52
50
|
```ruby
|
53
|
-
class MyHandler < SharkOnLambda::
|
51
|
+
class MyHandler < SharkOnLambda::BaseHandler
|
54
52
|
end
|
55
53
|
```
|
56
54
|
|
57
|
-
By inheriting from `SharkOnLambda::
|
55
|
+
By inheriting from `SharkOnLambda::BaseHandler`, your own handler
|
58
56
|
class is indirectly tied to your controller class by convention: It assumes
|
59
57
|
the controller name is `MyController` and it will dispatch events to that
|
60
58
|
controller.
|
@@ -63,7 +61,7 @@ If you however bring your own class with a different name, you can configure
|
|
63
61
|
your handler to use that controller instead:
|
64
62
|
|
65
63
|
```ruby
|
66
|
-
class MyHandler < SharkOnLambda::
|
64
|
+
class MyHandler < SharkOnLambda::BaseHandler
|
67
65
|
self.controller_class = AnotherController
|
68
66
|
end
|
69
67
|
```
|
@@ -72,7 +70,7 @@ All controller methods are going to be automagically mapped to class methods
|
|
72
70
|
on the handler class.
|
73
71
|
|
74
72
|
```ruby
|
75
|
-
class MyController < SharkOnLambda::
|
73
|
+
class MyController < SharkOnLambda::BaseController
|
76
74
|
def index
|
77
75
|
end
|
78
76
|
|
@@ -80,7 +78,7 @@ class MyController < SharkOnLambda::ApiGateway::BaseController
|
|
80
78
|
end
|
81
79
|
end
|
82
80
|
|
83
|
-
class MyHandler < SharkOnLambda::
|
81
|
+
class MyHandler < SharkOnLambda::BaseHandler
|
84
82
|
end
|
85
83
|
```
|
86
84
|
|
@@ -103,7 +101,7 @@ functions you may know from Rails and `render` does not really support multiple
|
|
103
101
|
renderers (yet).
|
104
102
|
|
105
103
|
```ruby
|
106
|
-
class MyController < SharkOnLambda::
|
104
|
+
class MyController < SharkOnLambda::BaseController
|
107
105
|
def index
|
108
106
|
# Make the API Gateway respond with a 201 response saying "Hello, World!"
|
109
107
|
# in the response body.
|
@@ -124,7 +122,7 @@ end
|
|
124
122
|
### _JSON API_-compliant controllers
|
125
123
|
|
126
124
|
If you inherit your controller from
|
127
|
-
`SharkOnLambda::
|
125
|
+
`SharkOnLambda::JsonapiController`, `render` and `redirect_to` will
|
128
126
|
create _JSON API_-compliant responses.
|
129
127
|
|
130
128
|
You however __must__ have a serialiser for the objects you want to render.
|
@@ -141,7 +139,7 @@ _JSON API_ compatibility. Therefore, we expect the serialisers to be inherited
|
|
141
139
|
from `::JSONAPI::Serializable::Resource` (or `::JSONAPI::Serializable::Error`).
|
142
140
|
|
143
141
|
```ruby
|
144
|
-
class SomethingSerializer <
|
142
|
+
class SomethingSerializer < JSONAPI::Serializable::Resource
|
145
143
|
type :somethings
|
146
144
|
|
147
145
|
attributes :foo, :bar, :baz
|
data/changelog.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## Changelog
|
2
2
|
|
3
|
+
#### Unreleaesed
|
4
|
+
|
5
|
+
- [Break] HTTP redirection now uses the status code `302`.
|
6
|
+
- [Break] Remove the `ApiGateway` namespace, move all items from that namespace up by one level.
|
7
|
+
- [Break] Remove build rake tasks.
|
8
|
+
- Added support for Rack-compatible middleware.
|
9
|
+
- `SharkOnLambda::BaseController` now acts more like `ActionController::BaseController`.
|
10
|
+
- Support `ActiveModel::Errors` nested validation errors.
|
11
|
+
- Added `SharkOnLambda::RSpec::Helpers` and `SharkOnLambda::RSpec::JsonapiHelpers`.
|
12
|
+
- Moved to GitHub.
|
13
|
+
|
3
14
|
#### 0.6.10
|
4
15
|
|
5
16
|
- Upgrade `rack` for good measure.
|
data/gems.locked
CHANGED
@@ -1,14 +1,29 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
shark-on-lambda (0.
|
4
|
+
shark-on-lambda (1.0.0.rc1)
|
5
|
+
actionpack
|
5
6
|
activesupport
|
6
7
|
jsonapi-rb
|
7
|
-
rack (>= 2.0.8)
|
8
|
+
rack (>= 2.0.8, < 3)
|
9
|
+
zeitwerk (~> 2.2)
|
8
10
|
|
9
11
|
GEM
|
10
12
|
remote: https://rubygems.org/
|
11
13
|
specs:
|
14
|
+
actionpack (6.0.0)
|
15
|
+
actionview (= 6.0.0)
|
16
|
+
activesupport (= 6.0.0)
|
17
|
+
rack (~> 2.0)
|
18
|
+
rack-test (>= 0.6.3)
|
19
|
+
rails-dom-testing (~> 2.0)
|
20
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
21
|
+
actionview (6.0.0)
|
22
|
+
activesupport (= 6.0.0)
|
23
|
+
builder (~> 3.1)
|
24
|
+
erubi (~> 1.4)
|
25
|
+
rails-dom-testing (~> 2.0)
|
26
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
12
27
|
activemodel (6.0.0)
|
13
28
|
activesupport (= 6.0.0)
|
14
29
|
activesupport (6.0.0)
|
@@ -18,14 +33,23 @@ GEM
|
|
18
33
|
tzinfo (~> 1.1)
|
19
34
|
zeitwerk (~> 2.1, >= 2.1.8)
|
20
35
|
ast (2.4.0)
|
36
|
+
builder (3.2.4)
|
37
|
+
byebug (11.0.1)
|
38
|
+
coderay (1.1.2)
|
39
|
+
colorize (0.8.1)
|
21
40
|
concurrent-ruby (1.1.5)
|
41
|
+
crass (1.0.6)
|
22
42
|
diff-lcs (1.3)
|
23
43
|
docile (1.3.2)
|
24
|
-
|
44
|
+
erubi (1.9.0)
|
45
|
+
factory_bot (5.1.1)
|
25
46
|
activesupport (>= 4.2.0)
|
26
|
-
|
47
|
+
fasterer (0.8.2)
|
48
|
+
colorize (~> 0.7)
|
49
|
+
ruby_parser (>= 3.14.1)
|
50
|
+
i18n (1.7.0)
|
27
51
|
concurrent-ruby (~> 1.0)
|
28
|
-
jaro_winkler (1.5.
|
52
|
+
jaro_winkler (1.5.4)
|
29
53
|
json (2.2.0)
|
30
54
|
jsonapi-deserializable (0.2.0)
|
31
55
|
jsonapi-rb (0.5.0)
|
@@ -34,27 +58,47 @@ GEM
|
|
34
58
|
jsonapi-renderer (0.2.2)
|
35
59
|
jsonapi-serializable (0.3.1)
|
36
60
|
jsonapi-renderer (~> 0.2.0)
|
37
|
-
|
38
|
-
|
39
|
-
|
61
|
+
loofah (2.4.0)
|
62
|
+
crass (~> 1.0.2)
|
63
|
+
nokogiri (>= 1.5.9)
|
64
|
+
method_source (0.9.2)
|
65
|
+
mini_portile2 (2.4.0)
|
66
|
+
minitest (5.13.0)
|
67
|
+
nokogiri (1.10.8)
|
68
|
+
mini_portile2 (~> 2.4.0)
|
69
|
+
parallel (1.18.0)
|
70
|
+
parser (2.6.5.0)
|
40
71
|
ast (~> 2.4.0)
|
41
|
-
|
72
|
+
pry (0.12.2)
|
73
|
+
coderay (~> 1.1.0)
|
74
|
+
method_source (~> 0.9.0)
|
75
|
+
pry-byebug (3.7.0)
|
76
|
+
byebug (~> 11.0)
|
77
|
+
pry (~> 0.10)
|
78
|
+
rack (2.2.2)
|
79
|
+
rack-test (1.1.0)
|
80
|
+
rack (>= 1.0, < 3)
|
81
|
+
rails-dom-testing (2.0.3)
|
82
|
+
activesupport (>= 4.2.0)
|
83
|
+
nokogiri (>= 1.6)
|
84
|
+
rails-html-sanitizer (1.3.0)
|
85
|
+
loofah (~> 2.3)
|
42
86
|
rainbow (3.0.0)
|
43
87
|
rake (13.0.0)
|
44
|
-
rspec (3.
|
45
|
-
rspec-core (~> 3.
|
46
|
-
rspec-expectations (~> 3.
|
47
|
-
rspec-mocks (~> 3.
|
48
|
-
rspec-core (3.
|
49
|
-
rspec-support (~> 3.
|
50
|
-
rspec-expectations (3.
|
88
|
+
rspec (3.9.0)
|
89
|
+
rspec-core (~> 3.9.0)
|
90
|
+
rspec-expectations (~> 3.9.0)
|
91
|
+
rspec-mocks (~> 3.9.0)
|
92
|
+
rspec-core (3.9.0)
|
93
|
+
rspec-support (~> 3.9.0)
|
94
|
+
rspec-expectations (3.9.0)
|
51
95
|
diff-lcs (>= 1.2.0, < 2.0)
|
52
|
-
rspec-support (~> 3.
|
53
|
-
rspec-mocks (3.
|
96
|
+
rspec-support (~> 3.9.0)
|
97
|
+
rspec-mocks (3.9.0)
|
54
98
|
diff-lcs (>= 1.2.0, < 2.0)
|
55
|
-
rspec-support (~> 3.
|
56
|
-
rspec-support (3.
|
57
|
-
rubocop (0.
|
99
|
+
rspec-support (~> 3.9.0)
|
100
|
+
rspec-support (3.9.0)
|
101
|
+
rubocop (0.76.0)
|
58
102
|
jaro_winkler (~> 1.5.1)
|
59
103
|
parallel (~> 1.10)
|
60
104
|
parser (>= 2.6)
|
@@ -62,6 +106,9 @@ GEM
|
|
62
106
|
ruby-progressbar (~> 1.7)
|
63
107
|
unicode-display_width (>= 1.4.0, < 1.7)
|
64
108
|
ruby-progressbar (1.10.1)
|
109
|
+
ruby_parser (3.14.2)
|
110
|
+
sexp_processor (~> 4.9)
|
111
|
+
sexp_processor (4.14.1)
|
65
112
|
simplecov (0.17.1)
|
66
113
|
docile (~> 1.1)
|
67
114
|
json (>= 1.8, < 3)
|
@@ -72,7 +119,7 @@ GEM
|
|
72
119
|
thread_safe (~> 0.1)
|
73
120
|
unicode-display_width (1.6.0)
|
74
121
|
yard (0.9.20)
|
75
|
-
zeitwerk (2.1
|
122
|
+
zeitwerk (2.2.1)
|
76
123
|
|
77
124
|
PLATFORMS
|
78
125
|
ruby
|
@@ -81,6 +128,9 @@ DEPENDENCIES
|
|
81
128
|
activemodel
|
82
129
|
bundler
|
83
130
|
factory_bot
|
131
|
+
fasterer
|
132
|
+
pry
|
133
|
+
pry-byebug
|
84
134
|
rake
|
85
135
|
rspec
|
86
136
|
rubocop
|
@@ -89,4 +139,4 @@ DEPENDENCIES
|
|
89
139
|
yard
|
90
140
|
|
91
141
|
BUNDLED WITH
|
92
|
-
2.1.
|
142
|
+
2.1.4
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SharkOnLambda
|
4
|
+
class ApiGatewayHandler
|
5
|
+
class << self
|
6
|
+
attr_writer :controller_class_name
|
7
|
+
|
8
|
+
def controller_action?(action)
|
9
|
+
controller_actions.include?(action.to_sym)
|
10
|
+
end
|
11
|
+
|
12
|
+
def controller_class_name
|
13
|
+
return @controller_class_name if defined?(@controller_class_name)
|
14
|
+
|
15
|
+
name_inferrer = Inferrers::NameInferrer.from_handler_name(name)
|
16
|
+
@controller_class_name = name_inferrer.controller
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def controller_actions
|
22
|
+
return [] if controller_class.nil?
|
23
|
+
|
24
|
+
controller_class.public_instance_methods(false)
|
25
|
+
end
|
26
|
+
|
27
|
+
def controller_class
|
28
|
+
controller_class_name.safe_constantize
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(action, *args, &_block)
|
32
|
+
return super unless respond_to_missing?(action)
|
33
|
+
|
34
|
+
new.call(action, *args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def respond_to_missing?(name, _include_all = false)
|
38
|
+
controller_action?(name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :application, :env
|
43
|
+
delegate :context, :event, to: :adapter
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
@application = Application.new
|
47
|
+
end
|
48
|
+
|
49
|
+
def call(action, event:, context:)
|
50
|
+
raise NoMethodError unless self.class.controller_action?(action)
|
51
|
+
|
52
|
+
adapter = RackAdapters::ApiGateway.new(context: context, event: event)
|
53
|
+
env = adapter.env
|
54
|
+
env['shark.controller'] = self.class.controller_class_name
|
55
|
+
env['shark.action'] = action.to_s
|
56
|
+
|
57
|
+
status, headers, body = @application.call(env)
|
58
|
+
adapter.build_response(status, headers, body)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SharkOnLambda
|
4
|
+
class Application
|
5
|
+
def call(env)
|
6
|
+
dup.send('_call', env)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def _call(env)
|
12
|
+
dispatcher = SharkOnLambda.config.dispatcher
|
13
|
+
middleware_stack = SharkOnLambda.config.middleware.build(dispatcher)
|
14
|
+
middleware_stack.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SharkOnLambda
|
4
|
+
class BaseController < ActionController::Metal
|
5
|
+
EXCLUDED_MODULES = [
|
6
|
+
AbstractController::Translation,
|
7
|
+
AbstractController::AssetPaths,
|
8
|
+
|
9
|
+
ActionController::UrlFor,
|
10
|
+
ActionController::ConditionalGet,
|
11
|
+
ActionController::EtagWithTemplateDigest,
|
12
|
+
ActionController::EtagWithFlash,
|
13
|
+
ActionController::Caching,
|
14
|
+
ActionController::MimeResponds,
|
15
|
+
ActionController::ImplicitRender,
|
16
|
+
ActionController::Cookies,
|
17
|
+
ActionController::Flash,
|
18
|
+
ActionController::FormBuilder,
|
19
|
+
ActionController::RequestForgeryProtection,
|
20
|
+
ActionController::ContentSecurityPolicy,
|
21
|
+
ActionController::ForceSSL,
|
22
|
+
ActionController::HttpAuthentication::Basic::ControllerMethods,
|
23
|
+
ActionController::HttpAuthentication::Digest::ControllerMethods,
|
24
|
+
ActionController::HttpAuthentication::Token::ControllerMethods,
|
25
|
+
ActionView::Layouts
|
26
|
+
].freeze
|
27
|
+
ActionController::Base.without_modules(EXCLUDED_MODULES).each do |mod|
|
28
|
+
include mod
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.dispatch(*)
|
32
|
+
super
|
33
|
+
rescue AbstractController::ActionNotFound,
|
34
|
+
AbstractController::DoubleRenderError,
|
35
|
+
ActionController::ActionControllerError => e
|
36
|
+
raise Errors[500], e.message
|
37
|
+
end
|
38
|
+
|
39
|
+
def redirect_to(*)
|
40
|
+
super
|
41
|
+
self.response_body = '' if no_body?
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def no_body?
|
47
|
+
response.status.in?(Response::NO_CONTENT_CODES)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -4,7 +4,7 @@ module SharkOnLambda
|
|
4
4
|
class Configuration < OpenStruct
|
5
5
|
include Concerns::ResettableSingleton
|
6
6
|
|
7
|
-
attr_writer :stage
|
7
|
+
attr_writer :dispatcher, :stage
|
8
8
|
|
9
9
|
class << self
|
10
10
|
include Concerns::YamlConfigLoader
|
@@ -56,6 +56,14 @@ module SharkOnLambda
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
def dispatcher
|
60
|
+
@dispatcher ||= Dispatcher.new
|
61
|
+
end
|
62
|
+
|
63
|
+
def middleware
|
64
|
+
@middleware ||= ActionDispatch::MiddlewareStack.new
|
65
|
+
end
|
66
|
+
|
59
67
|
def root
|
60
68
|
@root ||= Pathname.new('.')
|
61
69
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SharkOnLambda
|
4
|
+
class Dispatcher
|
5
|
+
def call(env)
|
6
|
+
request = Request.new(env)
|
7
|
+
response = Response.new
|
8
|
+
|
9
|
+
controller = controller_class(env)
|
10
|
+
action = controller_action(env)
|
11
|
+
controller.dispatch(action, request, response)
|
12
|
+
|
13
|
+
response.prepare!
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def controller_action(env)
|
19
|
+
env['shark.action']
|
20
|
+
end
|
21
|
+
|
22
|
+
def controller_class(env)
|
23
|
+
env['shark.controller'].camelize.constantize
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SharkOnLambda
|
4
|
+
module Errors
|
5
|
+
class Base < StandardError
|
6
|
+
attr_accessor :id, :code, :meta, :pointer, :parameter
|
7
|
+
attr_writer :detail
|
8
|
+
|
9
|
+
def self.status(status_code)
|
10
|
+
define_method :status do
|
11
|
+
status_code
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def detail
|
16
|
+
return @detail if @detail.present?
|
17
|
+
return nil if message == self.class.name
|
18
|
+
|
19
|
+
message
|
20
|
+
end
|
21
|
+
|
22
|
+
def title
|
23
|
+
Rack::Utils::HTTP_STATUS_CODES[status]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.[](status_code)
|
28
|
+
@errors[status_code]
|
29
|
+
end
|
30
|
+
|
31
|
+
@errors = Rack::Utils::HTTP_STATUS_CODES.map do |status_code, message|
|
32
|
+
next unless (400..599).cover?(status_code) && message.present?
|
33
|
+
|
34
|
+
error_class = Class.new(Base) do
|
35
|
+
status status_code
|
36
|
+
end
|
37
|
+
class_name_parts = message.to_s.split(/\s+/)
|
38
|
+
class_name_parts.map! { |word| word.gsub(/[^a-z]/i, '').capitalize }
|
39
|
+
class_name = class_name_parts.join('')
|
40
|
+
const_set(class_name, error_class)
|
41
|
+
|
42
|
+
[status_code, error_class]
|
43
|
+
end
|
44
|
+
@errors.compact!
|
45
|
+
@errors = @errors.to_h
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SharkOnLambda
|
4
|
+
module Errors
|
5
|
+
class BaseSerializer < JSONAPI::Serializable::Error
|
6
|
+
id { @object.id }
|
7
|
+
status { @object.status }
|
8
|
+
code { @object.code }
|
9
|
+
title { @object.title }
|
10
|
+
detail { @object.detail }
|
11
|
+
meta { @object.meta }
|
12
|
+
source do
|
13
|
+
pointer @object.pointer if @object.pointer.present?
|
14
|
+
parameter @object.parameter if @object.parameter.present?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SharkOnLambda
|
4
|
+
class JsonapiController < BaseController
|
5
|
+
ActionController::Renderers.add :jsonapi do |object, options|
|
6
|
+
response.set_header('content-type', 'application/vnd.api+json')
|
7
|
+
return { data: {} }.to_json if object.nil?
|
8
|
+
|
9
|
+
jsonapi_params = JsonapiParameters.new(params)
|
10
|
+
jsonapi_renderer = JsonapiRenderer.new
|
11
|
+
render_options = jsonapi_params.to_h.deep_merge(options)
|
12
|
+
|
13
|
+
jsonapi_renderer.render(object, render_options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def redirect_to(options = {}, response_status = {})
|
17
|
+
super
|
18
|
+
return if response_status[:status] == 304
|
19
|
+
|
20
|
+
self.response_body = { data: {} }.to_json
|
21
|
+
end
|
22
|
+
|
23
|
+
def render(object, options = {})
|
24
|
+
options.merge!(jsonapi: object, content_type: 'application/vnd.api+json')
|
25
|
+
|
26
|
+
super(options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|