tynn 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b3f1c481e9598f3996534f61913917797c496b2f
4
- data.tar.gz: 7c5af7d6d35e404d81ec9eece88b35570a314851
3
+ metadata.gz: d0c2e697419542ac01be6106e60a3bd2a6221d3b
4
+ data.tar.gz: 917cac7cbbd5a4123c1f70ca431dd818aa17efcc
5
5
  SHA512:
6
- metadata.gz: 3b571bda996fc71b5d4a1cf7abdeb99e0eef5cc3d962ca4d064293bedb253d862e2f58b8d440534426228bb9a5946039b88e98c6604bf69acf03547dce90c7bb
7
- data.tar.gz: 99a7ec1117a9ff0b017bf02c310e9e525045bc30f7ea259ac9d531462e6c821a25c8e0f33e0ca0233d2dfab4a491176fd53cfc3760b202a10d02e921849a9764
6
+ metadata.gz: 70b7c35be68be33da92b5b95808b4e241081912c588b0d4e29a2f07a87413e5b5907f3adbe02ebc1aabee06d0d61071768cf471f05bb2e59e8f4fe132fd2a45a
7
+ data.tar.gz: 765f7512ccae32a7b6e92db62f2acc1a1b6370bcd05d0e14c6d1dd6da2cbe765dc9808baa269b1067e564b1beed0496082e6eb1859478455657303f89b15e7c6
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ doc/
@@ -0,0 +1,18 @@
1
+ require_relative "../lib/tynn"
2
+ require_relative "../lib/tynn/environment"
3
+ require_relative "../lib/tynn/protection"
4
+ require_relative "../lib/tynn/session"
5
+
6
+ Tynn.helpers(Tynn::Environment)
7
+
8
+ Tynn.helpers(Tynn::Protection, ssl: Tynn.production?)
9
+
10
+ Tynn.helpers(Tynn::Session, secret: SecureRandom.hex(64))
11
+
12
+ Tynn.define do
13
+ root do
14
+ res.write("use protection")
15
+ end
16
+ end
17
+
18
+ run(Tynn)
data/lib/tynn.rb CHANGED
@@ -9,7 +9,7 @@ class Tynn < Syro::Deck
9
9
  end
10
10
 
11
11
  def self.use(_middleware, *args, &block)
12
- middleware.unshift(Proc.new { |app| _middleware.new(app, *args, &block) })
12
+ middleware << (Proc.new { |app| _middleware.new(app, *args, &block) })
13
13
  end
14
14
 
15
15
  def self.helpers(helper, *args)
@@ -34,7 +34,7 @@ class Tynn < Syro::Deck
34
34
  if middleware.empty?
35
35
  return @syro
36
36
  else
37
- return middleware.inject(@syro) { |a, m| m.call(a) }
37
+ return middleware.reverse.inject(@syro) { |a, m| m.call(a) }
38
38
  end
39
39
  end
40
40
 
data/lib/tynn/csrf.rb ADDED
@@ -0,0 +1,48 @@
1
+ module Tynn::CSRF
2
+ def csrf
3
+ @csrf ||= Tynn::CSRF::Helper.new(self)
4
+ end
5
+
6
+ class Helper
7
+ CSRF_HEADER = "HTTP_X_CSRF_TOKEN".freeze
8
+
9
+ def initialize(app)
10
+ @app = app
11
+ @req = app.req
12
+ end
13
+
14
+ def token
15
+ return session[:csrf_token] ||= SecureRandom.base64(32)
16
+ end
17
+
18
+ def reset!
19
+ session.delete(:csrf_token)
20
+ end
21
+
22
+ def safe?
23
+ return @req.get? || @req.head? || verify_token
24
+ end
25
+
26
+ def unsafe?
27
+ return !safe?
28
+ end
29
+
30
+ def form_tag
31
+ return %Q(<input type="hidden" name="csrf_token" value="#{ token }">)
32
+ end
33
+
34
+ def meta_tag
35
+ return %Q(<meta name="csrf_token" content="#{ token }">)
36
+ end
37
+
38
+ private
39
+
40
+ def verify_token
41
+ return @req[:csrf_token] == token || @req.env[CSRF_HEADER] == token
42
+ end
43
+
44
+ def session
45
+ return @app.session
46
+ end
47
+ end
48
+ end
@@ -1,9 +1,26 @@
1
+ # Adds helper methods to get and check the current environment.
2
+ #
3
+ # require "tynn"
4
+ # require "tynn/environment"
5
+ #
6
+ # Tynn.helpers(Tynn::Environment)
7
+ #
8
+ # Tynn.environment # => :development
9
+ #
10
+ # Tynn.development? # => true
11
+ # Tynn.production? # => false
12
+ # Tynn.test? # => false
13
+ #
14
+ # By default, the environment is based on `ENV["RACK_ENV"]`.
15
+ #
16
+ # Tynn.helpers(Tynn::Environment, env: ENV["RACK_ENV"])
17
+ #
1
18
  module Tynn::Environment
