Skip to content

Commit f032606

Browse files
committed
Adding support for public_suffix.
* New runtime dependency on `public_suffix` gem. * Match the escaping rules in the `reg-name` rule. * Note: This implies underscores are no longer escaped in hostnames.
1 parent 8d040f6 commit f032606

File tree

5 files changed

+115
-19
lines changed

5 files changed

+115
-19
lines changed

CHANGELOG.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Addressable 2.5.0
2-
- Paths beginning with // and missing an authority are now considered invalid
3-
- URI validation now also takes place after setting a path
4-
- Handle backslashes in authority more like a browser for `heuristic_parse`
5-
- Unescaped backslashes in host now raise an `InvalidURIError`
2+
- add support for public suffixes and tld; first runtime dependency
3+
- hostname escaping should match RFC; underscores in hostnames no longer escaped
4+
- paths beginning with // and missing an authority are now considered invalid
5+
- validation now also takes place after setting a path
6+
- handle backslashes in authority more like a browser for `heuristic_parse`
7+
- unescaped backslashes in host now raise an `InvalidURIError`
68
- `merge!`, `join!`, `omit!` and `normalize!` don't disable deferred validation
79
- `heuristic_parse` now trims whitespace before parsing
810

addressable.gemspec

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
11
# -*- encoding: utf-8 -*-
2-
# stub: addressable 2.4.0 ruby lib
2+
# stub: addressable 2.5.0 ruby lib
33

44
Gem::Specification.new do |s|
55
s.name = "addressable"
6-
s.version = "2.4.0"
6+
s.version = "2.5.0"
77

88
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
99
s.require_paths = ["lib"]
1010
s.authors = ["Bob Aman"]
11-
s.date = "2015-12-07"
11+
s.date = "2016-11-04"
1212
s.description = "Addressable is a replacement for the URI implementation that is part of\nRuby's standard library. It more closely conforms to the relevant RFCs and\nadds support for IRIs and URI templates.\n"
1313
s.email = "bob@sporkmonger.com"
1414
s.extra_rdoc_files = ["README.md"]
15-
s.files = ["CHANGELOG.md", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "addressable.gemspec", "data/unicode.data", "lib/addressable.rb", "lib/addressable/idna.rb", "lib/addressable/idna/native.rb", "lib/addressable/idna/pure.rb", "lib/addressable/template.rb", "lib/addressable/uri.rb", "lib/addressable/version.rb", "spec/addressable/idna_spec.rb", "spec/addressable/net_http_compat_spec.rb", "spec/addressable/rack_mount_compat_spec.rb", "spec/addressable/security_spec.rb", "spec/addressable/template_spec.rb", "spec/addressable/uri_spec.rb", "spec/spec_helper.rb", "tasks/clobber.rake", "tasks/gem.rake", "tasks/git.rake", "tasks/metrics.rake", "tasks/rspec.rake", "tasks/yard.rake"]
15+
s.files = ["CHANGELOG.md", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "data/unicode.data", "lib/addressable", "lib/addressable.rb", "lib/addressable/idna", "lib/addressable/idna.rb", "lib/addressable/idna/native.rb", "lib/addressable/idna/pure.rb", "lib/addressable/template.rb", "lib/addressable/uri.rb", "lib/addressable/version.rb", "spec/addressable", "spec/addressable/idna_spec.rb", "spec/addressable/net_http_compat_spec.rb", "spec/addressable/rack_mount_compat_spec.rb", "spec/addressable/security_spec.rb", "spec/addressable/template_spec.rb", "spec/addressable/uri_spec.rb", "spec/spec_helper.rb", "tasks/clobber.rake", "tasks/gem.rake", "tasks/git.rake", "tasks/metrics.rake", "tasks/rspec.rake", "tasks/yard.rake"]
1616
s.homepage = "https://github.com/sporkmonger/addressable"
1717
s.licenses = ["Apache-2.0"]
1818
s.rdoc_options = ["--main", "README.md"]
1919
s.required_ruby_version = Gem::Requirement.new(">= 1.9.0")
20-
s.rubygems_version = "2.5.0"
20+
s.rubygems_version = "2.5.1"
2121
s.summary = "URI Implementation"
2222

2323
if s.respond_to? :specification_version then
2424
s.specification_version = 4
2525

2626
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27+
s.add_runtime_dependency(%q<public_suffix>, [">= 2.0.3", "~> 2.0"])
2728
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
2829
else
30+
s.add_dependency(%q<public_suffix>, [">= 2.0.3", "~> 2.0"])
2931
s.add_dependency(%q<bundler>, ["~> 1.0"])
3032
end
3133
else
34+
s.add_dependency(%q<public_suffix>, [">= 2.0.3", "~> 2.0"])
3235
s.add_dependency(%q<bundler>, ["~> 1.0"])
3336
end
3437
end

lib/addressable/uri.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
require "addressable/version"
2020
require "addressable/idna"
21+
require "public_suffix"
2122

2223
##
2324
# Addressable is a library for processing links and URIs.
@@ -44,7 +45,7 @@ module CharacterClasses
4445
UNRESERVED = ALPHA + DIGIT + "\\-\\.\\_\\~"
4546
PCHAR = UNRESERVED + SUB_DELIMS + "\\:\\@"
4647
SCHEME = ALPHA + DIGIT + "\\-\\+\\."
47-
HOST = ALPHA + DIGIT + "\\-\\.\\[\\:\\]"
48+
HOST = UNRESERVED + SUB_DELIMS + "\\[\\:\\]"
4849
AUTHORITY = PCHAR
4950
PATH = PCHAR + "\\/"
5051
QUERY = PCHAR + "\\/\\?"
@@ -1145,6 +1146,24 @@ def hostname=(new_hostname)
11451146
self.host = v
11461147
end
11471148

