tynn 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gems +8 -5
- data/README.md +8 -0
- data/examples/composition.ru +42 -0
- data/examples/hello.ru +9 -0
- data/examples/render.ru +13 -0
- data/examples/views/home.erb +1 -0
- data/examples/views/layout.erb +5 -0
- data/lib/tynn/default_matcher.rb +7 -0
- data/lib/tynn/environment.rb +23 -0
- data/lib/tynn/erubis.rb +15 -0
- data/lib/tynn/hmote.rb +40 -0
- data/lib/tynn/hsts.rb +23 -0
- data/lib/tynn/json.rb +11 -0
- data/lib/tynn/json_parser.rb +34 -0
- data/lib/tynn/render.rb +56 -0
- data/lib/tynn/secure_headers.rb +15 -0
- data/lib/tynn/send_file.rb +12 -0
- data/lib/tynn/session.rb +11 -0
- data/lib/tynn/static.rb +10 -0
- data/lib/tynn/test.rb +16 -0
- data/lib/tynn/version.rb +1 -1
- data/lib/tynn.rb +31 -22
- data/makefile +9 -2
- data/test/core.rb +232 -0
- data/test/default_matcher.rb +17 -0
- data/test/environment.rb +31 -0
- data/test/erubis.rb +20 -0
- data/test/helper.rb +4 -11
- data/test/hmote.rb +78 -0
- data/test/hsts.rb +29 -0
- data/test/json.rb +19 -0
- data/test/json_parser.rb +22 -0
- data/test/render.rb +79 -0
- data/test/secure_headers.rb +20 -0
- data/test/send_file.rb +31 -0
- data/test/session.rb +22 -0
- data/test/static.rb +13 -0
- data/test/views/custom_layout.erb +1 -0
- data/test/views/custom_layout.mote +1 -0
- data/test/views/layout.erb +1 -0
- data/test/views/layout.mote +1 -0
- data/test/views/partial.erb +1 -0
- data/test/views/partial.mote +1 -0
- data/test/views/view.erb +1 -0
- data/test/views/view.mote +1 -0
- data/tynn.gemspec +5 -2
- metadata +82 -21
- data/test/captures.rb +0 -20
- data/test/composition.rb +0 -27
- data/test/hello.rb +0 -15
- data/test/helpers.rb +0 -54
- data/test/middleware.rb +0 -86
- data/test/settings.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3f1c481e9598f3996534f61913917797c496b2f
|
4
|
+
data.tar.gz: 7c5af7d6d35e404d81ec9eece88b35570a314851
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b571bda996fc71b5d4a1cf7abdeb99e0eef5cc3d962ca4d064293bedb253d862e2f58b8d440534426228bb9a5946039b88e98c6604bf69acf03547dce90c7bb
|
7
|
+
data.tar.gz: 99a7ec1117a9ff0b017bf02c310e9e525045bc30f7ea259ac9d531462e6c821a25c8e0f33e0ca0233d2dfab4a491176fd53cfc3760b202a10d02e921849a9764
|
data/.gems
CHANGED
data/README.md
CHANGED
@@ -37,6 +37,14 @@ Installation
|
|
37
37
|
$ gem install tynn
|
38
38
|
```
|
39
39
|
|
40
|
+
Contributing
|
41
|
+
------------
|
42
|
+
|
43
|
+
- Fork the project.
|
44
|
+
- Use `make install` to install dependencies.
|
45
|
+
- Use `make test` to run the test suite.
|
46
|
+
- Create a pull request with your changes.
|
47
|
+
|
40
48
|
[cuba]: https://github.com/soveran/cuba
|
41
49
|
[rack]: https://github.com/rack/rack
|
42
50
|
[syro]: https://github.com/soveran/syro
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative "../lib/tynn"
|
2
|
+
|
3
|
+
class Users < Tynn
|
4
|
+
end
|
5
|
+
|
6
|
+
Users.define do
|
7
|
+
on(:id) do
|
8
|
+
id = inbox[:id]
|
9
|
+
|
10
|
+
get do
|
11
|
+
res.write("GET /users/#{ id }")
|
12
|
+
end
|
13
|
+
|
14
|
+
put do
|
15
|
+
res.write("PUT /users/#{ id }")
|
16
|
+
end
|
17
|
+
|
18
|
+
patch do
|
19
|
+
res.write("PATCH /users/#{ id }")
|
20
|
+
end
|
21
|
+
|
22
|
+
delete do
|
23
|
+
res.write("DELETE /users/#{ id }")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
get do
|
28
|
+
res.write("GET /users")
|
29
|
+
end
|
30
|
+
|
31
|
+
post do
|
32
|
+
res.write("POST /users")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Tynn.define do
|
37
|
+
on("users") do
|
38
|
+
run(Users)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
run(Tynn)
|
data/examples/hello.ru
ADDED
data/examples/render.ru
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "erb"
|
2
|
+
require_relative "../lib/tynn"
|
3
|
+
require_relative "../lib/tynn/render"
|
4
|
+
|
5
|
+
Tynn.helpers(Tynn::Render, views: File.expand_path("views", __dir__))
|
6
|
+
|
7
|
+
Tynn.define do
|
8
|
+
root do
|
9
|
+
render("home", title: "Thanks for using Tynn!")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
run(Tynn)
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= title %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tynn::Environment
|
2
|
+
def self.setup(app, env: ENV["RACK_ENV"]) # :nodoc:
|
3
|
+
app.settings[:environment] = (env || :development).to_sym
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def environment
|
8
|
+
return settings[:environment]
|
9
|
+
end
|
10
|
+
|
11
|
+
def development?
|
12
|
+
return environment == :development
|
13
|
+
end
|
14
|
+
|
15
|
+
def test?
|
16
|
+
return environment == :test
|
17
|
+
end
|
18
|
+
|
19
|
+
def production?
|
20
|
+
return environment == :production
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/tynn/erubis.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "erubis"
|
2
|
+
require_relative "render"
|
3
|
+
|
4
|
+
module Tynn::Erubis
|
5
|
+
def self.setup(app, options = {}) # :nodoc:
|
6
|
+
options = options.dup
|
7
|
+
|
8
|
+
options[:options] ||= {}
|
9
|
+
options[:options] = {
|
10
|
+
escape_html: true
|
11
|
+
}.merge!(options[:options])
|
12
|
+
|
13
|
+
app.helpers(Tynn::Render, options)
|
14
|
+
end
|
15
|
+
end
|
data/lib/tynn/hmote.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "hmote"
|
2
|
+
|
3
|
+
module Tynn::HMote
|
4
|
+
include ::HMote::Helpers
|
5
|
+
|
6
|
+
def self.setup(app, options = {}) # :nodoc:
|
7
|
+
options = options.dup
|
8
|
+
|
9
|
+
options[:layout] ||= "layout"
|
10
|
+
options[:views] ||= File.expand_path("views", Dir.pwd)
|
11
|
+
|
12
|
+
app.settings[:hmote] ||= options
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def layout(layout)
|
17
|
+
settings[:hmote][:layout] = layout
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(template, locals = {}, layout = settings[:hmote][:layout])
|
22
|
+
res.headers[Rack::CONTENT_TYPE] ||= Syro::Response::DEFAULT
|
23
|
+
|
24
|
+
res.write(view(template, locals, layout))
|
25
|
+
end
|
26
|
+
|
27
|
+
def view(template, locals = {}, layout = settings[:hmote][:layout])
|
28
|
+
return partial(layout, locals.merge(content: partial(template, locals)))
|
29
|
+
end
|
30
|
+
|
31
|
+
def partial(template, locals = {})
|
32
|
+
return hmote(template_path(template), locals.merge(app: self), TOPLEVEL_BINDING)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def template_path(template)
|
38
|
+
return File.join(settings[:hmote][:views], "#{ template }.mote")
|
39
|
+
end
|
40
|
+
end
|
data/lib/tynn/hsts.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tynn::HSTS
|
2
|
+
HSTS_HEADER = "Strict-Transport-Security".freeze # :nodoc:
|
3
|
+
HSTS_EXPIRE = 15_552_000 # 180 days # :nodoc:
|
4
|
+
|
5
|
+
def self.setup(app, options = {}) # :nodoc:
|
6
|
+
max_age = options.fetch(:max_age, HSTS_EXPIRE)
|
7
|
+
subdomains = options.fetch(:subdomains, true)
|
8
|
+
preload = options.fetch(:preload, false)
|
9
|
+
|
10
|
+
header = sprintf("max-age=%i", max_age)
|
11
|
+
header << "; includeSubdomains" if subdomains
|
12
|
+
header << "; preload" if preload
|
13
|
+
|
14
|
+
app.settings[:hsts] = header
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env, inbox) # :nodoc:
|
18
|
+
result = super(env, inbox)
|
19
|
+
result[1][HSTS_HEADER] = settings[:hsts]
|
20
|
+
|
21
|
+
return result
|
22
|
+
end
|
23
|
+
end
|
data/lib/tynn/json.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Tynn::JSONParser
|
4
|
+
def self.setup(app) # :nodoc:
|
5
|
+
app.use(Middleware)
|
6
|
+
end
|
7
|
+
|
8
|
+
class Middleware # :nodoc:
|
9
|
+
CONTENT_TYPE = "application/json".freeze
|
10
|
+
FORM_HASH = "rack.request.form_hash".freeze
|
11
|
+
FORM_INPUT = "rack.request.form_input".freeze
|
12
|
+
|
13
|
+
def initialize(app)
|
14
|
+
@app = app
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
request = Rack::Request.new(env)
|
19
|
+
|
20
|
+
if json?(request) && !(body = request.body.read).empty?
|
21
|
+
request.body.rewind
|
22
|
+
|
23
|
+
request.env[FORM_HASH] = JSON.parse(body)
|
24
|
+
request.env[FORM_INPUT] = request.body
|
25
|
+
end
|
26
|
+
|
27
|
+
return @app.call(request.env)
|
28
|
+
end
|
29
|
+
|
30
|
+
def json?(request)
|
31
|
+
return request.media_type == CONTENT_TYPE
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/tynn/render.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "tilt"
|
2
|
+
|
3
|
+
module Tynn::Render
|
4
|
+
def self.setup(app, options = {}) # :nodoc:
|
5
|
+
options = options.dup
|
6
|
+
|
7
|
+
options[:engine] ||= "erb"
|
8
|
+
options[:layout] ||= "layout"
|
9
|
+
options[:views] ||= File.expand_path("views", Dir.pwd)
|
10
|
+
|
11
|
+
options[:options] ||= {}
|
12
|
+
options[:options] = {
|
13
|
+
default_encoding: Encoding.default_external,
|
14
|
+
outvar: "@_output"
|
15
|
+
}.merge!(options[:options])
|
16
|
+
|
17
|
+
app.settings[:render] ||= options
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
def layout(layout)
|
22
|
+
settings[:render][:layout] = layout
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def render(template, locals = {}, layout = settings[:render][:layout])
|
27
|
+
res.headers[Rack::CONTENT_TYPE] ||= Syro::Response::DEFAULT
|
28
|
+
|
29
|
+
res.write(view(template, locals, layout))
|
30
|
+
end
|
31
|
+
|
32
|
+
def view(template, locals = {}, layout = settings[:render][:layout])
|
33
|
+
return partial(layout, locals.merge(content: partial(template, locals)))
|
34
|
+
end
|
35
|
+
|
36
|
+
def partial(template, locals = {})
|
37
|
+
return tilt(template_path(template), locals, settings[:render][:options])
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def tilt(file, locals = {}, opts = {})
|
43
|
+
return tilt_cache.fetch(file) { Tilt.new(file, 1, opts) }.render(self, locals)
|
44
|
+
end
|
45
|
+
|
46
|
+
def tilt_cache
|
47
|
+
return Thread.current[:tilt_cache] ||= Tilt::Cache.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def template_path(template)
|
51
|
+
dir = settings[:render][:views]
|
52
|
+
ext = settings[:render][:engine]
|
53
|
+
|
54
|
+
return File.join(dir, "#{ template }.#{ ext }")
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Tynn::SecureHeaders
|
2
|
+
HEADERS = {
|
3
|
+
"X-Content-Type-Options" => "nosniff",
|
4
|
+
"X-Frame-Options" => "SAMEORIGIN",
|
5
|
+
"X-Permitted-Cross-Domain-Policies" => "none",
|
6
|
+
"X-XSS-Protection" => "1; mode=block"
|
7
|
+
} # :nodoc:
|
8
|
+
|
9
|
+
def call(env, inbox) # :nodoc:
|
10
|
+
result = super(env, inbox)
|
11
|
+
result[1].merge!(HEADERS)
|
12
|
+
|
13
|
+
return result
|
14
|
+
end
|
15
|
+
end
|
data/lib/tynn/session.rb
ADDED
data/lib/tynn/static.rb
ADDED
data/lib/tynn/test.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rack/test"
|
2
|
+
|
3
|
+
class Tynn::Test
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
def initialize(app = Tynn) # :nodoc:
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def app # :nodoc:
|
11
|
+
return @app
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :res, :last_response
|
15
|
+
alias_method :req, :last_request
|
16
|
+
end
|
data/lib/tynn/version.rb
CHANGED
data/lib/tynn.rb
CHANGED
@@ -4,39 +4,48 @@ require "syro"
|
|
4
4
|
class Tynn < Syro::Deck
|
5
5
|
include Seteable
|
6
6
|
|
7
|
-
def self.
|
8
|
-
|
7
|
+
def self.define(&block)
|
8
|
+
@syro = Syro.new(self, &block)
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.
|
12
|
-
|
13
|
-
return @__syro
|
14
|
-
else
|
15
|
-
return __middleware.inject(@__syro) { |a, m| m.call(a) }
|
16
|
-
end
|
11
|
+
def self.use(_middleware, *args, &block)
|
12
|
+
middleware.unshift(Proc.new { |app| _middleware.new(app, *args, &block) })
|
17
13
|
end
|
18
14
|
|
19
|
-
def self.
|
20
|
-
|
21
|
-
end
|
15
|
+
def self.helpers(helper, *args)
|
16
|
+
self.include(helper)
|
22
17
|
|
23
|
-
|
24
|
-
|
18
|
+
if defined?(helper::ClassMethods)
|
19
|
+
self.extend(helper::ClassMethods)
|
20
|
+
end
|
21
|
+
|
22
|
+
if helper.respond_to?(:setup)
|
23
|
+
helper.setup(self, *args)
|
24
|
+
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def self.
|
28
|
-
|
27
|
+
def self.call(env) # :nodoc:
|
28
|
+
return to_app.call(env)
|
29
29
|
end
|
30
30
|
|
31
|
-
def self.
|
32
|
-
self.
|
31
|
+
def self.to_app # :nodoc:
|
32
|
+
fail("Missing application handler. Try #{ self }.define") unless @syro
|
33
33
|
|
34
|
-
if
|
35
|
-
|
34
|
+
if middleware.empty?
|
35
|
+
return @syro
|
36
|
+
else
|
37
|
+
return middleware.inject(@syro) { |a, m| m.call(a) }
|
36
38
|
end
|
39
|
+
end
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
+
def self.middleware # :nodoc:
|
42
|
+
return @middleware ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.reset! # :nodoc:
|
46
|
+
@syro = nil
|
47
|
+
@middleware = []
|
41
48
|
end
|
42
49
|
end
|
50
|
+
|
51
|
+
require_relative "tynn/version"
|