serverless-rack 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0e289b85392f4e213d35b038b1fdb7799465808977279b3c851d15e3f38a31cf
4
+ data.tar.gz: 5cfa5111685c7d22109325c0bbb6539aadcae750c7ea2407cd62285619a73544
5
+ SHA512:
6
+ metadata.gz: 9c906ef876675f6df4bae686f50623bdb31769122e8ce36b82110c9eb92baab10c9a48308bfa7f9c2a8a7b3e27b2a4b531e95618f6898002a496666c7d9a98c6
7
+ data.tar.gz: 88c461157b7449c9fd4e974767d452e10059b87805916aed60392cd421b7745865d1dec7e23e0a1c645dd03b190a976ac09a2d913fdb29bc156c9c05ed1c5301
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # 1.0.0
2
+
3
+ Feature parity with `serverless-wsgi`.
4
+
5
+ # 0.0.1
6
+
7
+ Initial release.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'rack'
6
+
7
+ group :test do
8
+ gem 'codecov', require: false
9
+ gem 'rake'
10
+ gem 'rspec'
11
+ gem 'rubocop', require: false
12
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Logan Raarup
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,392 @@
1
+ <p align="center">
2
+ <img src="https://logandk.github.io/serverless-rack/assets/header.svg">
3
+ </p>
4
+
5
+ [![npm package](https://nodei.co/npm/serverless-rack.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/serverless-rack/)
6
+
7
+ [![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com)
8
+ [![Build Status](https://travis-ci.org/logandk/serverless-rack.png?branch=master)](https://travis-ci.org/logandk/serverless-rack)
9
+ [![Coverage Status](https://codecov.io/gh/logandk/serverless-rack/branch/master/graph/badge.svg)](https://codecov.io/gh/logandk/serverless-rack)
10
+ [![Dependency Status](https://david-dm.org/logandk/serverless-rack.png)](https://david-dm.org/logandk/serverless-rack)
11
+ [![Dev Dependency Status](https://david-dm.org/logandk/serverless-rack/dev-status.png)](https://david-dm.org/logandk/serverless-rack?type=dev)
12
+
13
+ A Serverless v1.x plugin to build your deploy Ruby Rack applications using Serverless. Compatible
14
+ Rack application frameworks include Sinatra, Cuba and Padrino.
15
+
16
+ ### Features
17
+
18
+ - Transparently converts API Gateway and ALB requests to and from standard Rack requests
19
+ - Supports anything you'd expect from Rack such as redirects, cookies, file uploads etc.
20
+ - Bundler integration, including dockerized bundling of binary dependencies
21
+ - Convenient `rack serve` command for serving your application locally during development
22
+ - CLI commands for remote execution of Ruby code (`rack exec`), rake tasks ('rack rake') and shell commands (`rack command`)
23
+
24
+ ## Install
25
+
26
+ ```
27
+ sls plugin install -n serverless-rack
28
+ ```
29
+
30
+ This will automatically add the plugin to `package.json` and the plugins section of `serverless.yml`.
31
+
32
+ ## Sinatra configuration example
33
+
34
+ ```
35
+ project
36
+ ├── api.rb
37
+ ├── config.ru
38
+ ├── Gemfile
39
+ └── serverless.yml
40
+ ```
41
+
42
+ ### api.rb
43
+
44
+ A regular Sinatra application.
45
+
46
+ ```ruby
47
+ require 'sinatra'
48
+
49
+ get '/cats' do
50
+ 'Cats'
51
+ end
52
+
53
+ get '/dogs/:id' do
54
+ 'Dog'
55
+ end
56
+ ```
57
+
58
+ ### config.ru
59
+
60
+ ```
61
+ require './api'
62
+ run Sinatra::Application
63
+ ```
64
+
65
+ ### serverless.yml
66
+
67
+ All functions that will use Rack need to have `rack_adapter.handler` set as the Lambda handler and
68
+ use the default `lambda-proxy` integration for API Gateway. This configuration example treats
69
+ API Gateway as a transparent proxy, passing all requests directly to your Sinatra application,
70
+ and letting the application handle errors, 404s etc.
71
+
72
+ ```yaml
73
+ service: example
74
+
75
+ provider:
76
+ name: aws
77
+ runtime: ruby2.5
78
+
79
+ plugins:
80
+ - serverless-rack
81
+
82
+ functions:
83
+ api:
84
+ handler: rack_adapter.handler
85
+ events:
86
+ - http: ANY /
87
+ - http: ANY {proxy+}
88
+ ```
89
+
90
+ ### Gemfile
91
+
92
+ Add Sinatra to the application bundle.
93
+
94
+ ```
95
+ source 'https://rubygems.org'
96
+
97
+ gem 'sinatra'
98
+ ```
99
+
100
+ ## Deployment
101
+
102
+ Simply run the serverless deploy command as usual:
103
+
104
+ ```
105
+ $ bundle install --path vendor/bundle
106
+ $ sls deploy
107
+ Serverless: Packaging Ruby Rack handler...
108
+ Serverless: Packaging gem dependencies using docker...
109
+ Serverless: Packaging service...
110
+ Serverless: Excluding development dependencies...
111
+ Serverless: Uploading CloudFormation file to S3...
112
+ Serverless: Uploading artifacts...
113
+ Serverless: Uploading service .zip file to S3 (1.64 MB)...
114
+ Serverless: Validating template...
115
+ Serverless: Updating Stack...
116
+ Serverless: Checking Stack update progress...
117
+ ..............
118
+ Serverless: Stack update finished...
119
+ ```
120
+
121
+ ## Usage
122
+
123
+ ### Automatic bundling of gems
124
+
125
+ You'll need to include any gems that your application uses in the bundle
126
+ that's deployed to AWS Lambda. This plugin helps you out by doing this automatically,
127
+ as long as you specify your required gems in a [Gemfile](https://bundler.io/gemfile.html):
128
+
129
+ ```
130
+ source 'https://rubygems.org'
131
+
132
+ gem 'rake'
133
+ gem 'sinatra'
134
+ ```
135
+
136
+ For more information, see https://bundler.io/docs.html.
137
+
138
+ ### Dockerized bundling
139
+
140
+ If your application depends on any gems that include compiled binaries, these
141
+ must be compiled for the lambda execution environment. Enabling the `dockerizeBundler` configuration
142
+ option will fetch and build the gems using a [docker image](https://hub.docker.com/r/logandk/serverless-rack-bundler)
143
+ that emulates the lambda environment:
144
+
145
+ ```yaml
146
+ custom:
147
+ rack:
148
+ dockerizeBundler: false
149
+ ```
150
+
151
+ ### Bundler configuration
152
+
153
+ You can use the automatic bundling functionality of _serverless-rack_ without the Rack request
154
+ handler itself by including the plugin in your `serverless.yml` configuration, without specifying
155
+ `rack_adapter.handler` as the handler for any of your lambda functions.
156
+ This will omit the Rack handler from the package, but include any gems specified in the `Gemfile`.
157
+
158
+ If you don't want to use automatic gem bundling you can set `custom.rack.enableBundler` to `false`:
159
+
160
+ ```yaml
161
+ custom:
162
+ rack:
163
+ enableBundler: false
164
+ ```
165
+
166
+ In order to pass additional arguments to `bundler` when installing requirements, the `bundlerArgs`
167
+ configuration option is available:
168
+
169
+ ```yaml
170
+ custom:
171
+ rack:
172
+ bundlerArgs: --no-cache
173
+ ```
174
+
175
+ If your `bundler` executable is not in `$PATH`, set the path explicitly using the `bundlerBin`
176
+ configuration option:
177
+
178
+ ```yaml
179
+ custom:
180
+ rack:
181
+ bundlerBin: /path/to/bundler
182
+ ```
183
+
184
+ ### Local server
185
+
186
+ For convenience, a `sls rack serve` command is provided to run your Rack application
187
+ locally. This command requires the `rack` gem to be installed, and acts as a simple
188
+ wrapper for `rackup`.
189
+
190
+ By default, the server will start on port 5000.
191
+
192
+ ```
193
+ $ sls rack serve
194
+ [2019-01-03 18:13:21] INFO WEBrick 1.4.2
195
+ [2019-01-03 18:13:21] INFO ruby 2.5.1 (2018-03-29) [x86_64-linux-gnu]
196
+ [2019-01-03 18:13:21] INFO WEBrick::HTTPServer#start: pid=25678 port=5000
197
+ ```
198
+
199
+ Configure the port using the `-p` parameter:
200
+
201
+ ```
202
+ $ sls rack serve -p 8000
203
+ [2019-01-03 18:13:21] INFO WEBrick 1.4.2
204
+ [2019-01-03 18:13:21] INFO ruby 2.5.1 (2018-03-29) [x86_64-linux-gnu]
205
+ [2019-01-03 18:13:21] INFO WEBrick::HTTPServer#start: pid=25678 port=8000
206
+ ```
207
+
208
+ When running locally, an environment variable named `IS_OFFLINE` will be set to `True`.
209
+ So, if you want to know when the application is running locally, check `ENV["IS_OFFLINE"]`.
210
+
211
+ ### Remote command execution
212
+
213
+ The `rack exec` command lets you execute ruby code remotely:
214
+
215
+ ```
216
+ $ sls rack exec -c "puts (1 + Math.sqrt(5)) / 2"
217
+ 1.618033988749895
218
+
219
+ $ cat count.rb
220
+ 3.times do |i|
221
+ puts i
222
+ end
223
+
224
+ $ sls rack exec -f count.rb
225
+ 0
226
+ 1
227
+ 2
228
+ ```
229
+
230
+ The `rack command` command lets you execute shell commands remotely:
231
+
232
+ ```
233
+ $ sls rack command -c "pwd"
234
+ /var/task
235
+
236
+ $ cat script.sh
237
+ #!/bin/bash
238
+ echo "dlrow olleh" | rev
239
+
240
+ $ sls rack command -f script.sh
241
+ hello world
242
+ ```
243
+
244
+ The `rack rake` command lets you execute Rake tasks remotely:
245
+
246
+ ```
247
+ $ sls rack rake -t "db:rollback STEP=3"
248
+ ```
249
+
250
+ ### Explicit routes
251
+
252
+ If you'd like to be explicit about which routes and HTTP methods should pass through to your
253
+ application, see the following example:
254
+
255
+ ```yaml
256
+ service: example
257
+
258
+ provider:
259
+ name: aws
260
+ runtime: ruby2.5
261
+
262
+ plugins:
263
+ - serverless-rack
264
+
265
+ functions:
266
+ api:
267
+ handler: rack_adapter.handler
268
+ events:
269
+ - http:
270
+ path: cats
271
+ method: get
272
+ integration: lambda-proxy
273
+ - http:
274
+ path: dogs/{id}
275
+ method: get
276
+ integration: lambda-proxy
277
+ ```
278
+
279
+ ### Custom domain names
280
+
281
+ If you use custom domain names with API Gateway, you might have a base path that is
282
+ at the beginning of your path, such as the stage (`/dev`, `/stage`, `/prod`). In this case, set
283
+ the `API_GATEWAY_BASE_PATH` environment variable to let `serverless-rack` know.
284
+
285
+ The example below uses the [serverless-domain-manager](https://github.com/amplify-education/serverless-domain-manager)
286
+ plugin to handle custom domains in API Gateway:
287
+
288
+ ```yaml
289
+ service: example
290
+
291
+ provider:
292
+ name: aws
293
+ runtime: ruby2.5
294
+ environment:
295
+ API_GATEWAY_BASE_PATH: ${self:custom.customDomain.basePath}
296
+
297
+ plugins:
298
+ - serverless-rack
299
+ - serverless-domain-manager
300
+
301
+ functions:
302
+ api:
303
+ handler: rack_adapter.handler
304
+ events:
305
+ - http: ANY /
306
+ - http: ANY {proxy+}
307
+
308
+ custom:
309
+ customDomain:
310
+ basePath: ${opt:stage}
311
+ domainName: mydomain.name.com
312
+ stage: ${opt:stage}
313
+ createRoute53Record: true
314
+ ```
315
+
316
+ ### File uploads
317
+
318
+ In order to accept file uploads from HTML forms, make sure to add `multipart/form-data` to
319
+ the list of content types with _Binary Support_ in your API Gateway API. The
320
+ [serverless-apigw-binary](https://github.com/maciejtreder/serverless-apigw-binary)
321
+ Serverless plugin can be used to automate this process.
322
+
323
+ Keep in mind that, when building Serverless applications, uploading
324
+ [directly to S3](http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html)
325
+ from the browser is usually the preferred approach.
326
+
327
+ ### Raw context and event
328
+
329
+ The raw context and event from AWS Lambda are both accessible through the Rack
330
+ request. The following example shows how to access them when using Flask:
331
+
332
+ ```ruby
333
+ require 'sinatra'
334
+
335
+ get '/' do
336
+ puts request.env['serverless.event']
337
+ puts request.env['serverless.context']
338
+ end
339
+ ```
340
+
341
+ ### Text MIME types
342
+
343
+ By default, all MIME types starting with `text/` and the following whitelist are sent
344
+ through API Gateway in plain text. All other MIME types will have their response body
345
+ base64 encoded (and the `isBase64Encoded` API Gateway flag set) in order to be
346
+ delivered by API Gateway as binary data (remember to add any binary MIME types that
347
+ you're using to the _Binary Support_ list in API Gateway).
348
+
349
+ This is the default whitelist of plain text MIME types:
350
+
351
+ - `application/json`
352
+ - `application/javascript`
353
+ - `application/xml`
354
+ - `application/vnd.api+json`
355
+ - `image/svg+xml`
356
+
357
+ In order to add additional plain text MIME types to this whitelist, use the
358
+ `textMimeTypes` configuration option:
359
+
360
+ ```yaml
361
+ custom:
362
+ rack:
363
+ textMimeTypes:
364
+ - application/custom+json
365
+ - application/vnd.company+json
366
+ ```
367
+
368
+ ## Usage without Serverless
369
+
370
+ The AWS API Gateway to Rack mapping module is available as a gem.
371
+
372
+ Use this gem if you need to deploy Ruby functions to handle
373
+ API Gateway events directly, without using the Serverless framework.
374
+
375
+ ```
376
+ gem install --install-dir vendor/bundle serverless-rack
377
+ ```
378
+
379
+ Initialize your Rack application and in your Lambda event handler, call
380
+ the request mapper:
381
+
382
+ ```ruby
383
+ require 'serverless_rack'
384
+
385
+ $app ||= Proc.new do |env|
386
+ ['200', {'Content-Type' => 'text/html'}, ['A barebones rack app.']]
387
+ end
388
+
389
+ def handler(event:, context:)
390
+ handle_request(app: $app, event: event, context: context)
391
+ end
392
+ ```
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This module handles conversion between API Gateway/ALB and Rack requests/responses.
4
+ #
5
+ # Author: Logan Raarup <logan@logan.dk>
6
+
7
+ require 'rack'
8
+ require 'base64'
9
+
10
+ TEXT_MIME_TYPES = [
11
+ 'application/json',
12
+ 'application/javascript',
13
+ 'application/xml',
14
+ 'application/vnd.api+json',
15
+ 'image/svg+xml'
16
+ ].freeze
17
+
18
+ def keepalive_event?(event)
19
+ ['aws.events', 'serverless-plugin-warmup'].include?(event['source'])
20
+ end
21
+
22
+ def parse_script_name(event, headers)
23
+ if ENV['API_GATEWAY_BASE_PATH']
24
+ "/#{ENV['API_GATEWAY_BASE_PATH']}"
25
+ elsif (headers['Host'] || '').include?('amazonaws.com')
26
+ "/#{event['requestContext']['stage']}"
27
+ else
28
+ ''
29
+ end
30
+ end
31
+
32
+ def parse_path_info(event)
33
+ # If a user is using a custom domain on API Gateway, they may have a base
34
+ # path in their URL. This allows us to strip it out via an optional
35
+ # environment variable.
36
+ if ENV['API_GATEWAY_BASE_PATH']
37
+ base_path = "/#{ENV['API_GATEWAY_BASE_PATH']}"
38
+ return event['path'][base_path.length..-1] if event['path'].start_with?(base_path)
39
+ end
40
+
41
+ event['path']
42
+ end
43
+
44
+ def parse_body(event)
45
+ if event['isBase64Encoded']
46
+ Base64.decode64(event['body'])
47
+ else
48
+ event['body'] || ''
49
+ end
50
+ end
51
+
52
+ def parse_http_headers(headers)
53
+ headers = headers.map do |key, value|
54
+ ["HTTP_#{key.upcase.tr('-', '_')}", value]
55
+ end
56
+
57
+ headers = headers.reject do |key, _value|
58
+ %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].include?(key)
59
+ end
60
+
61
+ headers.to_h
62
+ end
63
+
64
+ def build_environ(event:, context:, headers:, body:)
65
+ {
66
+ 'REQUEST_METHOD' => event['httpMethod'],
67
+ 'SCRIPT_NAME' => parse_script_name(event, headers),
68
+ 'PATH_INFO' => parse_path_info(event),
69
+ 'QUERY_STRING' => Rack::Utils.build_query(event['queryStringParameters'] || {}),
70
+ 'SERVER_NAME' => headers['Host'] || 'lambda',
71
+ 'SERVER_PORT' => headers['X-Forwarded-Port'] || '80',
72
+ 'CONTENT_LENGTH' => body.bytesize.to_s,
73
+ 'CONTENT_TYPE' => headers['Content-Type'] || '',
74
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
75
+ 'REMOTE_ADDR' => (event['requestContext']['identity'] || {})['sourceIp'] || '',
76
+ 'REMOTE_USER' => (event['requestContext']['authorizer'] || {})['principalId'] || '',
77
+ 'rack.version' => Rack::VERSION,
78
+ 'rack.url_scheme' => headers['X-Forwarded-Proto'] || 'http',
79
+ 'rack.input' => StringIO.new(body),
80
+ 'rack.errors' => $stderr,
81
+ 'rack.multithread' => false,
82
+ 'rack.multiprocess' => false,
83
+ 'rack.run_once' => false,
84
+ 'serverless.event' => event,
85
+ 'serverless.context' => context,
86
+ 'serverless.authorizer' => event['requestContext']['authorizer']
87
+ }.merge(parse_http_headers(headers))
88
+ end
89
+
90
+ def format_status_description(event:, status:)
91
+ return {} unless event['requestContext']['elb']
92
+
93
+ # If the request comes from ALB we need to add a status description
94
+ description = Rack::Utils::HTTP_STATUS_CODES[status]
95
+
96
+ { 'statusDescription' => "#{status} #{description}" }
97
+ end
98
+
99
+ def text_mime_type?(headers:, text_mime_types:)
100
+ mime_type = headers['Content-Type'] || 'text/plain'
101
+
102
+ return false if headers['Content-Encoding']
103
+ return true if mime_type.start_with?('text/')
104
+ return true if text_mime_types.include?(mime_type)
105
+
106
+ false
107
+ end
108
+
109
+ def format_body(body:, headers:, text_mime_types:)
110
+ response_data = ''
111
+ body.each { |part| response_data += part }
112
+
113
+ return {} if response_data.empty?
114
+
115
+ if text_mime_type?(headers: headers, text_mime_types: text_mime_types)
116
+ {
117
+ 'body' => response_data,
118
+ 'isBase64Encoded' => false
119
+ }
120
+ else
121
+ {
122
+ 'body' => Base64.strict_encode64(response_data),
123
+ 'isBase64Encoded' => true
124
+ }
125
+ end
126
+ end
127
+
128
+ def all_casings(input_string)
129
+ # Permute all casings of a given string.
130
+ # A pretty algoritm, via @Amber
131
+ # http://stackoverflow.com/questions/6792803/finding-all-possible-case-permutations-in-python
132
+ if input_string.empty?
133
+ yield ''
134
+ else
135
+ first = input_string[0]
136
+ if first.downcase == first.upcase
137
+ all_casings(input_string[1..-1]) do |sub_casing|
138
+ yield first + sub_casing
139
+ end
140
+ else
141
+ all_casings(input_string[1..-1]) do |sub_casing|
142
+ yield first.downcase + sub_casing
143
+ yield first.upcase + sub_casing
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ def format_headers(headers:)
150
+ headers = headers.to_hash
151
+
152
+ # If there are headers multiple occurrences, e.g. Set-Cookie, create
153
+ # case-mutated variations in order to pass them through APIGW.
154
+ # This is a hack that's currently needed.
155
+ headers.keys.each do |key|
156
+ values = headers[key].split("\n")
157
+
158
+ next if values.size < 2
159
+
160
+ headers.delete(key)
161
+
162
+ all_casings(key) do |casing|
163
+ headers[casing] = values.shift
164
+ break if values.empty?
165
+ end
166
+ end
167
+
168
+ { 'headers' => headers }
169
+ end
170
+
171
+ def format_response(event:, status:, headers:, body:, text_mime_types:)
172
+ response = { 'statusCode' => status }
173
+
174
+ response.merge!(
175
+ format_headers(headers: headers)
176
+ )
177
+
178
+ response.merge!(
179
+ format_status_description(event: event, status: status)
180
+ )
181
+
182
+ response.merge!(
183
+ format_body(
184
+ body: body,
185
+ headers: headers,
186
+ text_mime_types: text_mime_types
187
+ )
188
+ )
189
+
190
+ response
191
+ end
192
+
193
+ def handle_request(app:, event:, context:, config: {})
194
+ return {} if keepalive_event?(event)
195
+
196
+ status, headers, body = app.call(
197
+ build_environ(
198
+ event: event,
199
+ context: context,
200
+ headers: Rack::Utils::HeaderHash.new(event['headers'] || {}),
201
+ body: parse_body(event)
202
+ )
203
+ )
204
+
205
+ format_response(
206
+ event: event,
207
+ status: status,
208
+ headers: headers,
209
+ body: body,
210
+ text_mime_types: TEXT_MIME_TYPES + config['text_mime_types'].to_a
211
+ )
212
+ end
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'serverless-rack'
3
+ s.version = '1.0.0'
4
+ s.summary =
5
+ 'Serverless plugin to deploy Ruby Rack applications (Sinatra/Padrino/Cuba etc.) '\
6
+ 'and bundle gems'
7
+ s.description =
8
+ 'A Serverless v1.x plugin to build your deploy Ruby Rack applications using '\
9
+ 'Serverless. Compatible Rack application frameworks include Sinatra, '\
10
+ 'Cuba and Padrino.'
11
+ s.authors = ['Logan Raarup']
12
+ s.email = 'logan@logan.dk'
13
+ s.files = [
14
+ 'lib/serverless_rack.rb',
15
+ 'CHANGELOG.md',
16
+ 'Gemfile',
17
+ 'LICENSE',
18
+ 'README.md',
19
+ 'serverless-rack.gemspec'
20
+ ]
21
+ s.homepage = 'https://github.com/logandk/serverless-rack'
22
+ s.license = 'MIT'
23
+
24
+ s.required_ruby_version = '>= 2.2.0'
25
+ s.add_dependency 'rack', '~> 2.0'
26
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serverless-rack
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Logan Raarup
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ description: A Serverless v1.x plugin to build your deploy Ruby Rack applications
28
+ using Serverless. Compatible Rack application frameworks include Sinatra, Cuba and
29
+ Padrino.
30
+ email: logan@logan.dk
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - Gemfile
37
+ - LICENSE
38
+ - README.md
39
+ - lib/serverless_rack.rb
40
+ - serverless-rack.gemspec
41
+ homepage: https://github.com/logandk/serverless-rack
42
+ licenses:
43
+ - MIT
44
+ metadata: {}
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.2.0
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 2.7.6
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: Serverless plugin to deploy Ruby Rack applications (Sinatra/Padrino/Cuba
65
+ etc.) and bundle gems
66
+ test_files: []