strict_request_uri 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 738571a4631e7084c03451d4fd855a6c3cc0ed70
4
+ data.tar.gz: ac07e480bb801f3ff018354ea1589243415b66a3
5
+ SHA512:
6
+ metadata.gz: 582c0060f97ccfb5dba596ab0c9d8a4f5c23acf364a57d7b21077ff66c20cd42a020f4e2d0380dff439c876ee88a00ff9b349099e4b576f19cc92e3a35e14835
7
+ data.tar.gz: 36eb35790951f82a32eba98f78feed081d5b9558010089950ab28cae62f5ebe37230415cbc83a7f658ee63223a0bc83881260e2b71ea8df8e7b13cb1d92382e5
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 2.1
3
+ - 2.2
4
+ - 2.3.0
5
+ - jruby-9.0
6
+ sudo: false
7
+ cache: bundler
8
+ script: bundle exec rspec
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'rack', '~> 1'
4
+
5
+ group :development do
6
+ gem 'gemfury'
7
+ gem "rspec", "~> 3.0"
8
+ gem "rdoc", "~> 3.12"
9
+ gem "bundler", "~> 1.0"
10
+ gem "jeweler", "~> 2.2.1"
11
+ gem "simplecov", ">= 0"
12
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 WeTransfer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # strict_request_uri
2
+
3
+ [![Build Status](https://travis-ci.org/WeTransfer/strict_request_uri.svg?branch=master)](https://travis-ci.org/WeTransfer/strict_request_uri)
4
+
5
+ ![Nasty URL](images/strict_uri.png)
6
+
7
+ Reject requests with an invalid REQUEST_URI at the gate.
8
+ Some HTTP clients will happily append raw junk bytes to your URL before doing a request. Others
9
+ will first append junk, and then URL-encode it.
10
+
11
+ What you want for a valid URL is something that is
12
+
13
+ * properly URL-encoded
14
+ * is valid UTF-8 once URL-decoded
15
+
16
+ This gem provides a Rack middleware that is going to try to decode REQUEST_URI, and if it
17
+ cannot be decoded, an error page will be rendered instead.
18
+
19
+ use StrictRequestUri do |env|
20
+ # You can use the preserved invalid path+qs to do additional checks/logging
21
+ logger.warn "Invalid URL received"
22
+ logger.warn env['strict_uri.original_invalid_url']
23
+
24
+ # You can also render a suggestion or redirect based on the suggested fixed URL.
25
+ # The fixed URL will have all junk at the end removed until the string becomes a valid URL.
26
+ logger.warn "Suggested instead:"
27
+ logger.warn env['strict_uri.proposed_fixed_url']
28
+
29
+ [400, {'Content-Type' => 'text/plain'}, ['This is a no go mate']]
30
+ end
31
+
32
+ Note that `PATH_INFO` and `QUERY_STRING` variables in Rack env are going to be replaced
33
+ with something harmless (because they get used to render self-URLs and so on).
34
+
35
+ You can also use it in your Rails middleware stack, and render a controller in return
36
+
37
+ Rails.application.config.middleware.insert_after 'Warden::Manager', StrictRequestUri do | env |
38
+ ErrorPagesController.action(:invalid_url).call(env)
39
+ end
40
+
41
+
42
+ ## Contributing to strict_request_uri
43
+
44
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
45
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
46
+ * Fork the project.
47
+ * Start a feature/bugfix branch.
48
+ * Commit and push until you are happy with your contribution.
49
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
50
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
51
+
52
+ ## Copyright
53
+
54
+ Copyright (c) 2016 WeTransfer. See LICENSE.txt for
55
+ further details.
56
+
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require_relative 'lib/strict_request_uri'
15
+
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |gem|
18
+ gem.version = StrictRequestUri::VERSION
19
+ gem.name = "strict_request_uri"
20
+ gem.homepage = "https://github.com/WeTransfer/strict_request_uri"
21
+ gem.license = "MIT"
22
+ gem.description = %Q{Reject Rack requests with an invalid URL}
23
+ gem.summary = %Q{and show an error page instead}
24
+ gem.email = "me@julik.nl"
25
+ gem.authors = ["Julik Tarkhanov"]
26
+ # dependencies defined in Gemfile
27
+ end
28
+ # Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rspec/core'
31
+ require 'rspec/core/rake_task'
32
+ RSpec::Core::RakeTask.new(:spec) do |spec|
33
+ spec.pattern = FileList['spec/**/*_spec.rb']
34
+ end
35
+
36
+ desc "Code coverage detail"
37
+ task :simplecov do
38
+ ENV['COVERAGE'] = "true"
39
+ Rake::Task['spec'].execute
40
+ end
41
+
42
+ task :default => :spec
43
+
44
+ require 'rdoc/task'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "strict_request_uri #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
53
+
54
+ namespace :fury do
55
+ desc "Pick up the .gem file from pkg/ and push it to Gemfury"
56
+ task :release do
57
+ # IMPORTANT: You need to have the `fury` gem installed, and you need to be logged in.
58
+ # Please DO READ about "impersonation", which is how you push to your company account instead
59
+ # of your personal account!
60
+ # https://gemfury.com/help/collaboration#impersonation
61
+ paths = Dir.glob(__dir__ + '/pkg/*.gem')
62
+ if paths.length != 1
63
+ raise "Must have found only 1 .gem path, but found %s" % paths.inspect
64
+ end
65
+ escaped_gem_path = Shellwords.escape(paths.shift)
66
+ `fury push #{escaped_gem_path} --as=wetransfer`
67
+ end
68
+ end
69
+ task :release => [:clean, 'gemspec:generate', 'git:release', :build, 'fury:release']
data/images/icon.png ADDED
Binary file
Binary file
@@ -0,0 +1,103 @@
1
+ require 'rack'
2
+
3
+ # Sometimes junk gets appended to the URLs clicked in e-mails.
4
+ # This junk then gets sent by browsers undecoded, and causes Unicode-related
5
+ # exceptions when the full request URI or path is rebuilt for ActionDispatch.
6
+ #
7
+ # We can fix this by iteratively removing bytes from the end of the URL until it becomes parseable.
8
+ #
9
+ # We do however answer to those URLs with a 400 to indicate clients that those requests are not
10
+ # welcome. This also allows us to tell the users that they are using a URL which is in fact
11
+ # not really valid.
12
+ class StrictRequestUri
13
+ VERSION = '1.0.2'
14
+
15
+ # Inits the middleware. The optional proc should be a Rack application that
16
+ # will render the error page. To make a controller render that page,
17
+ # use <ControllerClass>.action()
18
+ #
19
+ # use RequestUriCleanup do | env |
20
+ # ErrorsController.action(:invalid_request).call(env)
21
+ # end
22
+ def initialize(app, &error_page_rack_app)
23
+ @app = app
24
+ @error_page_app = if error_page_rack_app
25
+ error_page_rack_app
26
+ else
27
+ ->(env) { [400, {'Content-Type' => 'text/plain'}, ['Invalid request URI']] }
28
+ end
29
+ end
30
+
31
+ def call(env)
32
+ # Compose the original URL, taking care not to treat it as UTF8.
33
+ # Do not use Rack::Request since it is not really needed for this
34
+ # (and _might be doing something with strings that we do not necessarily want).
35
+ # For instance, Rack::Request does regexes when you ask it for the REQUEST_URI
36
+ tainted_url = reconstruct_original_url(env)
37
+ return @app.call(env) if string_parses_to_url?(tainted_url)
38
+
39
+ # At this point we know the URL is fishy.
40
+ referer = to_utf8(env['HTTP_REFERER'] || '(unknown)')
41
+ env['rack.errors'].puts("Invalid URL received from referer #{referer}") if env['rack.errors']
42
+
43
+ # Save the original URL so that the error page can use it
44
+ env['strict_uri.original_invalid_url'] = tainted_url
45
+ env['strict_uri.proposed_fixed_url'] =
46
+ truncate_bytes_at_end_until_parseable(tainted_url)
47
+
48
+ # Strictly speaking, the parts we are going to put into QUERY_STRING and PATH_INFO
49
+ # should _only_ be used for rendering the error page, and that's it.
50
+ #
51
+ # We can therefore wipe them clean.
52
+ env['PATH_INFO'] = '/invalid-url'
53
+ env['QUERY_STRING'] = ''
54
+
55
+ # And render the error page using the provided error app.
56
+ @error_page_app.call(env)
57
+ end
58
+
59
+ private
60
+
61
+ # Reconstruct the original URL from the Rack env variables, converting them to
62
+ # binary encoding before joining them together. This ensures the "bad" bits stay
63
+ # broken and no errors are raised.
64
+ def reconstruct_original_url(env)
65
+ original_url_components = env.values_at('SCRIPT_NAME', 'PATH_INFO')
66
+ unless env['QUERY_STRING'].empty?
67
+ original_url_components << '?'
68
+ original_url_components << env['QUERY_STRING']
69
+ end
70
+ original_url_components.map{|e| e.unpack("C*").pack("C*") }.join
71
+ end
72
+
73
+ def string_parses_to_url?(string)
74
+ # We can have two sorts of possible damage.
75
+ # First sort is when raw garbage bytes just get added to the URL.
76
+ # This can be caught by attempting to parse the URL with URI().
77
+ parsed_uri = URI(string)
78
+ # The second kind of damage is when there _is_ in fact a normal URL-encoded
79
+ # character, which URI() will happily swallow - but this character is not valid
80
+ # UTF-8 and will make the Rails router crash. For our purposes it _also_ means
81
+ # the URL has been damaged bayound repair.
82
+ decoded_uri = Rack::Utils.unescape(string).unpack("U*")
83
+ true
84
+ rescue URI::InvalidURIError, ArgumentError
85
+ false
86
+ end
87
+
88
+ def to_utf8(str, repl_char='?')
89
+ str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: repl_char)
90
+ end
91
+
92
+ # Chops off one byte from the given string iteratively, until the string can be parsed
93
+ # using URI() _and_ decoded using Rack::Utils.unescape.
94
+ def truncate_bytes_at_end_until_parseable(str)
95
+ cutoff = -1
96
+ until str.empty? do
97
+ str = str[0..cutoff]
98
+ return str if string_parses_to_url?(str)
99
+ cutoff -= 1
100
+ end
101
+ ''
102
+ end
103
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rspec'
5
+ require 'strict_request_uri'
6
+
7
+ RSpec.configure do |config|
8
+ config.order = 'random'
9
+ end
@@ -0,0 +1,205 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe StrictRequestUri do
4
+ context 'with a good URL' do
5
+ it 'returns the downstream response for URLs without a query string' do
6
+ env_with_valid_chars = {
7
+ 'SCRIPT_NAME' => 'myscript',
8
+ 'PATH_INFO' => '/items/457',
9
+ 'QUERY_STRING' => ''
10
+ }
11
+ app = ->(env) {
12
+ expect(env['QUERY_STRING']).to eq('')
13
+ expect(env['SCRIPT_NAME']).to eq('myscript')
14
+ expect(env['PATH_INFO']).to eq('/items/457')
15
+ :total_success
16
+ }
17
+ expect(described_class.new(app).call(env_with_valid_chars)).to eq(:total_success)
18
+ end
19
+
20
+ it 'returns the downstream response for URLs with a query string' do
21
+ env_with_valid_chars = {
22
+ 'SCRIPT_NAME' => 'myscript',
23
+ 'PATH_INFO' => '/items/457',
24
+ 'QUERY_STRING' => 'foo=bar'
25
+ }
26
+ app = ->(env) {
27
+ expect(env['QUERY_STRING']).to eq('foo=bar')
28
+ expect(env['SCRIPT_NAME']).to eq('myscript')
29
+ expect(env['PATH_INFO']).to eq('/items/457')
30
+ :total_success
31
+ }
32
+ expect(described_class.new(app).call(env_with_valid_chars)).to eq(:total_success)
33
+ end
34
+ end
35
+
36
+ context 'with a garbage URL' do
37
+ it 'calls the default error app if none was set' do
38
+ # All of those 3 components are required as per Rack spec
39
+ env_with_invalid_chars = {
40
+ 'SCRIPT_NAME' => '',
41
+ 'PATH_INFO' => [107, 17, 52, 140].pack("C*"),
42
+ 'QUERY_STRING' => '',
43
+ }
44
+
45
+ middleware = described_class.new(nil) # will raise if the wrapped app is called
46
+ status, headers, body = middleware.call(env_with_invalid_chars)
47
+ expect(status).to eq(400)
48
+ expect(headers).to eq({'Content-Type' => 'text/plain'})
49
+ expect(body).to eq(['Invalid request URI'])
50
+ end
51
+
52
+ it 'with junk after the path calls the error app instead' do
53
+ # The related bug ticket - https://www.assembla.com/spaces/wetransfer-2-0/tickets/1568
54
+ script_name = 'myscript'
55
+ valid_part = '/items/457'
56
+ invalid_part = [107, 17, 52, 140].pack("C*")
57
+ invalid_path_info = valid_part.encode(Encoding::BINARY) + invalid_part
58
+
59
+ expect {
60
+ invalid_path_info.encode(Encoding::UTF_8)
61
+ }.to raise_error(Encoding::UndefinedConversionError)
62
+
63
+ # All of those 3 components are required as per Rack spec
64
+ env_with_invalid_chars = {
65
+ 'SCRIPT_NAME' => script_name,
66
+ 'PATH_INFO' => invalid_path_info,
67
+ 'QUERY_STRING' => '',
68
+ 'rack.errors' => double('IO')
69
+ }
70
+
71
+ # Do not render from the controller since we do not have a complete Rack env hash initialized.
72
+ # Instead, sneak in our own testing Proc.
73
+ error_handling_app = ->(env) {
74
+ # Make sure those are now safe to concat with each other
75
+ expect(env['SCRIPT_NAME']).to eq("myscript")
76
+ expect(env['PATH_INFO']).to eq("/invalid-url")
77
+ expect(env['QUERY_STRING']).to eq('')
78
+
79
+ # Make sure the original broken URL is stashed somewhere for the error page to act on
80
+ expect(env['strict_uri.original_invalid_url']).to include(script_name)
81
+ expect(env['strict_uri.original_invalid_url']).to include(invalid_path_info)
82
+ expect(env['strict_uri.proposed_fixed_url']).to eq("myscript/items/457k")
83
+
84
+ # Ensure those are valid - if this call raises the spec will fail
85
+ env['PATH_INFO'].encode(Encoding::UTF_8)
86
+
87
+ [200, {'Content-Type' => 'text/plain'}, ['This is an error message']]
88
+ }
89
+
90
+ expect(env_with_invalid_chars['rack.errors']).to receive(:puts).
91
+ with("Invalid URL received from referer (unknown)")
92
+
93
+ middleware = described_class.new(nil, &error_handling_app) # will raise if the wrapped app is called
94
+ status, headers, body = middleware.call(env_with_invalid_chars)
95
+ expect(status).to eq(200)
96
+ expect(headers).to eq({'Content-Type' => 'text/plain'})
97
+ end
98
+
99
+ it 'after the query string calls the error app instead' do
100
+ # The related bug ticket - https://www.assembla.com/spaces/wetransfer-2-0/tickets/1568
101
+ script_name = 'myscript'
102
+ valid_path_info = '/items/457'
103
+ query_string = 'foo=bar&baz=bad'
104
+ invalid_part = [107, 17, 52, 140].pack("C*")
105
+ invalid_qs = query_string.encode(Encoding::BINARY) + invalid_part
106
+
107
+ expect {
108
+ invalid_qs.encode(Encoding::UTF_8)
109
+ }.to raise_error(Encoding::UndefinedConversionError)
110
+
111
+ # All of those 3 components are required as per Rack spec
112
+ env_with_invalid_chars = {
113
+ 'SCRIPT_NAME' => script_name,
114
+ 'PATH_INFO' => valid_path_info,
115
+ 'QUERY_STRING' => invalid_qs,
116
+ 'HTTP_REFERER' => 'https://megacorp.co/webmail.asp',
117
+ 'rack.errors' => double('IO')
118
+ }
119
+
120
+ error_handling_app = ->(env) {
121
+ # Make sure those are now safe to concat with each other
122
+ expect(env['SCRIPT_NAME']).to eq("myscript")
123
+ expect(env['PATH_INFO']).to eq("/invalid-url")
124
+ expect(env['QUERY_STRING']).to eq('')
125
+
126
+ expect(env['strict_uri.original_invalid_url']).to include(valid_path_info)
127
+ expect(env['strict_uri.original_invalid_url']).to include(invalid_qs)
128
+
129
+ # Ensure those are valid - if this call raises the spec will fail
130
+ env['QUERY_STRING'].encode(Encoding::UTF_8)
131
+
132
+ [200, {'Content-Type' => 'text/plain'}, ['This is an error message']]
133
+ }
134
+ expect(env_with_invalid_chars['rack.errors']).to receive(:puts).
135
+ with('Invalid URL received from referer https://megacorp.co/webmail.asp')
136
+
137
+ # nil will raise if the wrapped app is called
138
+ middleware = described_class.new(nil, &error_handling_app)
139
+ status, headers, body = middleware.call(env_with_invalid_chars)
140
+ expect(status).to eq(200)
141
+ expect(headers).to eq({'Content-Type' => 'text/plain'})
142
+ end
143
+ end
144
+
145
+ context 'with production examples of garbled PATH_INFO' do
146
+ it 'triggers with URL-encoded bytes that are invalid UTF-8 when decoded' do
147
+ # Example from production - here at the end of the url you have
148
+ # \xC2 in percent-encoded form, which cannot be converted to UTF-8.
149
+ # If we let it through, it _can_ be rendered using request.original_url
150
+ # but _cannot_ be used by Journey when url_for is called.
151
+ #
152
+ # So we have to intercept this as well.
153
+ path = '/downloads/918ab1e20586c0b4e1875b3789b84ec720150615173920' +
154
+ '/a480d026f46b0f0533cec47545cd5e2820150615173920/0130a0%C2'
155
+ fake_action = ->(env) {
156
+ # Make sure those are now safe to concat with each other
157
+ expect(env['SCRIPT_NAME']).to eq('')
158
+ expect(env['PATH_INFO']).to eq('/invalid-url')
159
+ expect(env['QUERY_STRING']).to eq('')
160
+
161
+ expect(env['strict_uri.original_invalid_url']).not_to be_nil
162
+ expect(env['strict_uri.proposed_fixed_url']).to match(/\/0130a0$/)
163
+ expect(env['strict_uri.proposed_fixed_url']).to match(/^\/downloads\//)
164
+ [200, :h, :b]
165
+ }
166
+ invalid_env = {
167
+ 'SCRIPT_NAME' => '',
168
+ 'PATH_INFO' => path,
169
+ 'QUERY_STRING' => '',
170
+ }
171
+ # nil will raise if the wrapped app is called
172
+ middleware = described_class.new(nil, &fake_action)
173
+ status, headers, body = middleware.call(invalid_env)
174
+ expect(status).to eq(200)
175
+ expect(headers).to eq(:h)
176
+ end
177
+
178
+ it 'triggers with raw bytes that cannot be URL-decoded' do
179
+ # Example from production - just random gunk appended to the end of the URL
180
+ path = '/downloads/918ab1e20586c0b4e1875b3789b84ec720150615173920' +
181
+ '/a480d026f46b0f0533cec47545cd5e2820150615173920/0130a' + '���'
182
+
183
+ fake_action = ->(env) {
184
+ # Make sure those are now safe to concat with each other
185
+ expect(env['SCRIPT_NAME']).to eq('')
186
+ expect(env['PATH_INFO']).to eq('/invalid-url')
187
+ expect(env['QUERY_STRING']).to eq('')
188
+
189
+ expect(env['request_uri_cleanup.original_invalid_url']).not_to be_nil
190
+ expect(env['request_uri_cleanup.proposed_fixed_url']).to match(/^\/downloads\//)
191
+ expect(env['request_uri_cleanup.proposed_fixed_url']).to match(/0130$/)
192
+
193
+ [200, :h, :b]
194
+ }
195
+ invalid_env = {
196
+ 'SCRIPT_NAME' => '',
197
+ 'PATH_INFO' => path,
198
+ 'QUERY_STRING' => '',
199
+ }
200
+ middleware = described_class.new(nil)
201
+ status, headers, body = middleware.call(invalid_env)
202
+ expect(status).to eq(400)
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,71 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: strict_request_uri 1.0.2 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "strict_request_uri"
9
+ s.version = "1.0.2"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Julik Tarkhanov"]
14
+ s.date = "2016-11-25"
15
+ s.description = "Reject Rack requests with an invalid URL"
16
+ s.email = "me@julik.nl"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ ".travis.yml",
25
+ "Gemfile",
26
+ "LICENSE.txt",
27
+ "README.md",
28
+ "Rakefile",
29
+ "images/icon.png",
30
+ "images/strict_uri.png",
31
+ "lib/strict_request_uri.rb",
32
+ "spec/spec_helper.rb",
33
+ "spec/strict_request_uri_spec.rb",
34
+ "strict_request_uri.gemspec"
35
+ ]
36
+ s.homepage = "https://github.com/WeTransfer/strict_request_uri"
37
+ s.licenses = ["MIT"]
38
+ s.rubygems_version = "2.4.5.1"
39
+ s.summary = "and show an error page instead"
40
+
41
+ if s.respond_to? :specification_version then
42
+ s.specification_version = 4
43
+
44
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
+ s.add_runtime_dependency(%q<rack>, ["~> 1"])
46
+ s.add_development_dependency(%q<gemfury>, [">= 0"])
47
+ s.add_development_dependency(%q<rspec>, ["~> 3.0"])
48
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
49
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
50
+ s.add_development_dependency(%q<jeweler>, ["~> 2.2.1"])
51
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<rack>, ["~> 1"])
54
+ s.add_dependency(%q<gemfury>, [">= 0"])
55
+ s.add_dependency(%q<rspec>, ["~> 3.0"])
56
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
57
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
58
+ s.add_dependency(%q<jeweler>, ["~> 2.2.1"])
59
+ s.add_dependency(%q<simplecov>, [">= 0"])
60
+ end
61
+ else
62
+ s.add_dependency(%q<rack>, ["~> 1"])
63
+ s.add_dependency(%q<gemfury>, [">= 0"])
64
+ s.add_dependency(%q<rspec>, ["~> 3.0"])
65
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
66
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
67
+ s.add_dependency(%q<jeweler>, ["~> 2.2.1"])
68
+ s.add_dependency(%q<simplecov>, [">= 0"])
69
+ end
70
+ end
71
+
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: strict_request_uri
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Julik Tarkhanov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gemfury
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdoc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: jeweler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.2.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.2.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Reject Rack requests with an invalid URL
112
+ email: me@julik.nl
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files:
116
+ - LICENSE.txt
117
+ - README.md
118
+ files:
119
+ - ".document"
120
+ - ".rspec"
121
+ - ".travis.yml"
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - images/icon.png
127
+ - images/strict_uri.png
128
+ - lib/strict_request_uri.rb
129
+ - spec/spec_helper.rb
130
+ - spec/strict_request_uri_spec.rb
131
+ - strict_request_uri.gemspec
132
+ homepage: https://github.com/WeTransfer/strict_request_uri
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.4.5.1
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: and show an error page instead
156
+ test_files: []