2
19
  def self.setup(app, env: ENV["RACK_ENV"]) # :nodoc:
3
20
  app.settings[:environment] = (env || :development).to_sym
4
21
  end
5
22
 
6
- module ClassMethods
23
+ module ClassMethods # :nodoc:
7
24
  def environment
8
25
  return settings[:environment]
9
26
  end
data/lib/tynn/json.rb CHANGED
@@ -4,7 +4,7 @@ module Tynn::JSON
4
4
  JSON_CONTENT_TYPE = "application/json".freeze # :nodoc:
5
5
 
6
6
  def json(data)
7
- res.headers[Rack::CONTENT_TYPE] ||= JSON_CONTENT_TYPE
7
+ res.headers[Rack::CONTENT_TYPE] = JSON_CONTENT_TYPE
8
8
 
9
9
  res.write(data.to_json)
10
10
  end
@@ -2,7 +2,7 @@ require "json"
2
2
 
3
3
  module Tynn::JSONParser
4
4
  def self.setup(app) # :nodoc:
5
- app.use(Middleware)
5
+ app.use(Tynn::JSONParser::Middleware)
6
6
  end
7
7
 
8
8
  class Middleware # :nodoc:
@@ -27,6 +27,8 @@ module Tynn::JSONParser
27
27
  return @app.call(request.env)
28
28
  end
29
29
 
30
+ private
31
+
30
32
  def json?(request)
31
33
  return request.media_type == CONTENT_TYPE
32
34
  end
@@ -0,0 +1,40 @@
1
+ # Adds extra matchers to Tynn.
2
+ #
3
+ # require "tynn"
4
+ # require "tynn/matchers"
5
+ #
6
+ # Tynn.helpers(Tynn::Matchers)
7
+ #
8
+ module Tynn::Matchers
9
+ # A catch-all matcher.
10
+ #
11
+ # Tynn.define do
12
+ # authenticated? do
13
+ # # ...
14
+ # end
15
+ #
16
+ # default do # on true
17
+ # # ...
18
+ # end
19
+ # end
20
+ #
21
+ # :call-seq: default(&block)
22
+ #
23
+ def default
24
+ yield
25
+
26
+ halt(res.finish)
27
+ end
28
+
29
+ # Match if the given `params` are present.
30
+ #
31
+ # Tynn.define do
32
+ # on param?(:token) do
33
+ # # ...
34
+ # end
35
+ # end
36
+ #
37
+ def param?(*params)
38
+ return params.all? { |param| (v = req[param]) && !v.empty? }
39
+ end
40
+ end
@@ -0,0 +1,18 @@
1
+ module Tynn::NotFound
2
+ def call(env, inbox) # :nodoc:
3
+ result = super(env, inbox)
4
+
5
+ status, _, body = result
6
+
7
+ if status == 404 && body.empty?
8
+ not_found
9
+
10
+ return res.finish
11
+ else
12
+ return result
13
+ end
14
+ end
15
+
16
+ def not_found # :nodoc:
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ require_relative "secure_headers"
2
+
3
+ module Tynn::Protection
4
+ def self.setup(app, ssl: false, hsts: {}) # :nodoc:
5
+ app.helpers(Tynn::SecureHeaders)
6
+
7
+ if ssl
8
+ require_relative "ssl"
9
+
10
+ app.helpers(Tynn::SSL, hsts: hsts)
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,10 @@
1
+ # Adds security related HTTP headers.
2
+ #
3
+ # require "tynn"
4
+ # require "tynn/secure_headers"
5
+ #
6
+ # Tynn.helpers(Tynn::SecureHeaders)
7
+ #
1
8
  module Tynn::SecureHeaders
