Skip to content

Commit 2211cde

Browse files
authored
Merge pull request #42 from johnnyshields/rack3-support
Support Rack 3 and drop Rack 2
2 parents ca8eff6 + 81b1bad commit 2211cde

16 files changed

Lines changed: 185 additions & 103 deletions

.github/workflows/test.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
name: Test
3+
4+
'on':
5+
- push
6+
- pull_request
7+
8+
jobs:
9+
# rubocop:
10+
# runs-on: ubuntu-latest
11+
# env:
12+
# CI: true
13+
# steps:
14+
# - uses: actions/checkout@v3
15+
# - name: Set up Ruby 3.4
16+
# uses: ruby/setup-ruby@v1
17+
# with:
18+
# ruby-version: 3.4
19+
# bundler-cache: true
20+
# - name: Run RuboCop
21+
# run: bundle exec rubocop --parallel
22+
23+
test:
24+
name: "${{matrix.ruby}} ${{matrix.os || 'ubuntu-latest'}}"
25+
env:
26+
CI: true
27+
runs-on: ${{matrix.os || 'ubuntu-latest'}}
28+
continue-on-error: "${{matrix.experimental || false}}"
29+
strategy:
30+
fail-fast: false
31+
matrix:
32+
ruby:
33+
- ruby-2.4
34+
- ruby-2.5
35+
- ruby-2.6
36+
- ruby-2.7
37+
- ruby-3.0
38+
- ruby-3.1
39+
- ruby-3.2
40+
- ruby-3.3
41+
- ruby-3.4
42+
- jruby-9.4
43+
- truffleruby
44+
os:
45+
- ubuntu-latest
46+
- macos-latest
47+
- windows-latest
48+
exclude:
49+
- ruby: ruby-2.4
50+
os: macos-latest
51+
- ruby: ruby-2.5
52+
os: macos-latest
53+
- ruby: jruby-9.4
54+
os: windows-latest
55+
- ruby: truffleruby
56+
os: windows-latest
57+
58+
steps:
59+
- name: repo checkout
60+
uses: actions/checkout@v3
61+
- name: load ruby
62+
uses: ruby/setup-ruby@v1
63+
with:
64+
ruby-version: "${{matrix.ruby}}"
65+
- name: bundle
66+
run: bundle install --jobs 4 --retry 3
67+
- name: test
68+
timeout-minutes: 60
69+
continue-on-error: "${{matrix.experimental || false}}"
70+
run: bundle exec rake spec

.travis.yml

Lines changed: 0 additions & 9 deletions
This file was deleted.

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# CHANGELOG
22

3+
## v2.0.0
4+
5+
* Support Rack 3 and add Rack >= 3.0 as a dependency
6+
* Dropped support for Ruby < 2.4 to match Rack
7+
* Replace Travis CI with GitHub Actions
8+
* Add frozen_string_literal to all files
9+
* Remove guard gem
10+
311
## v1.0.0
412

513
* Dropped support for Ruby < 2.3
@@ -36,4 +44,4 @@
3644

3745
## v0.1.0
3846

39-
Broken.
47+
* Broken.

Gemfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1+
# frozen_string_literal: true
2+
13
source 'https://rubygems.org'
24

3-
# Specify your gem's dependencies in utf8-cleaner.gemspec
45
gemspec

Guardfile

Lines changed: 0 additions & 9 deletions
This file was deleted.

README.md

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
# UTF8Cleaner
22

3-
Removes invalid UTF-8 characters from the environment so that your app doesn't choke
4-
on them. This prevents errors like "invalid byte sequence in UTF-8".
3+
Rack middleware to remove invalid UTF-8 characters from the environment so that your
4+
app doesn't choke them. Prevents errors like "invalid byte sequence in UTF-8".
55

66
## Installation
77

8-
Add this line to your application's Gemfile:
8+
Add this line to your application's `Gemfile`:
99

10-
gem 'utf8-cleaner'
10+
```ruby
11+
gem 'utf8-cleaner'
12+
```
1113

12-
And then execute:
14+
If you're not running Rails, you'll have to add the middleware to your `config.ru`:
1315

14-
$ bundle
15-
16-
Or install it yourself as:
17-
18-
$ gem install utf8-cleaner
19-
20-
If you're not running Rails, you'll have to add the middleware to your config.ru:
21-
22-
require 'utf8-cleaner'
23-
use UTF8Cleaner::Middleware
16+
```ruby
17+
require 'utf8-cleaner'
18+
use UTF8Cleaner::Middleware
19+
```
2420

2521
## Usage
2622

@@ -36,10 +32,10 @@ There's nothing to "use". It just works!
3632

3733
## Credits
3834

39-
Original middleware author: @phoet - https://gist.github.com/phoet/1336754
40-
35+
* Original middleware author: @phoet - https://gist.github.com/phoet/1336754
4136
* Ruby 1.9.3 compatibility: @pithyless - https://gist.github.com/pithyless/3639014
4237
* Code review and cleanup: @nextmat
4338
* POST body sanitization: @salrepe
4439
* Bug fixes: @cosine
4540
* Rails 5 deprecation fix: @benlovell
41+
* Rack 3 support: @johnnyshields

