strict_request_uri 1.0.2 → 1.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 +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
|