shark-on-lambda 1.0.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/changelog.md +12 -0
- data/doc/upgrade-from-0.6.x-to-1.x.md +3 -3
- data/lib/shark-on-lambda.rb +9 -0
- data/lib/shark_on_lambda.rb +14 -54
- data/lib/shark_on_lambda/api_gateway_handler.rb +3 -55
- data/lib/shark_on_lambda/application.rb +74 -2
- data/lib/shark_on_lambda/base_controller.rb +29 -9
- data/lib/shark_on_lambda/cacheable.rb +21 -0
- data/lib/shark_on_lambda/configuration.rb +1 -65
- data/lib/shark_on_lambda/inferrers/serializer_inferrer.rb +10 -7
- data/lib/shark_on_lambda/jsonapi_renderer.rb +1 -2
- data/lib/shark_on_lambda/middleware/honeybadger.rb +5 -3
- data/lib/shark_on_lambda/middleware/jsonapi_rescuer.rb +21 -1
- data/lib/shark_on_lambda/middleware/lambda_logger.rb +5 -13
- data/lib/shark_on_lambda/rake_tasks.rb +16 -0
- data/lib/shark_on_lambda/request.rb +0 -3
- data/lib/shark_on_lambda/rspec/env_builder.rb +71 -37
- data/lib/shark_on_lambda/rspec/helpers.rb +5 -88
- data/lib/shark_on_lambda/rspec/request_helpers.rb +63 -0
- data/lib/shark_on_lambda/rspec/{jsonapi_helpers.rb → response_helpers.rb} +4 -10
- data/lib/shark_on_lambda/version.rb +1 -1
- data/shark-on-lambda.gemspec +7 -5
- metadata +37 -37
- data/lib/shark_on_lambda/concerns/resettable_singleton.rb +0 -18
- data/lib/shark_on_lambda/concerns/yaml_config_loader.rb +0 -28
- data/lib/shark_on_lambda/dispatcher.rb +0 -26
- data/lib/shark_on_lambda/inferrers/name_inferrer.rb +0 -66
- data/lib/shark_on_lambda/jsonapi_controller.rb +0 -32
- data/lib/shark_on_lambda/middleware/rescuer.rb +0 -37
- data/lib/shark_on_lambda/query.rb +0 -67
- data/lib/shark_on_lambda/rack_adapters/api_gateway.rb +0 -128
- data/lib/shark_on_lambda/secrets.rb +0 -43
@@ -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.with_indifferent_access
|
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
|