phaedra 0.3.2 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f0e4c33ad4a5241f2a6b7455522db8389a1bc2323ef4542ad75546b2b874a08
4
- data.tar.gz: 42f380fa9cb7a620da9591862c7fd7abbd4022e8046c1ed8f089e902a052c1c2
3
+ metadata.gz: 00d5ba6f3bc10860baef3bf63867665db4ef610b7cf14a8281495cf929339bc3
4
+ data.tar.gz: 5d1c500a8cbe79a89182497e7881fdeba3d129e5e2f2ddcce19012f9ae713171
5
5
  SHA512:
6
- metadata.gz: 0003a862d70c030695b33c1318c69c14eb3f0eda149590e485083827d6c703c06d68dbf8daa6c39e911274b5a5527c2e043aa327e18759bdb8ff970179e764cd
7
- data.tar.gz: a5a22957adcb6c3e1fbce24e39e4c7b582381936b3d832d23ea32813888d5789ea779e89116fb3b16ac1a7122db97ac77d6de2fdd909ee791d351629f3c7dfcb
6
+ metadata.gz: 3f3a8145df4a02f5362dfffb66f1de44ccd650425504007f2f49fa666c68bd9d228d0e8ade98daa2d318c57b220013009bd2c9b37d10d375a7cecca2cee0c4ac
7
+ data.tar.gz: f0effbf926248e56c67da411bd688cc3f6783d7710bdedf141029d523b4e55667df18b1e509cb68aa55795a01b74369ac8e007a91754ac9b3c6046741d166258
data/README.md CHANGED
@@ -118,7 +118,13 @@ All you have to do is create a static site repo ([Bridgetown](https://www.bridge
118
118
 
119
119
  We recommend using OpenFaaS' dockerfile template so you can define your own `Dockerfile` to book Rack + Phaedra using the Puma web server. This also allows you to customize the Docker image configuration to install and configure other tools as necessary.
120
120
 
121
- First, make sure you've pulled down the template:
121
+ First make sure you've added Puma to your Gemfile:
122
+
123
+ ```
124
+ gem "puma"
125
+ ```
126
+
127
+ Then make sure you've pulled down the OpenFaaS template:
122
128
 
123
129
  ```sh
124
130
  faas-cli template store pull dockerfile
@@ -174,7 +180,7 @@ Next add the `config.ru` file to boot Rack:
174
180
  ```ruby
175
181
  # testphaedra/config.ru
176
182
 
177
- require "phaedra"
183
+ require "phaedra/rack_app"
178
184
 
179
185
  run Phaedra::RackApp.new
180
186
  ```
@@ -210,7 +216,7 @@ In case you're wondering: yes, with Phaedra you can write multiple Ruby function
210
216
  Booting Phaedra up as Rack app is very simple. All you need to do is add a `config.ru` file alongside your `api` folder:
211
217
 
212
218
  ```ruby
213
- require "phaedra"
219
+ require "phaedra/rack_app"
214
220
 
215
221
  run Phaedra::RackApp.new
216
222
  ```
@@ -0,0 +1,46 @@
1
+ FROM ruby:2.6-alpine3.11 as builder
2
+
3
+ RUN apk add --no-cache --virtual \\
4
+ #
5
+ # required
6
+ bash tzdata build-base libffi-dev \\
7
+ #
8
+ # nice to haves
9
+ curl git
10
+
11
+ FROM builder as phaedra-app
12
+
13
+ # This is to fix an issue on Linux with permissions issues
14
+ ARG USER_ID=${USER_ID:-1000}
15
+ ARG GROUP_ID=${GROUP_ID:-1000}
16
+ ARG DOCKER_USER=${DOCKER_USER:-user}
17
+ ARG APP_DIR=${APP_DIR:-/home/user/phaedra-app}
18
+
19
+ # Change with --build-arg PHAEDRA_ENV=production
20
+ ARG PHAEDRA_ENV=staging
21
+ ENV PHAEDRA_ENV=$PHAEDRA_ENV
22
+
23
+ # Create a non-root user
24
+ RUN addgroup -g $GROUP_ID -S $GROUP_ID
25
+ RUN adduser --disabled-password -G $GROUP_ID --uid $USER_ID -S $DOCKER_USER
26
+
27
+ # Create and then own the directory to fix permissions issues
28
+ RUN mkdir -p $APP_DIR
29
+ RUN chown -R $USER_ID:$GROUP_ID $APP_DIR
30
+
31
+ # Define the user running the container
32
+ USER $USER_ID:$GROUP_ID
33
+
34
+ # . now == $APP_DIR
35
+ WORKDIR $APP_DIR
36
+
37
+ # COPY is run as a root user, not as the USER defined above, so we must chown it
38
+ COPY --chown=$USER_ID:$GROUP_ID Gemfile* ./
39
+ RUN gem install bundler
40
+ RUN bundle install
41
+
42
+ COPY --chown=$USER_ID:$GROUP_ID . .
43
+
44
+ EXPOSE 8080
45
+
46
+ CMD ["bundle", "exec", "rackup", "-p", "8080", "-o", "0.0.0.0"]
@@ -1,9 +1,9 @@
1
- require "phaedra"
1
+ require_relative "../phaedra/initializers"
2
2
 
3
3
  class PhaedraFunction < Phaedra::Base
4
4
  def get(params)
5
5
  response["Content-Type"] = "text/html; charset=utf-8"
6
- "<p>This is Interesting. 😁</p>"
6
+ "<p>😁 #{Phaedra.the_time} - #{ENV["PHAEDRA_ENV"]} - #{Time.new}</p>"
7
7
  end
8
8
  end
9
9
 
@@ -1,10 +1,10 @@
1
- require "phaedra"
1
+ require_relative "../phaedra/initializers"
2
2
 
3
3
  class PhaedraFunction < Phaedra::Base
4
4
  before_action :earlier_stuff
5
5
 
6
6
  def get(params)
7
- "The Current Time is: #{Time.new} and Search Param is #{params[:search]}."
7
+ "The ?search param is #{params[:search]}"
8
8
  end
9
9
 
10
10
  def post(params)
@@ -1,3 +1,3 @@
1
- require "phaedra"
1
+ require "phaedra/rack_app"
2
2
 
3
3
  run Phaedra::RackApp.new
@@ -0,0 +1,8 @@
1
+ version: '3'
2
+ services:
3
+ web:
4
+ build: .
5
+ ports:
6
+ - "8080:8080"
7
+ environment:
8
+ - PHAEDRA_ENV
@@ -0,0 +1,11 @@
1
+ require "phaedra"
2
+
3
+ module Phaedra
4
+ Initializers.register self do
5
+ the_time("123")
6
+ end
7
+
8
+ def self.the_time(init = nil)
9
+ @the_time ||= "#{Time.now} + #{init}"
10
+ end
11
+ end
@@ -1,7 +1,5 @@
1
1
  require "phaedra/version"
2
-
3
2
  require "webrick"
4
- require "rack"
5
-
3
+ require "phaedra/initializers_module"
4
+ require "phaedra/startup_initializers"
6
5
  require "phaedra/base"
7
- require "phaedra/rack_app"
@@ -7,6 +7,10 @@ module Phaedra
7
7
  class Base
8
8
  include CallbacksActionable
9
9
 
10
+ before_action do
11
+ Initializers.run
12
+ end
13
+
10
14
  # Used by WEBrick
11
15
  def self.get_instance(server, *options)
12
16
  self.new(server, *options)
@@ -112,7 +116,7 @@ module Phaedra
112
116
 
113
117
  def set_initial_status
114
118
  @res.status = 200
115
- @res["Content-Type"] = "application/json"
119
+ @res["Content-Type"] = "application/json; charset=utf-8"
116
120
  end
117
121
 
118
122
  def call_method_action(params)
@@ -123,7 +127,7 @@ module Phaedra
123
127
  def complete_response
124
128
  if @res.body.is_a?(String) && !@res["Content-Type"].start_with?("text/")
125
129
  @res["Content-Type"] = "text/plain; charset=utf-8"
126
- elsif @res["Content-Type"] == "application/json"
130
+ elsif @res["Content-Type"].start_with? "application/json"
127
131
  @res.body = @res.body.to_json
128
132
  end
129
133
  end
@@ -11,14 +11,14 @@ module Phaedra
11
11
  end
12
12
 
13
13
  module ClassMethods
14
- def before_action(*args)
15
- set_callback :action, :before, *args
14
+ def before_action(*args, &block)
15
+ set_callback :action, :before, *args, &block
16
16
  end
17
- def after_action(*args)
18
- set_callback :action, :after, *args
17
+ def after_action(*args, &block)
18
+ set_callback :action, :after, *args, &block
19
19
  end
20
- def around_action(*args)
21
- set_callback :action, :around, *args
20
+ def around_action(*args, &block)
21
+ set_callback :action, :around, *args, &block
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,69 @@
1
+ module Phaedra
2
+ module Initializers
3
+ Registration = Struct.new(
4
+ :origin,
5
+ :priority,
6
+ :block,
7
+ keyword_init: true
8
+ ) do
9
+ def to_s
10
+ "#{owner}:#{priority} for #{block}"
11
+ end
12
+ end
13
+
14
+ DEFAULT_PRIORITY = 20
15
+
16
+ PRIORITY_MAP = {
17
+ low: 10,
18
+ normal: 20,
19
+ high: 30,
20
+ }.freeze
21
+
22
+ # initial empty hooks
23
+ @registry = []
24
+
25
+ NotAvailable = Class.new(RuntimeError)
26
+ Uncallable = Class.new(RuntimeError)
27
+
28
+ # Ensure the priority is a Fixnum
29
+ def self.priority_value(priority)
30
+ return priority if priority.is_a?(Integer)
31
+
32
+ PRIORITY_MAP[priority] || DEFAULT_PRIORITY
33
+ end
34
+
35
+ def self.register(origin, priority: DEFAULT_PRIORITY, &block)
36
+ raise Uncallable, "Initializers must respond to :call" unless block.respond_to? :call
37
+
38
+ @registry << Registration.new(
39
+ origin: origin,
40
+ priority: priority_value(priority),
41
+ block: block
42
+ )
43
+
44
+ block
45
+ end
46
+
47
+ def self.remove(origin)
48
+ @registry.delete_if { |item| item.origin == origin }
49
+ end
50
+
51
+ def self.run(force: false)
52
+ if !@initializers_ran || force
53
+ prioritized_initializers.each do |initializer|
54
+ initializer.block.call
55
+ end
56
+ end
57
+
58
+ @initializers_ran = true
59
+ end
60
+
61
+ def self.prioritized_initializers
62
+ # sort initializers according to priority and load order
63
+ grouped_initializers = @registry.group_by(&:priority)
64
+ grouped_initializers.keys.sort.reverse.map do |priority|
65
+ grouped_initializers[priority]
66
+ end.flatten
67
+ end
68
+ end
69
+ end
@@ -1,3 +1,6 @@
1
+ require "rack"
2
+ require "phaedra"
3
+
1
4
  module Phaedra
2
5
  class Request < Rack::Request
3
6
  def query
@@ -0,0 +1,2 @@
1
+ require "phaedra/rack_middleware/not_found"
2
+ require "phaedra/rack_middleware/static"
@@ -0,0 +1,21 @@
1
+ module Phaedra
2
+ module Middleware
3
+ class NotFound
4
+ def initialize(app, path, content_type = 'text/html; charset=utf-8')
5
+ @app = app
6
+ @content = File.read(path)
7
+ @length = @content.bytesize.to_s
8
+ @content_type = content_type
9
+ end
10
+
11
+ def call(env)
12
+ response = @app.call(env)
13
+ if response[0] == 404
14
+ [404, {'Content-Type' => @content_type, 'Content-Length' => @length}, [@content]]
15
+ else
16
+ response
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ module Phaedra
2
+ module Middleware
3
+ # Based on Rack::TryStatic middleware
4
+ # https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/try_static.rb
5
+
6
+ class Static
7
+ def initialize(app, options)
8
+ @app = app
9
+ @try = ["", ".html", "index.html", "/index.html", *options[:try]]
10
+ @static = Rack::Static.new(
11
+ lambda { |_| [404, {}, []] },
12
+ options)
13
+ end
14
+
15
+ def call(env)
16
+ orig_path = env['PATH_INFO']
17
+ found = nil
18
+ @try.each do |path|
19
+ resp = @static.call(env.merge!({'PATH_INFO' => orig_path + path}))
20
+ break if !(403..405).include?(resp[0]) && found = resp
21
+ end
22
+ found or @app.call(env.merge!('PATH_INFO' => orig_path))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ module Phaedra
2
+ Initializers.register self, priority: :high do
3
+ environment
4
+ end
5
+
6
+ def self.environment
7
+ @environment ||= ENV.fetch("PHAEDRA_ENV", :development).to_sym
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Phaedra
2
- VERSION = "0.3.2"
2
+ VERSION = "0.5.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phaedra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared White
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-09 00:00:00.000000000 Z
11
+ date: 2020-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,14 +80,22 @@ files:
80
80
  - LICENSE.txt
81
81
  - README.md
82
82
  - Rakefile
83
+ - example/Dockerfile
83
84
  - example/Gemfile
84
85
  - example/api/simple.rb
85
86
  - example/api/the-time.rb
86
87
  - example/config.ru
88
+ - example/docker-compose.yml
89
+ - example/phaedra/initializers.rb
87
90
  - lib/phaedra.rb
88
91
  - lib/phaedra/base.rb
89
92
  - lib/phaedra/concerns/callbacks_actionable.rb
93
+ - lib/phaedra/initializers_module.rb
90
94
  - lib/phaedra/rack_app.rb
95
+ - lib/phaedra/rack_middleware.rb
96
+ - lib/phaedra/rack_middleware/not_found.rb
97
+ - lib/phaedra/rack_middleware/static.rb
98
+ - lib/phaedra/startup_initializers.rb
91
99
  - lib/phaedra/version.rb
92
100
  - phaedra.gemspec
93
101
  homepage: https://github.com/whitefusionhq/phaedra
@@ -109,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
117
  - !ruby/object:Gem::Version
110
118
  version: '0'
111
119
  requirements: []
112
- rubygems_version: 3.0.6
120
+ rubygems_version: 3.0.8
113
121
  signing_key:
114
122
  specification_version: 4
115
123
  summary: Write serverless Ruby functions via a REST-like microframework compatible