sanitize_user_agent_header 0.1.0
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 +7 -0
- data/.gitignore +54 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/lib/sanitize_user_agent_header.rb +42 -0
- data/lib/sanitize_user_agent_header/railtie.rb +5 -0
- data/lib/sanitize_user_agent_header/version.rb +3 -0
- data/sanitize_user_agent_header.gemspec +35 -0
- data/spec/sanitize_user_agent_header_spec.rb +37 -0
- data/spec/spec_helper.rb +6 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 108290424f2d89412961132a44c5285e03547c42
|
4
|
+
data.tar.gz: e2f08105b183eb152ea976a0f81ff8de6ce9d697
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fabbc5e3c05aaccd421f1703973a328b74efd13ab06181047415d572b0a41da3c598d9d7357b6a38d3be9a48f42012f53a2837c530c02e2c852d3e7370cda7a7
|
7
|
+
data.tar.gz: fe8acd9a4bf5e55ad64403e9f1eaad04c7b279804cec8de2c40ec42518445231d5f38b24db0d126b955a9dfc3004512f615abdc6cc72381dad93613f86e95557
|
data/.gitignore
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# rbenv/rvm
|
2
|
+
.ruby-version
|
3
|
+
|
4
|
+
# rcov generated
|
5
|
+
coverage
|
6
|
+
coverage.data
|
7
|
+
|
8
|
+
# rdoc generated
|
9
|
+
rdoc
|
10
|
+
|
11
|
+
# yard generated
|
12
|
+
doc
|
13
|
+
.yardoc
|
14
|
+
|
15
|
+
# bundler
|
16
|
+
.bundle
|
17
|
+
Gemfile.lock
|
18
|
+
gemfiles/*.lock
|
19
|
+
|
20
|
+
# jeweler generated
|
21
|
+
pkg
|
22
|
+
|
23
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
24
|
+
#
|
25
|
+
# * Create a file at ~/.gitignore
|
26
|
+
# * Include files you want ignored
|
27
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
28
|
+
#
|
29
|
+
# After doing this, these files will be ignored in all your git projects,
|
30
|
+
# saving you from having to 'pollute' every project you touch with them
|
31
|
+
#
|
32
|
+
# 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)
|
33
|
+
#
|
34
|
+
# For MacOS:
|
35
|
+
#
|
36
|
+
#.DS_Store
|
37
|
+
|
38
|
+
# For TextMate
|
39
|
+
#*.tmproj
|
40
|
+
#tmtags
|
41
|
+
|
42
|
+
# For emacs:
|
43
|
+
#*~
|
44
|
+
#\#*
|
45
|
+
#.\#*
|
46
|
+
|
47
|
+
# For vim:
|
48
|
+
#*.swp
|
49
|
+
|
50
|
+
# For redcar:
|
51
|
+
#.redcar
|
52
|
+
|
53
|
+
# For rubinius:
|
54
|
+
#*.rbc
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Decodes the `User-Agent` header in your Rack request hash to be UTF-8. Mostly useful for headers like
|
2
|
+
|
3
|
+
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; Telecomunicaciones espa��olas`
|
4
|
+
|
5
|
+
which get inserted by (rather clueless) telcos, especially in packaged Android distributions (one of the many reasons why letting telcos
|
6
|
+
customize the handset is a bad idea). This library will do it's best to reencode the header in good UTF-8, and barring that will do a lossy
|
7
|
+
replacement with question-mark substitions.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'sanitize_user_agent_header'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install sanitize_user_agent_header
|
24
|
+
|
25
|
+
In Rails the gem will be inserted into your application stack automatically. In raw Rack, install the middleware in `config.ru` like so:
|
26
|
+
|
27
|
+
use SanitizeUserAgentHeader
|
28
|
+
|
29
|
+
## Development
|
30
|
+
|
31
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
32
|
+
|
33
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sanitize_user_agent_header.
|
38
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "sanitize_user_agent_header/version"
|
2
|
+
|
3
|
+
# This middleware will ensure that the User-Agent request header is actually
|
4
|
+
# UTF-8, which will prevent bad things down the road. Strictly speaking,
|
5
|
+
# the _string_ must be kept in an ISO encoding (single byte header limitations).
|
6
|
+
# But pragmatically we use this header in many places, and applying an explicit
|
7
|
+
# decode to it is a chore. Also, we are not violating the spec, merely "matching"
|
8
|
+
# the encoding of an input variable to the internal encoding of the system.
|
9
|
+
class SanitizeUserAgentHeader
|
10
|
+
HTTP_USER_AGENT = 'HTTP_USER_AGENT'.freeze
|
11
|
+
private_constant :HTTP_USER_AGENT
|
12
|
+
|
13
|
+
def initialize(app)
|
14
|
+
@app = app
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
if env[HTTP_USER_AGENT]
|
19
|
+
env[HTTP_USER_AGENT] = opportunistically_convert_to_utf8(env[HTTP_USER_AGENT])
|
20
|
+
end
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
|
24
|
+
# http://stackoverflow.com/questions/10384741/is-a-unicode-user-agent-legal-inside-an-http-header
|
25
|
+
def opportunistically_convert_to_utf8(str)
|
26
|
+
try_encodings = %w( ISO-8859-1 CP1252 )
|
27
|
+
try_encodings.each do |enc|
|
28
|
+
begin
|
29
|
+
encoded_as_utf8 = str.force_encoding(enc).encode(Encoding::UTF_8)
|
30
|
+
return encoded_as_utf8
|
31
|
+
rescue Encoding::UndefinedConversionError
|
32
|
+
end
|
33
|
+
end
|
34
|
+
# Last resort, just strip it of everything
|
35
|
+
str.force_encoding(Encoding::ISO8859_1)
|
36
|
+
str.encode(Encoding::ASCII, invalid: :replace, undef: :replace, replace: '?').encode(Encoding::UTF_8)
|
37
|
+
end
|
38
|
+
|
39
|
+
if defined?(Rails)
|
40
|
+
require_relative 'sanitize_user_agent_header/railtie'
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sanitize_user_agent_header/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sanitize_user_agent_header"
|
8
|
+
spec.version = SanitizeUserAgentHeader::VERSION
|
9
|
+
spec.authors = ["Julik Tarkhanov"]
|
10
|
+
spec.email = ["me@julik.nl"]
|
11
|
+
|
12
|
+
spec.summary = %q{ Decodes the User-Agent header into UTF-8 in any Rack app }
|
13
|
+
spec.description = %q{ Decodes the User-Agent header into UTF-8 in any Rack app }
|
14
|
+
spec.homepage = "https://github.com/WeTransfer/sanitize_user_agent_header"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
20
|
+
else
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
22
|
+
"public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0")
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "rack"
|
31
|
+
spec.add_development_dependency "rack-test"
|
32
|
+
spec.add_development_dependency "bundler"
|
33
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
+
spec.add_development_dependency "rspec", "~> 3.2"
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe SanitizeUserAgentHeader do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
let(:app) {
|
9
|
+
app_proc = ->(env) {
|
10
|
+
[200, {}, [env.fetch('HTTP_USER_AGENT', '<NONE>').encode(Encoding::UTF_8)]]
|
11
|
+
}
|
12
|
+
SanitizeUserAgentHeader.new(app_proc)
|
13
|
+
}
|
14
|
+
|
15
|
+
it 'calls the app when no user agent header is set' do
|
16
|
+
get '/'
|
17
|
+
expect(last_response.body).to eq("<NONE>")
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'calls the app when the user agent is just ASCII' do
|
21
|
+
get '/', {}, {'HTTP_USER_AGENT' => 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1)'}
|
22
|
+
expect(last_response.body).to eq("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1)")
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'with non-ASCII characters in the User-Agent header combined with UTF-8 params' do
|
26
|
+
['ISO-8859-1', 'CP1252'].each do | windows_encoding |
|
27
|
+
it "decodes the UA header and prevents encoding errors for UA header in #{windows_encoding}" do
|
28
|
+
# From our actual bug records
|
29
|
+
utf8_ua = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; Pernod Ricard España)'
|
30
|
+
windows_ua = utf8_ua.encode(windows_encoding)
|
31
|
+
post '/', {'message' => 'Voiçi un header'}, {'HTTP_USER_AGENT' => windows_ua}
|
32
|
+
expect(last_response).to be_ok
|
33
|
+
expect(last_response.body).to eq('Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; Pernod Ricard España)')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sanitize_user_agent_header
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Julik Tarkhanov
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-11 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: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack-test
|
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: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.2'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.2'
|
83
|
+
description: " Decodes the User-Agent header into UTF-8 in any Rack app "
|
84
|
+
email:
|
85
|
+
- me@julik.nl
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
92
|
+
- Gemfile
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/sanitize_user_agent_header.rb
|
96
|
+
- lib/sanitize_user_agent_header/railtie.rb
|
97
|
+
- lib/sanitize_user_agent_header/version.rb
|
98
|
+
- sanitize_user_agent_header.gemspec
|
99
|
+
- spec/sanitize_user_agent_header_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
homepage: https://github.com/WeTransfer/sanitize_user_agent_header
|
102
|
+
licenses: []
|
103
|
+
metadata:
|
104
|
+
allowed_push_host: https://rubygems.org
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.4.5.1
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: Decodes the User-Agent header into UTF-8 in any Rack app
|
125
|
+
test_files: []
|