Rakefile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
require "bundler/gem_tasks"
1+
# frozen_string_literal: true
22

3-
task :default do
4-
sh "rspec spec"
5-
end
3+
require 'bundler/gem_tasks'
4+
require 'rspec/core/rake_task'
5+
6+
RSpec::Core::RakeTask.new(:spec)
7+
8+
task default: :spec

lib/utf8-cleaner.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
require "utf8-cleaner/version"
2-
require "utf8-cleaner/middleware"
3-
require "utf8-cleaner/uri_string"
4-
require "utf8-cleaner/railtie" if defined? Rails
1+
# frozen_string_literal: true
2+
3+
require 'utf8-cleaner/version'
4+
require 'utf8-cleaner/middleware'
5+
require 'utf8-cleaner/uri_string'
6+
require 'utf8-cleaner/railtie' if defined?(Rails)

lib/utf8-cleaner/middleware.rb

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,81 @@
1+
# frozen_string_literal: true
2+
13
require 'active_support/multibyte/unicode'
24

35
module UTF8Cleaner
46
class Middleware
5-
6-
SANITIZE_ENV_KEYS = [
7-
"HTTP_REFERER",
8-
"HTTP_USER_AGENT",
9-
"PATH_INFO",
10-
"QUERY_STRING",
11-
"REQUEST_PATH",
12-
"REQUEST_URI",
13-
"HTTP_COOKIE"
14-
]
7+
SANITIZE_ENV_KEYS = %w[
8+
HTTP_REFERER
9+
HTTP_USER_AGENT
10+
PATH_INFO
11+
QUERY_STRING
12+
REQUEST_PATH
13+
REQUEST_URI
14+
HTTP_COOKIE
15+
].freeze
1516

1617
def initialize(app)
17-
@app = app
18+
@app = app
1819
end
1920

2021
def call(env)
21-
@app.call(sanitize_env(env))
22+
@app.call(sanitize_env(env))
2223
end
2324

2425
private
2526

2627
include ActiveSupport::Multibyte::Unicode
2728

2829
def sanitize_env(env)
30+
env = env.dup # Do not mutate the original
2931
sanitize_env_keys(env)
3032
sanitize_env_rack_input(env)
3133
env
3234
end
3335

3436
def sanitize_env_keys(env)
3537
SANITIZE_ENV_KEYS.each do |key|
36-
next unless value = env[key]
38+
next unless (value = env[key])
3739
env[key] = cleaned_string(value)
3840
end
3941
end
4042

4143
def sanitize_env_rack_input(env)
44+
return unless env['rack.input']
45+
4246
case env['CONTENT_TYPE']
43-
when 'application/x-www-form-urlencoded'
47+
when %r{\Aapplication/x-www-form-urlencoded}i
4448
# This data gets the full cleaning treatment
45-
cleaned_value = cleaned_string(env['rack.input'].read)
46-
env['rack.input'] = StringIO.new(cleaned_value) if cleaned_value
47-
env['rack.input'].rewind
48-
when 'application/json'
49+
input_data = read_input(env['rack.input'])
50+
return unless input_data
51+
52+
cleaned_value = cleaned_string(input_data)
53+
env['rack.input'] = StringIO.new(cleaned_value)
54+
when %r{\Aapplication/json}i
4955
# This data only gets cleaning of invalid UTF-8 (e.g. from another charset)
5056
# but we do not URI-decode it.
51-
rack_input = env['rack.input'].read
52-
if rack_input && !rack_input.ascii_only?
53-
env['rack.input'] = StringIO.new(tidy_bytes(rack_input))
54-
end
55-
env['rack.input'].rewind
56-
when 'multipart/form-data'
57-
# Don't process the data since it may contain binary content
57+
input_data = read_input(env['rack.input'])
58+
return unless input_data && !input_data.ascii_only?
59+
60+
env['rack.input'] = StringIO.new(tidy_bytes(input_data))
5861
else
59-
# Unknown content type. Leave it alone
62+
# Do not process multipart/form-data since it may contain binary content.
63+
# Leave all other unknown content types alone.
6064
end
6165
end
6266

67+
def read_input(input)
68+
return nil unless input
69+
70+
data = input.read
71+
input.rewind if input.respond_to?(:rewind)
72+
data
73+
end
74+
6375
def cleaned_string(value)
76+
return value if value.nil? || value.empty?
77+
78+
value = value.to_s
6479
value = tidy_bytes(value) unless value.ascii_only?
6580
value = URIString.new(value).cleaned if value.include?('%')
6681
value

lib/utf8-cleaner/railtie.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
# frozen_string_literal: true
2+
13
module UTF8Cleaner
24
class Railtie < Rails::Railtie
3-
initializer "utf8-cleaner.insert_middleware" do |app|
4-
app.config.middleware.insert_before 0, UTF8Cleaner::Middleware
5+
initializer('utf8-cleaner.insert_middleware') do |app|
6+
app.config.middleware.insert_before(0, UTF8Cleaner::Middleware)
57
end
68
end
79
end

0 commit comments

Comments
 (0)