1149+
##
1150+
# Returns the top-level domain for this host.
1151+
#
1152+
# @example
1153+
# Addressable::URI.parse("www.example.co.uk").tld # => "co.uk"
1154+
def tld
1155+
PublicSuffix.parse(self.host, ignore_private: true).tld
1156+
end
1157+
1158+
##
1159+
# Returns the public suffix domain for this host.
1160+
#
1161+
# @example
1162+
# Addressable::URI.parse("www.example.co.uk").domain # => "example.co.uk"
1163+
def domain
1164+
PublicSuffix.domain(self.host, ignore_private: true)
1165+
end
1166+
11481167
##
11491168
# The authority component for this URI.
11501169
# Combines the user, password, host, and port components.

spec/addressable/uri_spec.rb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,10 @@ def to_s
409409
expect(@uri.normalized_host).to eq("example.com")
410410
end
411411

412+
it "returns 'com' for #tld" do
413+
expect(@uri.tld).to eq("com")
414+
end
415+
412416
it "returns 'user:password@example.com:8080' for #authority" do
413417
expect(@uri.authority).to eq("user:password@example.com:8080")
414418
end
@@ -2344,6 +2348,80 @@ def to_s
23442348
end
23452349
end
23462350

2351+
describe Addressable::URI, "when parsed from " +
2352+
"'HTTP://EXAMPLE.COM/'" do
2353+
before do
2354+
@uri = Addressable::URI.parse("HTTP://EXAMPLE.COM/")
2355+
end
2356+
2357+
it "should be equivalent to http://example.com" do
2358+
expect(@uri).to eq(Addressable::URI.parse("http://example.com"))
2359+
end
2360+
2361+
it "should correctly convert to a hash" do
2362+
expect(@uri.to_hash).to eq({
2363+
:scheme => "HTTP",
2364+
:user => nil,
2365+
:password => nil,
2366+
:host => "EXAMPLE.COM",
2367+
:port => nil,
2368+
:path => "/",
2369+
:query => nil,
2370+
:fragment => nil
2371+
})
2372+
end
2373+
2374+
it "should be identical to its duplicate" do
2375+
expect(@uri).to eq(@uri.dup)
2376+
end
2377+
2378+
it "should have an origin of 'http://example.com'" do
2379+
expect(@uri.origin).to eq('http://example.com')
2380+
end
2381+
2382+
it "should have a tld of 'com'" do
2383+
expect(@uri.tld).to eq('com')
2384+
end
2385+
end
2386+
2387+
describe Addressable::URI, "when parsed from " +
2388+
"'http://www.example.co.uk/'" do
2389+
before do
2390+
@uri = Addressable::URI.parse("http://www.example.co.uk/")
2391+
end
2392+
2393+
it "should have an origin of 'http://www.example.co.uk'" do
2394+
expect(@uri.origin).to eq('http://www.example.co.uk')
2395+
end
2396+
2397+
it "should have a tld of 'co.uk'" do
2398+
expect(@uri.tld).to eq('co.uk')
2399+
end
2400+
2401+
it "should have a domain of 'example.co.uk'" do
2402+
expect(@uri.domain).to eq('example.co.uk')
2403+
end
2404+
end
2405+
2406+
describe Addressable::URI, "when parsed from " +
2407+
"'http://sub_domain.blogspot.com/'" do
2408+
before do
2409+
@uri = Addressable::URI.parse("http://sub_domain.blogspot.com/")
2410+
end
2411+
2412+
it "should have an origin of 'http://sub_domain.blogspot.com'" do
2413+
expect(@uri.origin).to eq('http://sub_domain.blogspot.com')
2414+
end
2415+
2416+
it "should have a tld of 'com'" do
2417+
expect(@uri.tld).to eq('com')
2418+
end
2419+
2420+
it "should have a domain of 'blogspot.com'" do
2421+
expect(@uri.domain).to eq('blogspot.com')
2422+
end
2423+
end
2424+
23472425
describe Addressable::URI, "when parsed from " +
23482426
"'http://example.com/~smith/'" do
23492427
before do

tasks/gem.rake

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace :gem do
2020

2121
s.required_ruby_version = '>= 1.9.0'
2222

23+
s.add_runtime_dependency 'public_suffix', '~> 2.0', '>= 2.0.3'
2324
s.add_development_dependency 'bundler', '~> 1.0'
2425

2526
s.require_path = "lib"
@@ -39,15 +40,8 @@ namespace :gem do
3940
desc "Generates .gemspec file"
4041
task :gemspec do
4142
spec_string = GEM_SPEC.to_ruby
42-
43-
begin
44-
Thread.new { eval("$SAFE = 3\n#{spec_string}", binding) }.join
45-
rescue
46-
abort "unsafe gemspec: #{$!}"
47-
else
48-
File.open("#{GEM_SPEC.name}.gemspec", 'w') do |file|
49-
file.write spec_string
50-
end
43+
File.open("#{GEM_SPEC.name}.gemspec", 'w') do |file|
44+
file.write spec_string
5145
end
5246
end
5347

0 commit comments

Comments
 (0)