strict_request_uri 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +50 -0
- data/.travis.yml +1 -3
- data/Gemfile +3 -11
- data/Rakefile +3 -42
- data/lib/strict_request_uri.rb +1 -2
- data/lib/strict_request_uri/version.rb +3 -0
- data/strict_request_uri.gemspec +27 -52
- metadata +20 -33
- data/spec/spec_helper.rb +0 -9
- data/spec/strict_request_uri_spec.rb +0 -205
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9190765e80ce93ec09388f7f375b4e7b8fada8f
|
4
|
+
data.tar.gz: 1e1e610be8f501730f9c37d54f3e4a947959c8d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca5931fbf8b37a3a5d54cf60f3de9f7441b077a8206f371eca6422b5429c5d47e72262871cf4501abdb74d30b9dee88b8ff066fc10acd253cc9eb4a8d3fbdf5f
|
7
|
+
data.tar.gz: ea47b279ea46da534e7a9f12127ebb5850fab91b653dc7a0d27fce2c74ecfb9c0486a47fa0591a04d4bf1249bf0e9b9aef70ad71090debdd62d043c8c6225bad
|
data/.gitignore
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# rcov generated
|
2
|
+
coverage
|
3
|
+
coverage.data
|
4
|
+
|
5
|
+
# rdoc generated
|
6
|
+
rdoc
|
7
|
+
|
8
|
+
# yard generated
|
9
|
+
doc
|
10
|
+
.yardoc
|
11
|
+
|
12
|
+
# bundler
|
13
|
+
.bundle
|
14
|
+
Gemfile.lock
|
15
|
+
|
16
|
+
# jeweler generated
|
17
|
+
pkg
|
18
|
+
|
19
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
20
|
+
#
|
21
|
+
# * Create a file at ~/.gitignore
|
22
|
+
# * Include files you want ignored
|
23
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
24
|
+
#
|
25
|
+
# After doing this, these files will be ignored in all your git projects,
|
26
|
+
# saving you from having to 'pollute' every project you touch with them
|
27
|
+
#
|
28
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
29
|
+
#
|
30
|
+
# For MacOS:
|
31
|
+
#
|
32
|
+
#.DS_Store
|
33
|
+
|
34
|
+
# For TextMate
|
35
|
+
#*.tmproj
|
36
|
+
#tmtags
|
37
|
+
|
38
|
+
# For emacs:
|
39
|
+
#*~
|
40
|
+
#\#*
|
41
|
+
#.\#*
|
42
|
+
|
43
|
+
# For vim:
|
44
|
+
#*.swp
|
45
|
+
|
46
|
+
# For redcar:
|
47
|
+
#.redcar
|
48
|
+
|
49
|
+
# For rubinius:
|
50
|
+
#*.rbc
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,12 +1,4 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
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
|
3
|
+
# Specify your gem's dependencies in zip_tricks.gemspec
|
4
|
+
gemspec
|
data/Rakefile
CHANGED
@@ -1,34 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require '
|
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
|
3
|
+
require 'bundler/gem_tasks'
|
12
4
|
require 'rake'
|
5
|
+
require 'rspec/core'
|
6
|
+
require 'rspec/core/rake_task'
|
13
7
|
|
14
8
|
require_relative 'lib/strict_request_uri'
|
15
9
|
|
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
10
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
33
11
|
spec.pattern = FileList['spec/**/*_spec.rb']
|
34
12
|
end
|
@@ -50,20 +28,3 @@ Rake::RDocTask.new do |rdoc|
|
|
50
28
|
rdoc.rdoc_files.include('README*')
|
51
29
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
30
|
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/lib/strict_request_uri.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rack'
|
2
|
+
require_relative 'strict_request_uri/version'
|
2
3
|
|
3
4
|
# Sometimes junk gets appended to the URLs clicked in e-mails.
|
4
5
|
# This junk then gets sent by browsers undecoded, and causes Unicode-related
|
@@ -10,8 +11,6 @@ require 'rack'
|
|
10
11
|
# welcome. This also allows us to tell the users that they are using a URL which is in fact
|
11
12
|
# not really valid.
|
12
13
|
class StrictRequestUri
|
13
|
-
VERSION = '1.0.2'
|
14
|
-
|
15
14
|
# Inits the middleware. The optional proc should be a Rack application that
|
16
15
|
# will render the error page. To make a controller render that page,
|
17
16
|
# use <ControllerClass>.action()
|
data/strict_request_uri.gemspec
CHANGED
@@ -1,71 +1,46 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'strict_request_uri/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "strict_request_uri"
|
9
|
-
s.version =
|
9
|
+
s.version = StrictRequestUri::VERSION
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Julik Tarkhanov"]
|
14
|
-
s.date = "2016-11-25"
|
15
14
|
s.description = "Reject Rack requests with an invalid URL"
|
16
15
|
s.email = "me@julik.nl"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org.
|
18
|
+
# To allow pushes either set the 'allowed_push_host'
|
19
|
+
# To allow pushing to a single host or delete this section to allow pushing to any host.
|
20
|
+
if s.respond_to?(:metadata)
|
21
|
+
s.metadata['allowed_push_host'] = 'https://rubygems.org'
|
22
|
+
else
|
23
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
24
|
+
'public gem pushes.'
|
25
|
+
end
|
26
|
+
|
17
27
|
s.extra_rdoc_files = [
|
18
28
|
"LICENSE.txt",
|
19
29
|
"README.md"
|
20
30
|
]
|
21
|
-
s.files =
|
22
|
-
|
23
|
-
|
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
|
-
]
|
31
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
32
|
+
f.match(%r{^(test|spec|features)/})
|
33
|
+
end
|
36
34
|
s.homepage = "https://github.com/WeTransfer/strict_request_uri"
|
37
35
|
s.licenses = ["MIT"]
|
38
36
|
s.rubygems_version = "2.4.5.1"
|
39
37
|
s.summary = "and show an error page instead"
|
40
38
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
39
|
+
s.specification_version = 4
|
40
|
+
s.add_runtime_dependency 'rack'
|
41
|
+
s.add_development_dependency 'rake', '~> 12'
|
42
|
+
s.add_development_dependency 'rspec', '~> 3'
|
43
|
+
s.add_development_dependency 'rdoc', '~> 3'
|
44
|
+
s.add_development_dependency 'bundler', '~> 1'
|
45
|
+
s.add_development_dependency 'simplecov', '>= 0'
|
70
46
|
end
|
71
|
-
|
metadata
CHANGED
@@ -1,37 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strict_request_uri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
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
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - ">="
|
32
18
|
- !ruby/object:Gem::Version
|
33
19
|
version: '0'
|
34
|
-
type: :
|
20
|
+
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
@@ -39,61 +25,61 @@ dependencies:
|
|
39
25
|
- !ruby/object:Gem::Version
|
40
26
|
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
28
|
+
name: rake
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
31
|
- - "~>"
|
46
32
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
33
|
+
version: '12'
|
48
34
|
type: :development
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
38
|
- - "~>"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
40
|
+
version: '12'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
42
|
+
name: rspec
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3
|
47
|
+
version: '3'
|
62
48
|
type: :development
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: '3
|
54
|
+
version: '3'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: rdoc
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
61
|
+
version: '3'
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
68
|
+
version: '3'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
70
|
+
name: bundler
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - "~>"
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
75
|
+
version: '1'
|
90
76
|
type: :development
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
80
|
- - "~>"
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
82
|
+
version: '1'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: simplecov
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,6 +103,7 @@ extra_rdoc_files:
|
|
117
103
|
- README.md
|
118
104
|
files:
|
119
105
|
- ".document"
|
106
|
+
- ".gitignore"
|
120
107
|
- ".rspec"
|
121
108
|
- ".travis.yml"
|
122
109
|
- Gemfile
|
@@ -126,13 +113,13 @@ files:
|
|
126
113
|
- images/icon.png
|
127
114
|
- images/strict_uri.png
|
128
115
|
- lib/strict_request_uri.rb
|
129
|
-
-
|
130
|
-
- spec/strict_request_uri_spec.rb
|
116
|
+
- lib/strict_request_uri/version.rb
|
131
117
|
- strict_request_uri.gemspec
|
132
118
|
homepage: https://github.com/WeTransfer/strict_request_uri
|
133
119
|
licenses:
|
134
120
|
- MIT
|
135
|
-
metadata:
|
121
|
+
metadata:
|
122
|
+
allowed_push_host: https://rubygems.org
|
136
123
|
post_install_message:
|
137
124
|
rdoc_options: []
|
138
125
|
require_paths:
|
@@ -149,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
136
|
version: '0'
|
150
137
|
requirements: []
|
151
138
|
rubyforge_project:
|
152
|
-
rubygems_version: 2.
|
139
|
+
rubygems_version: 2.6.11
|
153
140
|
signing_key:
|
154
141
|
specification_version: 4
|
155
142
|
summary: and show an error page instead
|
data/spec/spec_helper.rb
DELETED
@@ -1,205 +0,0 @@
|
|
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
|