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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) 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 +19 -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 +14 -54
  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/cacheable.rb +21 -0
  13. data/lib/shark_on_lambda/configuration.rb +1 -65
  14. data/lib/shark_on_lambda/inferrers/serializer_inferrer.rb +10 -7
  15. data/lib/shark_on_lambda/jsonapi_renderer.rb +16 -10
  16. data/lib/shark_on_lambda/middleware/base.rb +2 -4
  17. data/lib/shark_on_lambda/middleware/honeybadger.rb +45 -0
  18. data/lib/shark_on_lambda/middleware/jsonapi_rescuer.rb +21 -1
  19. data/lib/shark_on_lambda/middleware/lambda_logger.rb +8 -16
  20. data/lib/shark_on_lambda/rake_tasks.rb +16 -0
  21. data/lib/shark_on_lambda/request.rb +0 -3
  22. data/lib/shark_on_lambda/rspec/env_builder.rb +72 -31
  23. data/lib/shark_on_lambda/rspec/helpers.rb +5 -87
  24. data/lib/shark_on_lambda/rspec/request_helpers.rb +63 -0
  25. data/lib/shark_on_lambda/rspec/{jsonapi_helpers.rb → response_helpers.rb} +4 -10
  26. data/lib/shark_on_lambda/version.rb +1 -1
  27. data/shark-on-lambda.gemspec +7 -5
  28. metadata +33 -38
  29. data/gems.locked +0 -142
  30. data/lib/shark_on_lambda/concerns/resettable_singleton.rb +0 -18
  31. data/lib/shark_on_lambda/concerns/yaml_config_loader.rb +0 -28
  32. data/lib/shark_on_lambda/dispatcher.rb +0 -26
  33. data/lib/shark_on_lambda/inferrers/name_inferrer.rb +0 -66
  34. data/lib/shark_on_lambda/jsonapi_controller.rb +0 -29
  35. data/lib/shark_on_lambda/middleware/rescuer.rb +0 -38
  36. data/lib/shark_on_lambda/query.rb +0 -67
  37. data/lib/shark_on_lambda/rack_adapters/api_gateway.rb +0 -128
  38. data/lib/shark_on_lambda/secrets.rb +0 -43
@@ -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,128 +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
- 'CONTENT_LENGTH' => result.bytesize.to_s
58
- }
59
- end
60
-
61
- def env_headers
62
- result = {}
63
- http_headers.each_pair do |header, value|
64
- key = key_for_header(header)
65
- result[key] = value.to_s
66
- end
67
- result
68
- end
69
-
70
- def env_params
71
- {
72
- 'QUERY_STRING' => query_string,
73
- 'shark.path_parameters' => event['pathParameters']
74
- }
75
- end
76
-
77
- def env_request_metadata
78
- {
79
- 'REQUEST_METHOD' => event['httpMethod'],
80
- 'PATH_INFO' => path_info,
81
- 'SERVER_NAME' => server_name,
82
- 'SERVER_PORT' => server_port.to_s,
83
- 'rack.url_scheme' => url_scheme
84
- }
85
- end
86
-
87
- def http_headers
88
- event['headers'] || {}
89
- end
90
-
91
- def key_for_header(header)
92
- key = header.upcase.tr('-', '_')
93
- case key
94
- when 'CONTENT_LENGTH', 'CONTENT_TYPE' then key
95
- else "HTTP_#{key}"
96
- end
97
- end
98
-
99
- def path_info
100
- event['path'] || ''
101
- end
102
-
103
- def query_string
104
- return @query_string if defined?(@query_string)
105
-
106
- query = Query.new
107
- event['multiValueQueryStringParameters']&.each_pair do |key, value|
108
- query.add(key, value)
109
- end
110
- @query_string = query.to_s
111
- end
112
-
113
- def server_name
114
- http_headers['Host'] || 'localhost'
115
- end
116
-
117
- def server_port
118
- http_headers['X-Forwarded-Port'] || 443
119
- end
120
-
121
- def url_scheme
122
- http_headers['CloudFront-Forwarded-Proto'] ||
123
- http_headers['X-Forwarded-Proto'] ||
124
- 'https'
125
- end
126
- end
127
- end
128
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharkOnLambda
4
- class Secrets < OpenStruct
5
- include Concerns::ResettableSingleton
6
-
7
- class << self
8
- include Concerns::YamlConfigLoader
9
-
10
- attr_writer :files
11
-
12
- def load(stage, fallback: :default)
13
- load_secrets(stage, fallback: fallback)
14
-
15
- instance
16
- end
17
-
18
- def files
19
- return @files if defined?(@files)
20
-
21
- @files = paths(%w[config/secrets.yml config/secrets.local.yml])
22
- end
23
-
24
- protected
25
-
26
- def load_secrets(stage, fallback:)
27
- secrets = load_yaml_files(stage: stage,
28
- fallback: fallback,
29
- paths: files)
30
- secrets.each_pair { |key, value| instance.send("#{key}=", value) }
31
- end
32
-
33
- def paths(files)
34
- files.map { |file| SharkOnLambda.config.root.join(file) }
35
- end
36
- end
37
-
38
- def inspect
39
- # Do not display all the internals of this object when #inspect is called.
40
- "#<#{self.class.name}>"
41
- end
42
- end
43
- end