shark-on-lambda 1.0.0.rc2 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -3
  3. data/.rubocop.yml +4 -0
  4. data/README.md +70 -17
  5. data/changelog.md +17 -1
  6. data/doc/upgrade-from-0.6.x-to-1.x.md +122 -0
  7. data/lib/shark-on-lambda.rb +9 -0
  8. data/lib/shark_on_lambda.rb +10 -50
  9. data/lib/shark_on_lambda/api_gateway_handler.rb +3 -55
  10. data/lib/shark_on_lambda/application.rb +73 -5
  11. data/lib/shark_on_lambda/base_controller.rb +29 -9
  12. data/lib/shark_on_lambda/configuration.rb +1 -65
  13. data/lib/shark_on_lambda/inferrers/serializer_inferrer.rb +10 -7
  14. data/lib/shark_on_lambda/jsonapi_renderer.rb +16 -10
  15. data/lib/shark_on_lambda/middleware/base.rb +2 -4
  16. data/lib/shark_on_lambda/middleware/honeybadger.rb +45 -0
  17. data/lib/shark_on_lambda/middleware/jsonapi_rescuer.rb +21 -1
  18. data/lib/shark_on_lambda/middleware/lambda_logger.rb +8 -16
  19. data/lib/shark_on_lambda/rake_tasks.rb +16 -0
  20. data/lib/shark_on_lambda/request.rb +0 -3
  21. data/lib/shark_on_lambda/rspec/env_builder.rb +73 -31
  22. data/lib/shark_on_lambda/rspec/helpers.rb +5 -74
  23. data/lib/shark_on_lambda/rspec/request_helpers.rb +63 -0
  24. data/lib/shark_on_lambda/rspec/{jsonapi_helpers.rb → response_helpers.rb} +4 -6
  25. data/lib/shark_on_lambda/version.rb +1 -1
  26. data/shark-on-lambda.gemspec +7 -5
  27. metadata +32 -38
  28. data/gems.locked +0 -142
  29. data/lib/shark_on_lambda/concerns/resettable_singleton.rb +0 -18
  30. data/lib/shark_on_lambda/concerns/yaml_config_loader.rb +0 -28
  31. data/lib/shark_on_lambda/dispatcher.rb +0 -26
  32. data/lib/shark_on_lambda/inferrers/name_inferrer.rb +0 -66
  33. data/lib/shark_on_lambda/jsonapi_controller.rb +0 -29
  34. data/lib/shark_on_lambda/middleware/rescuer.rb +0 -38
  35. data/lib/shark_on_lambda/query.rb +0 -67
  36. data/lib/shark_on_lambda/rack_adapters/api_gateway.rb +0 -127
  37. data/lib/shark_on_lambda/secrets.rb +0 -43