2
9
  HEADERS = {
3
10
  "X-Content-Type-Options" => "nosniff",
data/lib/tynn/session.rb CHANGED
@@ -2,6 +2,9 @@ module Tynn::Session
2
2
  RACK_SESSION = "rack.session".freeze # :nodoc:
3
3
 
4
4
  def self.setup(app, options = {}) # :nodoc:
5
+ options = options.dup
6
+ options[:http_only] ||= true
7
+
5
8
  app.use(Rack::Session::Cookie, options)
6
9
  end
7
10
 
data/lib/tynn/ssl.rb ADDED
@@ -0,0 +1,71 @@
1
+ module Tynn::SSL
2
+ def self.setup(app, options = {}) # :nodoc:
3
+ app.use(Tynn::SSL::Middleware, options)
4
+ end
5
+
6
+ class Middleware # :nodoc:
7
+ def initialize(app, hsts: {})
8
+ @app = app
9
+ @hsts_header = build_hsts_header(hsts)
10
+ end
11
+
12
+ def call(env)
13
+ request = Rack::Request.new(env)
14
+
15
+ unless request.ssl?
16
+ return [301, redirect_headers(request), []]
17
+ end
18
+
19
+ result = @app.call(env)
20
+
21
+ set_hsts_header(result[1])
22
+ set_cookies_as_secure(result[1])
23
+
24
+ return result
25
+ end
26
+
27
+ private
28
+
29
+ HSTS_HEADER = "Strict-Transport-Security".freeze
30
+ HSTS_EXPIRE = 15_552_000 # 180 days
31
+
32
+ def build_hsts_header(options)
33
+ header = sprintf("max-age=%i", options.fetch(:expires, HSTS_EXPIRE))
34
+ header << "; includeSubdomains" if options.fetch(:subdomains, true)
35
+ header << "; preload" if options[:preload]
36
+
37
+ return header
38
+ end
39
+
40
+ def redirect_headers(request)
41
+ return {
42
+ "Content-Type" => "text/html",
43
+ "Location" => https_location(request)
44
+ }
45
+ end
46
+
47
+ HTTPS_LOCATION = "https://%s%s".freeze
48
+
49
+ def https_location(request)
50
+ return sprintf(HTTPS_LOCATION, request.host, request.fullpath)
51
+ end
52
+
53
+ def set_hsts_header(headers)
54
+ headers[HSTS_HEADER] = @hsts_header
55
+ end
56
+
57
+ COOKIE_HEADER = "Set-Cookie".freeze
58
+ COOKIE_SEPARATOR = "\n".freeze
59
+ COOKIE_REGEXP = /;\s*secure\s*(;|$)/i
60
+
61
+ def set_cookies_as_secure(headers)
62
+ return unless cookies = headers[COOKIE_HEADER]
63
+
64
+ cookies = cookies.split(COOKIE_SEPARATOR).map do |cookie|
65
+ (cookie !~ COOKIE_REGEXP) ? "#{ cookie }; secure" : cookie
66
+ end
67
+
68
+ headers[COOKIE_HEADER] = cookies.join(COOKIE_SEPARATOR)
69
+ end
70
+ end
71
+ end
data/lib/tynn/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Tynn
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/makefile CHANGED
@@ -1,9 +1,12 @@
1
1
  default: test
2
2
 
3
+ docs:
4
+ @rdoc --markup markdown ./lib/
5
+
3
6
  install:
4
7
  @cat .gems | xargs gem install
5
8
 
6
9
  test:
7
- @cutest -r ./test/helper.rb ./test/*.rb
10
+ @cutest -r ./test/helper.rb ./test/*_test.rb
8
11
 
9
12
  .PHONY: test
File without changes
data/test/csrf_test.rb ADDED
@@ -0,0 +1,98 @@
1
+ require "securerandom"
2
+ require_relative "../lib/tynn/csrf"
3
+ require_relative "../lib/tynn/session"
4
+
5
+ setup do
6
+ Tynn.helpers(Tynn::CSRF)
7
+ Tynn.helpers(Tynn::Session, secret: SecureRandom.hex(64))
8
+
9
+ Tynn::Test.new
10
+ end
11
+
12
+ test "get should be safe" do |app|
13
+ Tynn.define do
14
+ get do
15
+ res.write(csrf.safe?)
16
+ end
17
+ end
18
+
19
+ app.get("/")
20
+
21
+ assert_equal "true", app.res.body
22
+ end
23
+
24
+ test "head should be safe" do |app|
25
+ Tynn.define do
26
+ on req.head? do
27
+ res.write(csrf.safe?)
28
+ end
29
+ end
30
+
31
+ app.head("/")
32
+
33
+ assert_equal "true", app.res.body
34
+ end
35
+
36
+ test "invalid csrf token" do |app|
37
+ Tynn.define do
38
+ post do
39
+ res.write(csrf.unsafe?)
40
+ end
41
+ end
42
+
43
+ app.post("/")
44
+
45
+ assert_equal "true", app.res.body
46
+ end
47
+
48
+ test "valid csrf token" do |app|
49
+ token = SecureRandom.hex(64)
50
+
51
+ Tynn.define do
52
+ post do
53
+ session[:csrf_token] = token
54
+
55
+ res.write(csrf.safe?)
56
+ end
57
+ end
58
+
59
+ app.post("/", csrf_token: token)
60
+
61
+ assert_equal "true", app.res.body
62
+ end
63
+
64
+ test "resets token" do |app|
65
+ token = SecureRandom.hex(64)
66
+
67
+ Tynn.define do
68
+ post do
69
+ session[:csrf_token] = token
70
+
71
+ if csrf.unsafe?
72
+ csrf.reset!
73
+ end
74
+
75
+ res.write(csrf.token)
76
+ end
77
+ end
78
+
79
+ app.post("/", csrf_token: "nonsense")
80
+
81
+ assert token != app.res.body
82
+ end
83
+
84
+ test "http header" do |app|
85
+ token = SecureRandom.hex(64)
86
+
87
+ Tynn.define do
88
+ post do
89
+ session[:csrf_token] = token
90
+
91
+ res.write(csrf.safe?)
92
+ end
93
+ end
94
+
95
+ app.post("/", {}, "HTTP_X_CSRF_TOKEN" => token)
96
+
97
+ assert_equal "true", app.res.body
98
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,37 @@
1
+ require_relative "../lib/tynn/matchers"
2
+
3
+ setup do
4
+ Tynn.helpers(Tynn::Matchers)
5
+
6
+ Tynn::Test.new
7
+ end
8
+
9
+ test "default" do |app|
10
+ Tynn.define do
11
+ default do
12
+ res.write("foo")
13
+ end
14
+ end
15
+
16
+ app.get("/")
17
+
18
+ assert_equal 200, app.res.status
19
+ assert_equal "foo", app.res.body
20
+ end
21
+
22
+ test "param?" do |app|
23
+ Tynn.define do
24
+ on param?(:key) do
25
+ res.write(req[:key])
26
+ end
27
+ end
28
+
29
+ app.get("/")
30
+
31
+ assert_equal 404, app.res.status
32
+
33
+ app.get("/", key: "foo")
34
+
35
+ assert_equal 200, app.res.status
36
+ assert_equal "foo", app.res.body
37
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "../lib/tynn/not_found"
2
+
3
+ test "not found" do
4
+ Tynn.helpers(Tynn::NotFound)
5
+
6
+ class Tynn
7
+ def not_found
8
+ res.write("not found")
9
+ end
10
+ end
11
+
12
+ Tynn.define do
13
+ end
14
+
15
+ app = Tynn::Test.new
16
+ app.get("/notfound")
17
+
18
+ assert_equal "not found", app.res.body
19
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "../lib/tynn/protection"
2
+
3
+ test "includes secure headers" do
4
+ Tynn.helpers(Tynn::Protection)
5
+
6
+ assert Tynn.include?(Tynn::SecureHeaders)
7
+ end
8
+
9
+ test "includes ssl helper if ssl is true" do
10
+ Tynn.helpers(Tynn::Protection, ssl: true)
11
+
12
+ assert Tynn.include?(Tynn::SSL)
13
+ end
14
+
15
+ test "supports hsts options" do
16
+ hsts = { expires: 100, subdomains: false, preload: true }
17
+
18
+ Tynn.helpers(Tynn::Protection, ssl: true, hsts: hsts)
19
+
20
+ Tynn.define do
21
+ end
22
+
23
+ app = Tynn::Test.new
24
+ app.get("/", {}, "HTTPS" => "on")
25
+
26
+ hsts = app.res.headers["Strict-Transport-Security"]
27
+
28
+ assert_equal "max-age=100; preload", hsts
29
+ end
File without changes
File without changes
File without changes
@@ -15,8 +15,11 @@ test "session" do
15
15
  app = Tynn::Test.new
16
16
  app.get("/")
17
17
 
18
- env = app.last_request.env
18
+ env = app.req.env
19
+ session = env["rack.session"]
20
+ session_options = env["rack.session.options"]
19
21
 
20
22
  assert_equal "foo", app.res.body
21
- assert_equal "foo", env["rack.session"]["foo"]
23
+ assert_equal "foo", session["foo"]
24
+ assert_equal true, session_options[:http_only]
22
25
  end
data/test/ssl_test.rb ADDED
@@ -0,0 +1,82 @@
1
+ require_relative "../lib/tynn/ssl"
2
+
3
+ setup do
4
+ Tynn::Test.new
5
+ end
6
+
7
+ test "redirects to https" do |app|
8
+ Tynn.helpers(Tynn::SSL)
9
+
10
+ Tynn.define do
11
+ end
12
+
13
+ app.get("/")
14
+
15
+ assert_equal 301, app.res.status
16
+ assert_equal "https://example.org/", app.res.location
17
+ end
18
+
19
+ test "https request" do |app|
20
+ Tynn.helpers(Tynn::SSL)
21
+
22
+ Tynn.define do
23
+ root do
24
+ res.write("secure")
25
+ end
26
+ end
27
+
28
+ app.get("/", {}, "HTTPS" => "on")
29
+
30
+ assert_equal "secure", app.res.body
31
+ end
32
+
33
+ test "hsts header" do |app|
34
+ Tynn.helpers(Tynn::SSL)
35
+
36
+ Tynn.define do
37
+ end
38
+
39
+ app = Tynn::Test.new
40
+ app.get("/", {}, "HTTPS" => "on")
41
+
42
+ header = app.res.headers["Strict-Transport-Security"]
43
+
44
+ assert_equal "max-age=15552000; includeSubdomains", header
45
+ end
46
+
47
+ test "hsts header options" do |app|
48
+ Tynn.helpers(Tynn::SSL, hsts: {
49
+ expires: 1,
50
+ subdomains: false,
51
+ preload: true
52
+ })
53
+
54
+ Tynn.define do
55
+ end
56
+
57
+ app = Tynn::Test.new
58
+ app.get("/", {}, "HTTPS" => "on")
59
+
60
+ header = app.res.headers["Strict-Transport-Security"]
61
+
62
+ assert_equal "max-age=1; preload", header
63
+ end
64
+
65
+ test "secure cookies" do |app|
66
+ Tynn.helpers(Tynn::SSL)
67
+
68
+ Tynn.define do
69
+ get do
70
+ res.set_cookie("first", "cookie")
71
+ res.set_cookie("other", "cookie")
72
+ end
73
+ end
74
+
75
+ app = Tynn::Test.new
76
+ app.get("/", {}, "HTTPS" => "on")
77
+
78
+ first, other = app.res.headers["Set-Cookie"].split("\n")
79
+
80
+ assert_equal "first=cookie; secure", first
81
+ assert_equal "other=cookie; secure", other
82
+ end
@@ -7,7 +7,7 @@ test "static" do
7
7
  end
8
8
 
9
9
  app = Tynn::Test.new
10
- app.get("/test/static.rb")
10
+ app.get("/test/static_test.rb")
11
11
 
12
12
  assert_equal File.read(__FILE__), app.res.body
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tynn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francesco Rodríguez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-02 00:00:00.000000000 Z
11
+ date: 2015-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -116,43 +116,51 @@ extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
118
  - ".gems"
119
+ - ".gitignore"
119
120
  - LICENSE
120
121
  - README.md
121
122
  - examples/composition.ru
122
123
  - examples/hello.ru
124
+ - examples/protection.ru
123
125
  - examples/render.ru
124
126
  - examples/views/home.erb
125
127
  - examples/views/layout.erb
126
128
  - lib/tynn.rb
127
- - lib/tynn/default_matcher.rb
129
+ - lib/tynn/csrf.rb
128
130
  - lib/tynn/environment.rb
129
131
  - lib/tynn/erubis.rb
130
132
  - lib/tynn/hmote.rb
131
- - lib/tynn/hsts.rb
132
133
  - lib/tynn/json.rb
133
134
  - lib/tynn/json_parser.rb
135
+ - lib/tynn/matchers.rb
136
+ - lib/tynn/not_found.rb
137
+ - lib/tynn/protection.rb
134
138
  - lib/tynn/render.rb
135
139
  - lib/tynn/secure_headers.rb
136
140
  - lib/tynn/send_file.rb
137
141
  - lib/tynn/session.rb
142
+ - lib/tynn/ssl.rb
138
143
  - lib/tynn/static.rb
139
144
  - lib/tynn/test.rb
140
145
  - lib/tynn/version.rb
141
146
  - makefile
142
- - test/core.rb
143
- - test/default_matcher.rb
144
- - test/environment.rb
145
- - test/erubis.rb
147
+ - test/core_test.rb
148
+ - test/csrf_test.rb
149
+ - test/environment_test.rb
150
+ - test/erubis_test.rb
146
151
  - test/helper.rb
147
- - test/hmote.rb
148
- - test/hsts.rb
149
- - test/json.rb
150
- - test/json_parser.rb
151
- - test/render.rb
152
- - test/secure_headers.rb
153
- - test/send_file.rb
154
- - test/session.rb
155
- - test/static.rb
152
+ - test/hmote_test.rb
153
+ - test/json_parser_test.rb
154
+ - test/json_test.rb
155
+ - test/matchers_test.rb
156
+ - test/not_found_test.rb
157
+ - test/protection_test.rb
158
+ - test/render_test.rb
159
+ - test/secure_headers_test.rb
160
+ - test/send_file_test.rb
161
+ - test/session_test.rb
162
+ - test/ssl_test.rb
163
+ - test/static_test.rb
156
164
  - test/views/custom_layout.erb
157
165
  - test/views/custom_layout.mote
158
166
  - test/views/layout.erb
@@ -1,7 +0,0 @@
1
- module Tynn::DefaultMatcher
2
- def default
3
- yield
4
-
5
- halt(res.finish)
6
- end
7
- end
data/lib/tynn/hsts.rb DELETED
@@ -1,23 +0,0 @@
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
@@ -1,17 +0,0 @@
1
- require_relative "../lib/tynn/default_matcher"
2
-
3
- test "default" do
4
- Tynn.helpers(Tynn::DefaultMatcher)
5
-
6
- Tynn.define do
7
- default do
8
- res.write("foo")
9
- end
10
- end
11
-
12
- app = Tynn::Test.new
13
- app.get("/")
14
-
15
- assert_equal 200, app.res.status
16
- assert_equal "foo", app.res.body
17
- end
data/test/hsts.rb DELETED
@@ -1,29 +0,0 @@
1
- require_relative "../lib/tynn/hsts"
2
-
3
- test "hsts" do
4
- Tynn.helpers(Tynn::HSTS)
5
-
6
- Tynn.define do
7
- end
8
-
9
- app = Tynn::Test.new
10
- app.get("/")
11
-
12
- header = app.res.headers["Strict-Transport-Security"]
13
-
14
- assert_equal "max-age=15552000; includeSubdomains", header
15
- end
16
-
17
- test "hsts with options" do
18
- Tynn.helpers(Tynn::HSTS, max_age: 1, preload: true)
19
-
20
- Tynn.define do
21
- end
22
-
23
- app = Tynn::Test.new
24
- app.get("/")
25
-
26
- header = app.res.headers["Strict-Transport-Security"]
27
-
28
- assert_equal "max-age=1; includeSubdomains; preload", header
29
- end