da99_rack_protect 2.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b2e6ef07cf45beee6e0e040c99df3c5f63a6c6f1
4
+ data.tar.gz: 551bfa85f643a26860b241a386e1ed752b6426a5
5
+ SHA512:
6
+ metadata.gz: 50fbd480139dcc53acd2b97106be75f9a823702c8926e9861f5b581facc4490488ae89cfae7012b3df76eb6bd4beeedeefcd07fc8543323c286c1ddaddd98de5
7
+ data.tar.gz: dca52f395017f3b6312d0064c8dd2520e01fd2d8964dbcb8a2473ab7dfb8209bed60ad45d509ad72272044e8da1eca4dbaf6194886f3b5ca6d1b6dd80ea57559
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ tmp/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+
2
+ Copyright (c) 2014 da99
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ rack\_protect
2
+ ===============
3
+
4
+ My favorite rack middleware in one package.
5
+
6
+ Notes:
7
+ ================
8
+
9
+ 1) `HTTP\_HOST`: Unreliable because it is sent by client.
10
+ Use `SERVER\_NAME`
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.0.2
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "da99_rack_protect"
7
+ spec.version = `cat VERSION`
8
+ spec.authors = ["da99"]
9
+ spec.email = ["i-hate-spam-1234567@mailinator.com"]
10
+ spec.summary = %q{My personal list of rack middlewares for web apps.}
11
+ spec.description = %q{
12
+ Various rack middlewares I use for projects.
13
+ I got tired of copying/pasting the same ones for
14
+ different apps.
15
+ }
16
+ spec.homepage = "https://github.com/da99/da99_rack_protect"
17
+ spec.license = "MIT"
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject { |file|
20
+ file.index('bin/') == 0 && file != "bin/#{File.basename Dir.pwd}"
21
+ }
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_runtime_dependency "rack-protection" , "> 1.5"
27
+
28
+ spec.add_development_dependency "pry" , "> 0.9"
29
+ spec.add_development_dependency "bundler" , "> 1.5"
30
+ spec.add_development_dependency "bacon" , "> 1.0"
31
+ spec.add_development_dependency "Bacon_Colored" , "> 0.1"
32
+ spec.add_development_dependency "cuba" , "> 3.2"
33
+ spec.add_development_dependency "thin" , "> 1.6"
34
+ end
@@ -0,0 +1,24 @@
1
+
2
+ class Da99_Rack_Protect
3
+ class Allow_Only_Roman_Uri
4
+
5
+ INVALID = /[^a-zA-Z0-9\_\-\/\.\?\@\*\=]+/
6
+ INVALID_QUERY = /[^a-zA-Z0-9\_\-\/\.\?\@\*\=\(\)\%\&]+/
7
+
8
+ def initialize new_app
9
+ @app = new_app
10
+ end
11
+
12
+ def call new_env
13
+ path_invalid = new_env['PATH_INFO'][INVALID]
14
+ qs_invalid = new_env['QUERY_STRING'][INVALID_QUERY]
15
+ if path_invalid || qs_invalid
16
+ content = "Page not found. \nReason: Invalid chars in page address: #{[path_invalid, qs_invalid].compact.join}"
17
+ DA99.response 400, :text, content
18
+ else
19
+ @app.call new_env
20
+ end
21
+ end
22
+
23
+ end # === Allow_Only_Roman_Uri
24
+ end # === Da99_Rack_Protect
@@ -0,0 +1,23 @@
1
+ class Da99_Rack_Protect
2
+ class Squeeze_Uri_Dots
3
+
4
+ DOTS_AND_SLASHES = /(\.+\/)|(\/\.+)/
5
+ DOTS = /\.\.+/
6
+
7
+ def initialize new_app
8
+ @app = new_app
9
+ end
10
+
11
+ # Using :REQUEST_URI includes query string
12
+ def call new_env
13
+ old = new_env['REQUEST_URI']
14
+ new = new_env['REQUEST_URI'].gsub(DOTS_AND_SLASHES, '/'.freeze).gsub(DOTS, '.'.freeze)
15
+ if new != old
16
+ DA99.redirect new, 301
17
+ else
18
+ @app.call new_env
19
+ end
20
+ end
21
+
22
+ end # === Squeeze_Uri_Dots
23
+ end # === Da99_Rack_Protect
@@ -0,0 +1,35 @@
1
+ class Da99_Rack_Protect
2
+ class No_Slash_Path_Ending
3
+
4
+ METHODS = ['HEAD', 'GET']
5
+ SLASH = '/'
6
+ LAST_SLASH = /\/\z/
7
+
8
+ def initialize new_app
9
+ @app = new_app
10
+ end
11
+
12
+ def call new_env
13
+
14
+ remove_slash = begin
15
+ new_env['PATH_INFO'] != SLASH &&
16
+ METHODS.include?(new_env['REQUEST_METHOD']) &&
17
+ new_env['PATH_INFO'][-1,1] == SLASH &&
18
+ File.extname(new_env['PATH_INFO']) === ''
19
+ end
20
+
21
+ return(@app.call( new_env )) unless remove_slash
22
+
23
+ req = Rack::Request.new(new_env)
24
+ response = Rack::Response.new
25
+
26
+ qs = req.query_string.strip.empty? ? nil : req.query_string
27
+ new = [ req.path_info.sub(LAST_SLASH, ''), qs ].compact.join('?')
28
+
29
+ response.redirect( new, 301 ) # permanent
30
+ response.finish
31
+
32
+ end
33
+
34
+ end # === Slashify_Path_Ending
35
+ end # === Da99_Rack_Protect
@@ -0,0 +1,18 @@
1
+ class Da99_Rack_Protect
2
+ class Root_Favicon_If_Not_Found
3
+
4
+ NON_ROOT_ICO = /.+\/favicon\.ico\z/
5
+ ROOT_ICO = '/favicon.ico'
6
+
7
+ def initialize new_app
8
+ @app = new_app
9
+ end
10
+
11
+ def call e
12
+ status, headers, body = @app.call( e )
13
+ return [status, headers, body] unless status == 404 && e['PATH_INFO'][NON_ROOT_ICO]
14
+ DA99.redirect ROOT_ICO, 302 # Permanent
15
+ end
16
+
17
+ end # === Root_Favicon_If_Not_Found
18
+ end # === Da99_Rack_Protect
@@ -0,0 +1,35 @@
1
+
2
+ class Da99_Rack_Protect
3
+
4
+ class Ensure_Host
5
+
6
+ SERVER_NAME = 'SERVER_NAME'
7
+ LOCALHOST = /\A(localhost|127\.0\.0\.1)\z/
8
+ HTT_HOST = 'HTTP_HOST'
9
+
10
+ def initialize new_app
11
+ @app = new_app
12
+ end
13
+
14
+ def call e
15
+ hosts = Da99_Rack_Protect::HOSTS
16
+ name = e[SERVER_NAME]
17
+ host = e[HTT_HOST]
18
+
19
+ is_valid = hosts.include?(name)
20
+
21
+ if !is_valid
22
+ is_local = hosts.include?(:localhost) && name[LOCALHOST]
23
+ is_valid = is_local
24
+ end
25
+
26
+ is_match = host[/\A#{name}(:\d+)?\z/]
27
+
28
+ return @app.call(e) if is_valid && is_match
29
+ Da99_Rack_Protect.response 444, :text, 'Unknown error.'
30
+ end
31
+
32
+ end # === class Ensure_Host
33
+
34
+
35
+ end # === class Da99_Rack_Protect
@@ -0,0 +1,21 @@
1
+
2
+ class Da99_Rack_Protect
3
+
4
+ class No_Old_MSIE
5
+
6
+ UA = /; MSIE (\d)\.\d/
7
+ def initialize new_app
8
+ @app = new_app
9
+ end
10
+
11
+ def call e
12
+ if e['HTTP_USER_AGENT'].to_s[UA] && $1.to_i < 9
13
+ return DA99.response 400, :text, "Page inaccessible because you are using an old browser: MSIE #{$1}"
14
+ end
15
+ @app.call e
16
+ end
17
+
18
+ end # === class No_Old_MSIE
19
+
20
+
21
+ end # === class Da99_Rack_Protect
@@ -0,0 +1,139 @@
1
+
2
+ require 'rack/protection'
3
+
4
+ class Da99_Rack_Protect
5
+
6
+ HOSTS = []
7
+ DA99 = self
8
+
9
+ # =================================================================
10
+ #
11
+ # I need to know if new middleware has been added
12
+ # to `rack-protection` so it can be properly
13
+ # used (or ignored) by Da99_Rack_Protect.
14
+ #
15
+ # =================================================================
16
+ RACK_PROTECTS_DIR = File.join File.dirname(`gem which rack-protection`.strip), '/rack/protection'
17
+ RACK_PROTECTS = Dir.glob(RACK_PROTECTS_DIR + '/*').map { |f|
18
+ File.basename(f).sub('.rb', '')
19
+ }.sort
20
+
21
+ Ignore_Rack_Protects = %w{ base version escaped_params remote_referrer }
22
+ Known_Rack_Protects = %w{
23
+ authenticity_token
24
+ form_token
25
+ frame_options
26
+ http_origin
27
+ ip_spoofing
28
+ json_csrf
29
+ path_traversal
30
+ remote_token
31
+ session_hijacking
32
+ xss_header
33
+ }
34
+
35
+ Rack_Protection_Names = {'ip_spoofing' => :IPSpoofing, 'xss_header'=>:XSSHeader}
36
+
37
+ Unknown_Rack_Protects = RACK_PROTECTS - Known_Rack_Protects - Ignore_Rack_Protects
38
+
39
+ if !Unknown_Rack_Protects.empty?
40
+ fail "Unknown rack-protection middleware: #{Unknown_Rack_Protects.inspect}"
41
+ end
42
+
43
+ require 'rack/protection/base'
44
+ Known_Rack_Protects.each { |name|
45
+ require "rack/protection/#{name}"
46
+ official_name = begin
47
+ Rack_Protection_Names[name] ||= name.split('_').map(&:capitalize).join.to_sym
48
+ end
49
+
50
+ Rack::Protection.const_get(official_name)
51
+ }
52
+ # =================================================================
53
+
54
+ dir = File.expand_path(File.dirname(__FILE__) + '/da99_rack_protect')
55
+ files = Dir.glob(dir + '/*.rb').sort
56
+ Names = files.map { |file|
57
+ base = File.basename(file).sub('.rb', '')
58
+ require "da99_rack_protect/#{base}"
59
+ pieces = base.split('_')
60
+ pieces.shift
61
+ pieces.join('_').to_sym
62
+ }
63
+
64
+ class << self
65
+
66
+ def config *args
67
+ yield(self) if block_given?
68
+ case args.length
69
+ when 0
70
+ # do nothing
71
+
72
+ when 2
73
+
74
+ case args.first
75
+
76
+ when :host
77
+ HOSTS.concat args.last
78
+
79
+ else
80
+ fail "Unknown args: #{args.inspect}"
81
+
82
+ end # === case
83
+
84
+ else
85
+ fail "Unknown args: #{args.inspect}"
86
+ end # === case
87
+
88
+ self
89
+ end # === def config
90
+
91
+ def redirect new, code = 301
92
+ res = Rack::Response.new
93
+ res.redirect new, code
94
+ res.finish
95
+ end
96
+
97
+ def response code, type, raw_content
98
+ content = raw_content.to_s
99
+ res = Rack::Response.new
100
+ res.status = code.to_i
101
+ res.headers['Content-Length'] = content.bytesize.to_s
102
+ res.headers['Content-Type'] = 'text/plain'.freeze
103
+ res.body = [content]
104
+ res.finish
105
+ end
106
+
107
+ end # === class self
108
+
109
+ def initialize main_app
110
+ @app = Rack::Builder.new do
111
+
112
+ use Rack::Lint
113
+ use Rack::ContentLength
114
+ use Rack::ContentType, "text/plain"
115
+ use Rack::MethodOverride
116
+ use Rack::Session::Cookie, secret: SecureRandom.urlsafe_base64(nil, true)
117
+
118
+ Known_Rack_Protects.each { |name|
119
+ use Rack::Protection.const_get(Rack_Protection_Names[name])
120
+ }
121
+
122
+ Names.each { |name|
123
+ use Da99_Rack_Protect.const_get(name)
124
+ }
125
+
126
+ if ENV['IS_DEV']
127
+ use Rack::CommonLogger
128
+ use Rack::ShowExceptions
129
+ end
130
+
131
+ run main_app
132
+ end
133
+ end
134
+
135
+ def call env
136
+ @app.call env
137
+ end
138
+
139
+ end # === class Da99_Rack_Protect ===
@@ -0,0 +1,129 @@
1
+
2
+ RACK_PROTECTS_DIR = File.join File.dirname(`gem which rack-protection`.strip), '/rack/protection'
3
+ RACK_PROTECTS = Dir.glob(RACK_PROTECTS_DIR + '/*').map { |f|
4
+ File.basename(f).sub('.rb', '')
5
+ }.sort
6
+
7
+
8
+ describe Da99_Rack_Protect do
9
+
10
+ it "runs" do
11
+ get(:http_code, '/').should == 200
12
+ end
13
+
14
+ it "does not have duplicates in Ignore_Rack_Protects, Known_Rack_Protects" do
15
+ (Da99_Rack_Protect::Ignore_Rack_Protects & Da99_Rack_Protect::Known_Rack_Protects).
16
+ should.be.empty
17
+ end
18
+
19
+ it "sets X-Frame-Options header to: SAMEORIGIN" do
20
+ get(:x_frame_options, '/').should == 'SAMEORIGIN'
21
+ end
22
+
23
+ it "returns 400 if browser is MSIE 6" do
24
+ get(:http_code, '/', '--header "User-Agent: Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)"').
25
+ should == 400
26
+ end
27
+
28
+ it "returns 400 if browser is MSIE 7" do
29
+ get(:http_code, '/', '--header "User-Agent: Mozilla/4.0(compatible; MSIE 7.0b; Windows NT 6.0)"').
30
+ should == 400
31
+ end
32
+
33
+ it "returns 400 if browser is MSIE 8" do
34
+ get(:http_code, '/', '--header "User-Agent: Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)"').
35
+ should == 400
36
+ end
37
+
38
+ describe 'unknown rack protect' do
39
+
40
+ before { @random_file = RACK_PROTECTS_DIR + '/random_rack_file.rb' }
41
+
42
+ after { `rm -f #{@random_file}` }
43
+
44
+ it "fails if unknown rack-protection middleware is found" do
45
+ `touch #{@random_file}`
46
+ `ruby -e "require 'da99_rack_protect'" 2>&1`.
47
+ should.match /Unknown rack-protection middleware: ..random_rack_file.. \(/
48
+ end
49
+
50
+ end # === describe
51
+
52
+ end # === describe da99_rack_protect ===
53
+
54
+ describe Da99_Rack_Protect::Allow_Only_Roman_Uri do
55
+
56
+ it "returns 400 if uri has non-roman chars" do
57
+ get(:http_code, '/()').should == 400
58
+ end
59
+
60
+ it "returns 400 if query string has invalid chars: @+" do
61
+ get(:http_code, '/?@+').should == 400
62
+ end
63
+
64
+ it "output 'Invalid chars' in content" do
65
+ get(:output, '/()').should.match /Invalid chars/
66
+ end
67
+
68
+ it "allows special chars in query string: /?module=allow%20(event)&testNum=48" do
69
+ get(:http_code, '/?module=allow%20(event)').should == 200
70
+ end
71
+
72
+ end # === describe Allow_Only_Roman_Uri
73
+
74
+ describe Da99_Rack_Protect::Squeeze_Uri_Dots do
75
+
76
+ it "squeezes multiple dots into one" do
77
+ code, url = get(:redirect, '/hello.....rb')
78
+ code.should == 301
79
+ url.should.match /\/hello\.rb/
80
+ end
81
+
82
+ it "replaces .../ with /" do
83
+ code, url = get(:redirect, '/hello.../abc')
84
+ code.should == 301
85
+ url.should.match /\/hello\/abc/
86
+ end
87
+
88
+ it "replaces /... with /" do
89
+ code, url = get(:redirect, '/hello/...h')
90
+ code.should == 301
91
+ url.should.match /\/hello\/h/
92
+ end
93
+
94
+ end # === describe Squeeze_Uri_Dots
95
+
96
+ describe Da99_Rack_Protect::No_Slash_Path_Ending do
97
+
98
+ it "redirects to path with no ending slash" do
99
+ code, url = get(:redirect, '/slash/')
100
+ code.should == 301
101
+ url.should.match /\/slash\z/
102
+ end
103
+
104
+ end # === describe No_Slash_Path_Ending
105
+
106
+ describe Da99_Rack_Protect::Root_Favicon_If_Not_Found do
107
+
108
+ it "redirects to /favicon.ico if deeper ico file not found." do
109
+ code, url = get(:redirect, '/something/favicon.ico')
110
+ code.should == 302
111
+ url.should.match /\:4567\/favicon.ico/
112
+ end
113
+
114
+ it "does not redirect /favicon.ico" do
115
+ get(:http_code, '/favicon.ico').should == 404
116
+ end
117
+
118
+ end # === describe Root_Favicon_If_Not_Found
119
+
120
+ describe Da99_Rack_Protect::Ensure_Host do
121
+
122
+ it "returns a 444 error if host does not match allowed hosts" do
123
+ get(:http_code, '/', '--header "Host: MEGA"').should == 444
124
+ end
125
+
126
+ end # === describe Da99_Rack_Protect::Ensure_Host ===
127
+
128
+
129
+
@@ -0,0 +1,23 @@
1
+
2
+ require 'cuba'
3
+ require 'da99_rack_protect'
4
+
5
+ Cuba.use Da99_Rack_Protect.config { |c|
6
+ c.config :host, [:localhost, 'da99_sample.com']
7
+ }
8
+
9
+ if ENV['IS_DEV']
10
+ Cuba.use Rack::ShowExceptions
11
+ end
12
+
13
+ Cuba.define do
14
+
15
+ on get do
16
+ on(root) { res.write "Root" }
17
+ on('hello') { res.write 'Hello' }
18
+ on('hello/s') { res.write 'Hello/' }
19
+ end
20
+
21
+ end
22
+
23
+ run Cuba
@@ -0,0 +1,33 @@
1
+
2
+ require 'Bacon_Colored'
3
+ require 'pry'
4
+ require 'da99_rack_protect'
5
+
6
+ def get var, path, append = ''
7
+ url = "http://localhost:#{ENV['PORT']}#{path}"
8
+
9
+ case var
10
+
11
+ when :x_frame_options
12
+ `bin/get -D - -o /dev/null "#{url}" #{append}`.strip[/X-Frame-Options: (.+)$/] && ($1 || '').strip
13
+
14
+ when :http_code
15
+ `bin/get -w "%{#{var}}" "#{url}" #{append}`.strip.to_i
16
+
17
+ when :redirect_url
18
+ `bin/get -w "%{#{var}}" "#{url}" #{append}`.strip
19
+
20
+ when :redirect
21
+ raw = `bin/get -w '%{http_code} %{redirect_url}' "#{url}" #{append}`
22
+ pieces = raw.strip.split
23
+ pieces[0] = pieces[0].to_i
24
+ pieces
25
+
26
+ when :output
27
+ `bin/get "#{url}" #{append}`
28
+
29
+ else
30
+ fail "Unknown option: #{var.inspect}"
31
+
32
+ end # === case var
33
+ end # === def get
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: da99_rack_protect
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.2
5
+ platform: ruby
6
+ authors:
7
+ - da99
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack-protection
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bacon
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: Bacon_Colored
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: cuba
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: thin
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.6'
111
+ description: "\n Various rack middlewares I use for projects.\n I got tired
112
+ of copying/pasting the same ones for\n different apps.\n "
113
+ email:
114
+ - i-hate-spam-1234567@mailinator.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - VERSION
124
+ - da99_rack_protect.gemspec
125
+ - lib/da99_rack_protect.rb
126
+ - lib/da99_rack_protect/0010_Allow_Only_Roman_Uri.rb
127
+ - lib/da99_rack_protect/0020_Squeeze_Uri_Dots.rb
128
+ - lib/da99_rack_protect/0030_No_Slash_Path_Ending.rb
129
+ - lib/da99_rack_protect/0040_Root_Favicon_If_Not_Found.rb
130
+ - lib/da99_rack_protect/0050_Ensure_Host.rb
131
+ - lib/da99_rack_protect/0050_No_Old_MSIE.rb
132
+ - specs/da99_rack_protect.rb
133
+ - specs/helpers/config.ru
134
+ - specs/helpers/helpers.rb
135
+ homepage: https://github.com/da99/da99_rack_protect
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.4.5
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: My personal list of rack middlewares for web apps.
159
+ test_files: []