tynn 0.0.2 → 0.0.3

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
  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