@@ -1,142 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- shark-on-lambda (1.0.0.rc2)
5
- actionpack
6
- activesupport
7
- jsonapi-rb
8
- rack (>= 2.0.8, < 3)
9
- zeitwerk (~> 2.2)
10
-
11
- GEM
12
- remote: https://rubygems.org/
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)
27
- activemodel (6.0.0)
28
- activesupport (= 6.0.0)
29
- activesupport (6.0.0)
30
- concurrent-ruby (~> 1.0, >= 1.0.2)
31
- i18n (>= 0.7, < 2)
32
- minitest (~> 5.1)
33
- tzinfo (~> 1.1)
34
- zeitwerk (~> 2.1, >= 2.1.8)
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)
40
- concurrent-ruby (1.1.5)
41
- crass (1.0.6)
42
- diff-lcs (1.3)
43
- docile (1.3.2)
44
- erubi (1.9.0)
45
- factory_bot (5.1.1)
46
- activesupport (>= 4.2.0)
47
- fasterer (0.8.2)
48
- colorize (~> 0.7)
49
- ruby_parser (>= 3.14.1)
50
- i18n (1.7.0)
51
- concurrent-ruby (~> 1.0)
52
- jaro_winkler (1.5.4)
53
- json (2.2.0)
54
- jsonapi-deserializable (0.2.0)
55
- jsonapi-rb (0.5.0)
56
- jsonapi-deserializable (~> 0.2.0)
57
- jsonapi-serializable (~> 0.3.0)
58
- jsonapi-renderer (0.2.2)
59
- jsonapi-serializable (0.3.1)
60
- jsonapi-renderer (~> 0.2.0)
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)
71
- ast (~> 2.4.0)
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)
86
- rainbow (3.0.0)
87
- rake (13.0.0)
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)
95
- diff-lcs (>= 1.2.0, < 2.0)
96
- rspec-support (~> 3.9.0)
97
- rspec-mocks (3.9.0)
98
- diff-lcs (>= 1.2.0, < 2.0)
99
- rspec-support (~> 3.9.0)
100
- rspec-support (3.9.0)
101
- rubocop (0.76.0)
102
- jaro_winkler (~> 1.5.1)
103
- parallel (~> 1.10)
104
- parser (>= 2.6)
105
- rainbow (>= 2.2.2, < 4.0)
106
- ruby-progressbar (~> 1.7)
107
- unicode-display_width (>= 1.4.0, < 1.7)
108
- ruby-progressbar (1.10.1)
109
- ruby_parser (3.14.2)
110
- sexp_processor (~> 4.9)
111
- sexp_processor (4.14.1)
112
- simplecov (0.17.1)
113
- docile (~> 1.1)
114
- json (>= 1.8, < 3)
115
- simplecov-html (~> 0.10.0)
116
- simplecov-html (0.10.2)
117
- thread_safe (0.3.6)
118
- tzinfo (1.2.5)
119
- thread_safe (~> 0.1)
120
- unicode-display_width (1.6.0)
121
- yard (0.9.20)
122
- zeitwerk (2.2.1)
123
-
124
- PLATFORMS
125
- ruby
126
-
127
- DEPENDENCIES
128
- activemodel
129
- bundler
130
- factory_bot
131
- fasterer
132
- pry
133
- pry-byebug
134
- rake
135
- rspec
136
- rubocop
137
- shark-on-lambda!
138
- simplecov
139
- yard
140
-
141
- BUNDLED WITH
142
- 2.1.4
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharkOnLambda
4
- module Concerns
5
- module ResettableSingleton
6
- def self.included(base)
7
- base.include(Singleton)
8
- base.extend(ClassMethods)
9
- end
10
-
11
- module ClassMethods
12
- def reset
13
- @singleton__instance__ = nil
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharkOnLambda
4
- module Concerns
5
- module YamlConfigLoader
6
- def load_yaml_files(stage:, fallback: :default, paths:)
7
- result = HashWithIndifferentAccess.new
8
- paths.each do |path|
9
- data = load_yaml_file(stage: stage, fallback: fallback, path: path)
10
- result.deep_merge!(data)
11
- end
12
- result
13
- end
14
-
15
- protected
16
-
17
- def load_yaml_file(stage:, fallback:, path:)
18
- return {} unless File.exist?(path)
19
-
20
- data = YAML.load_file(path)
21
- return {} unless data.is_a?(Hash)
22
-
23
- data = data.with_indifferent_access
24
- data[stage] || data[fallback] || {}
25
- end
26
- end
27
- end
28
- end
@@ -1,26 +0,0 @@
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
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharkOnLambda
4
- module Inferrers
5
- class NameInferrer
6
- class << self
7
- def from_controller_name(class_name)
8
- from_name(:controller, class_name)
9
- end
10
-
11
- def from_deserializer_name(class_name)
12
- from_name(:deserializer, class_name)
13
- end
14
-
15
- def from_handler_name(class_name)
16
- from_name(:handler, class_name)
17
- end
18
-
19
- def from_model_name(class_name)
20
- from_name(:model, class_name)
21
- end
22
-
23
- def from_serializer_name(class_name)
24
- from_name(:serializer, class_name)
25
- end
26
-
27
- protected
28
-
29
- def from_name(type, class_name)
30
- base = class_name.underscore
31
- base = case type
32
- when :controller, :deserializer, :handler, :serializer
33
- base.sub(/_#{type}\z/, '')
34
- when :model
35
- base
36
- end
37
- new(base)
38
- end
39
- end
40
-
41
- def initialize(base)
42
- @base = base
43
- end
44
-
45
- def controller
46
- "#{@base}_controller".camelize
47
- end
48
-
49
- def deserializer
50
- "#{@base}_deserializer".camelize
51
- end
52
-
53
- def handler
54
- "#{@base}_handler".camelize
55
- end
56
-
57
- def model
58
- @base.camelize
59
- end
60
-
61
- def serializer
62
- "#{@base}_serializer".camelize
63
- end
64
- end
65
- end
66
- end
@@ -1,29 +0,0 @@
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
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharkOnLambda
4
- module Middleware
5
- class Rescuer < Base
6
- private
7
-
8
- def _call(env)
9
- app.call(env)
10
- rescue Errors::Base => e
11
- rescue_shark_error(e)
12
- rescue StandardError => e
13
- rescue_standard_error(e)
14
- end
15
-
16
- def error_response(status, headers, message)
17
- response_body = Rack::BodyProxy.new([message]) do
18
- message.close if message.respond_to?(:close)
19
- end
20
-
21
- [status, headers, response_body]
22
- end
23
-
24
- def rescue_shark_error(error)
25
- status = error.status || 500
26
- error_response(status, {}, error.message)
27
- end
28
-
29
- def rescue_standard_error(error)
30
- SharkOnLambda.logger.error(error.message)
31
- SharkOnLambda.logger.error(error.backtrace.join("\n"))
32
- Honeybadger.notify(error) if defined?(Honeybadger)
33
-
34
- error_response(500, {}, error.message)
35
- end
36
- end
37
- end
38
- end
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharkOnLambda
4
- # The `multiValueQueryStringParameters` object from the API Gateway event
5
- # keeps _all_ values in an array, regardless of the actual size of the array
6
- # and regardless of the "intent" of the query string parameter.
7
- #
8
- # In order to normalise this behaviour, we treat the query strings
9
- #
10
- # `key=value1&key=value2`
11
- #
12
- # and
13
- #
14
- # `key[]=value1&key[]=value2`
15
- #
16
- # the same. Both are to be serialised to the query string
17
- #
18
- # `key[]=value1&key[]=value2`
19
- #
20
- # However, the query strings
21
- #
22
- # `key=value`
23
- #
24
- # and
25
- #
26
- # `key[]=value`
27
- #
28
- # are _not_ to be treated the same.
29
- class Query
30
- def initialize(data = {})
31
- @params = HashWithIndifferentAccess.new.merge(data)
32
- end
33
-
34
- def add(key, values)
35
- if key.to_s.end_with?('[]')
36
- actual_key = key[0..-3]
37
- add_list(actual_key, values)
38
- else
39
- values.each { |value| add_item(key, value) }
40
- end
41
- end
42
-
43
- def to_h
44
- @params
45
- end
46
-
47
- def to_s
48
- Rack::Utils.build_nested_query(to_h)
49
- end
50
-
51
- private
52
-
53
- def add_item(key, value)
54
- if @params[key].nil?
55
- @params[key] = value
56
- else
57
- @params[key] = Array(@params[key])
58
- @params[key] << value
59
- end
60
- end
61
-
62
- def add_list(key, value)
63
- @params[key] ||= []
64
- @params[key].concat(value)
65
- end
66
- end
67
- end
@@ -1,127 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharkOnLambda
4
- module RackAdapters
5
- class ApiGateway
6
- attr_reader :context, :event
7
-
8
- def initialize(context:, event:)
9
- @context = context
10
- @event = event.deep_stringify_keys
11
- end
12
-
13
- def build_response(status, headers, body)
14
- body_content = ''
15
- body.each { |line| body_content += line.to_s }
16
- response = {
17
- 'statusCode' => status,
18
- 'headers' => headers,
19
- 'body' => body_content
20
- }
21
- response['isBase64Encoded'] = false if elb?
22
- response
23
- end
24
-
25
- def env
26
- default_env.merge(env_request_metadata)
27
- .merge(env_headers)
28
- .merge(env_params)
29
- .merge(env_body)
30
- end
31
-
32
- private
33
-
34
- def default_env
35
- {
36
- 'SCRIPT_NAME' => '',
37
- 'rack.version' => Rack::VERSION,
38
- 'rack.errors' => $stderr,
39
- 'rack.multithread' => true,
40
- 'rack.multiprocess' => true,
41
- 'rack.run_once' => false
42
- }
43
- end
44
-
45
- def elb?
46
- return false if event['requestContext'].nil?
47
-
48
- event['requestContext'].key?('elb')
49
- end
50
-
51
- def env_body
52
- result = event['body'] || ''
53
- result = Base64.decode64(result) if event['isBase64Encoded']
54
-
55
- {
56
- 'rack.input' => StringIO.new(result).set_encoding(Encoding::BINARY)
57
- }
58
- end
59
-
60
- def env_headers
61
- result = {}
62
- http_headers.each_pair do |header, value|
63
- key = key_for_header(header)
64
- result[key] = value.to_s
65
- end
66
- result
67
- end
68
-
69
- def env_params
70
- {
71
- 'QUERY_STRING' => query_string,
72
- 'shark.path_parameters' => event['pathParameters']
73
- }
74
- end
75
-
76
- def env_request_metadata
77
- {
78
- 'REQUEST_METHOD' => event['httpMethod'],
79
- 'PATH_INFO' => path_info,
80
- 'SERVER_NAME' => server_name,
81
- 'SERVER_PORT' => server_port.to_s,
82
- 'rack.url_scheme' => url_scheme
83
- }
84
- end
85
-
86
- def http_headers
87
- event['headers'] || {}
88
- end
89
-
90
- def key_for_header(header)
91
- key = header.upcase.tr('-', '_')
92
- case key
93
- when 'CONTENT_LENGTH', 'CONTENT_TYPE' then key
94
- else "HTTP_#{key}"
95
- end
96
- end
97
-
98
- def path_info
99
- event['path'] || ''
100
- end
101
-
102
- def query_string
103
- return @query_string if defined?(@query_string)
104
-
105
- query = Query.new
106
- event['multiValueQueryStringParameters']&.each_pair do |key, value|
107
- query.add(key, value)
108
- end
109
- @query_string = query.to_s
110
- end
111
-
112
- def server_name
113
- http_headers['Host'] || 'localhost'
114
- end
115
-
116
- def server_port
117
- http_headers['X-Forwarded-Port'] || 443
118
- end
119
-
120
- def url_scheme
121
- http_headers['CloudFront-Forwarded-Proto'] ||
122
- http_headers['X-Forwarded-Proto'] ||
123
- 'https'
124
- end
125
- end
126
- end
127
- end