uniform_resource_identifier 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/VERSION +1 -0
- data/lib/uniform_resource_identifier.rb +214 -0
- data/lib/uniform_resource_identifier/authority.rb +121 -0
- data/lib/uniform_resource_identifier/domain.rb +50 -0
- data/lib/uniform_resource_identifier/host.rb +81 -0
- data/lib/uniform_resource_identifier/parsable.rb +7 -0
- data/lib/uniform_resource_identifier/parser.rb +22 -0
- data/lib/uniform_resource_identifier/path.rb +46 -0
- data/lib/uniform_resource_identifier/query.rb +28 -0
- data/lib/uniform_resource_identifier/relative.rb +86 -0
- data/lib/uniform_resource_identifier/rspec_matcher.rb +114 -0
- data/lib/uniform_resource_identifier/user_info.rb +44 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/uniform_resource_identifier/parser_spec.rb +30 -0
- data/spec/uniform_resource_identifier_spec.rb +178 -0
- metadata +144 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Ryan Scott Lewis
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'uniform_resource_identifier/authority'
|
2
|
+
require 'uniform_resource_identifier/relative'
|
3
|
+
|
4
|
+
class UniformResourceIdentifier
|
5
|
+
extend Parsable
|
6
|
+
|
7
|
+
def initialize(uri=nil)
|
8
|
+
if uri.respond_to?(:to_str)
|
9
|
+
parsed_uri = Parser.parse(uri)
|
10
|
+
|
11
|
+
@protocol = parsed_uri[:protocol]
|
12
|
+
|
13
|
+
@authority = Authority.new(
|
14
|
+
:user_info => {
|
15
|
+
:username => parsed_uri[:username],
|
16
|
+
:password => parsed_uri[:password]
|
17
|
+
},
|
18
|
+
:host => parsed_uri[:host],
|
19
|
+
:port => parsed_uri[:port]
|
20
|
+
)
|
21
|
+
|
22
|
+
@relative = Relative.new(
|
23
|
+
:path => {
|
24
|
+
:directory => parsed_uri[:directory],
|
25
|
+
:file => parsed_uri[:file]
|
26
|
+
},
|
27
|
+
:query => parsed_uri[:query],
|
28
|
+
:anchor => parsed_uri[:anchor]
|
29
|
+
)
|
30
|
+
elsif uri.respond_to?(:to_hash)
|
31
|
+
uri = uri.to_hash.symbolize_keys
|
32
|
+
|
33
|
+
@protocol = uri[:protocol].to_s if uri.has_key?(:protocol)
|
34
|
+
@authority = Authority.parse(uri[:authority]) if uri.has_key?(:authority)
|
35
|
+
@relative = Relative.parse(uri[:relative]) if uri.has_key?(:relative)
|
36
|
+
else
|
37
|
+
raise(TypeError, "uri must either be a String or a Hash") unless uri.nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
protocol = "#{@protocol}://" unless @protocol.nil?
|
43
|
+
"#{protocol}#{@authority}#{@relative}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_h
|
47
|
+
{
|
48
|
+
:protocol => @protocol,
|
49
|
+
:authority => @authority.nil? ? nil : @authority.to_h,
|
50
|
+
:relative => @relative.nil? ? nil : @relative.to_h
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
# ======================================================================= #
|
55
|
+
# = Attributes = #
|
56
|
+
# ======================================================================= #
|
57
|
+
|
58
|
+
attr_reader :protocol
|
59
|
+
|
60
|
+
def protocol=(protocol)
|
61
|
+
@protocol = protocol.nil? ? nil : protocol.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
alias_method :scheme, :protocol
|
65
|
+
alias_method :scheme=, :protocol=
|
66
|
+
|
67
|
+
def authority
|
68
|
+
@authority ||= Authority.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def authority=(authority)
|
72
|
+
@authority = Authority.parse(authority)
|
73
|
+
end
|
74
|
+
|
75
|
+
def relative
|
76
|
+
@relative ||= Relative.new
|
77
|
+
end
|
78
|
+
|
79
|
+
def relative=(relative)
|
80
|
+
@relative = Relative.parse(relative)
|
81
|
+
end
|
82
|
+
|
83
|
+
# ======================================================================= #
|
84
|
+
# = Delegates = #
|
85
|
+
# ======================================================================= #
|
86
|
+
|
87
|
+
def user_info
|
88
|
+
self.authority.user_info
|
89
|
+
end
|
90
|
+
|
91
|
+
def user_info=(user_info)
|
92
|
+
self.authority.user_info = user_info
|
93
|
+
end
|
94
|
+
|
95
|
+
def username
|
96
|
+
self.authority.user_info.username
|
97
|
+
end
|
98
|
+
|
99
|
+
def username=(username)
|
100
|
+
self.authority.user_info.username = username
|
101
|
+
end
|
102
|
+
|
103
|
+
def password
|
104
|
+
self.authority.user_info.password
|
105
|
+
end
|
106
|
+
|
107
|
+
def password=(password)
|
108
|
+
self.authority.user_info.password = password
|
109
|
+
end
|
110
|
+
|
111
|
+
def host
|
112
|
+
self.authority.host
|
113
|
+
end
|
114
|
+
|
115
|
+
def host=(host)
|
116
|
+
self.authority.host = host
|
117
|
+
end
|
118
|
+
|
119
|
+
def subdomain
|
120
|
+
self.authority.host.subdomain
|
121
|
+
end
|
122
|
+
|
123
|
+
def subdomain=(subdomain)
|
124
|
+
self.authority.host.subdomain = subdomain
|
125
|
+
end
|
126
|
+
|
127
|
+
def domain
|
128
|
+
self.authority.host.domain ||= Domain.new
|
129
|
+
end
|
130
|
+
|
131
|
+
def domain=(domain)
|
132
|
+
self.authority.host.domain = Domain.parse(domain)
|
133
|
+
end
|
134
|
+
|
135
|
+
def sld
|
136
|
+
self.authority.host.domain.sld
|
137
|
+
end
|
138
|
+
|
139
|
+
def sld=(sld)
|
140
|
+
self.authority.host.domain.sld = sld
|
141
|
+
end
|
142
|
+
|
143
|
+
def tld
|
144
|
+
self.authority.host.domain.tld
|
145
|
+
end
|
146
|
+
|
147
|
+
def tld=(sld)
|
148
|
+
self.authority.host.domain.tld = tld
|
149
|
+
end
|
150
|
+
|
151
|
+
def port
|
152
|
+
self.authority.port
|
153
|
+
end
|
154
|
+
|
155
|
+
def port=(port)
|
156
|
+
self.authority.port = port
|
157
|
+
end
|
158
|
+
|
159
|
+
def path
|
160
|
+
self.relative.path
|
161
|
+
end
|
162
|
+
|
163
|
+
def path=(path)
|
164
|
+
self.relative.path = path
|
165
|
+
end
|
166
|
+
|
167
|
+
def directory
|
168
|
+
self.relative.path.directory
|
169
|
+
end
|
170
|
+
|
171
|
+
def directory=(directory)
|
172
|
+
self.relative.path.directory = directory
|
173
|
+
end
|
174
|
+
|
175
|
+
def file
|
176
|
+
self.relative.path.file
|
177
|
+
end
|
178
|
+
|
179
|
+
def file=(file)
|
180
|
+
self.relative.path.file = file
|
181
|
+
end
|
182
|
+
|
183
|
+
def query
|
184
|
+
self.relative.query
|
185
|
+
end
|
186
|
+
|
187
|
+
def query=(query)
|
188
|
+
self.relative.query = query
|
189
|
+
end
|
190
|
+
|
191
|
+
def anchor
|
192
|
+
self.relative.anchor
|
193
|
+
end
|
194
|
+
|
195
|
+
def anchor=(anchor)
|
196
|
+
self.relative.anchor = anchor
|
197
|
+
end
|
198
|
+
|
199
|
+
# ======================================================================= #
|
200
|
+
# = Extras = #
|
201
|
+
# ======================================================================= #
|
202
|
+
|
203
|
+
def relative?
|
204
|
+
self.host.nil?
|
205
|
+
end
|
206
|
+
|
207
|
+
def absolute?
|
208
|
+
!relative?
|
209
|
+
end
|
210
|
+
|
211
|
+
def localhost?
|
212
|
+
!!(self.host =~ /^localhost$/i)
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'uniform_resource_identifier/parsable'
|
2
|
+
require 'uniform_resource_identifier/parser'
|
3
|
+
require 'uniform_resource_identifier/host'
|
4
|
+
require 'uniform_resource_identifier/user_info'
|
5
|
+
require 'active_support/core_ext/hash'
|
6
|
+
|
7
|
+
class UniformResourceIdentifier
|
8
|
+
class Authority
|
9
|
+
extend Parsable
|
10
|
+
|
11
|
+
def initialize(authority=nil)
|
12
|
+
if authority.respond_to?(:to_str)
|
13
|
+
authority = Parser.parse(authority)
|
14
|
+
|
15
|
+
@user_info = UserInfo.parse(authority[:user_info]) if authority.has_key?(:user_info)
|
16
|
+
@host = Host.parse(authority[:host]) if authority.has_key?(:host)
|
17
|
+
@port = authority[:port].to_i if authority.has_key?(:port)
|
18
|
+
elsif authority.respond_to?(:to_hash)
|
19
|
+
authority = authority.to_hash.symbolize_keys
|
20
|
+
|
21
|
+
@user_info = UserInfo.parse(authority[:user_info]) if authority.has_key?(:user_info)
|
22
|
+
@host = Host.parse(authority[:host]) if authority.has_key?(:host)
|
23
|
+
@port = authority[:port].to_i if authority.has_key?(:port)
|
24
|
+
else
|
25
|
+
raise(TypeError, "authority must either be a String or a Hash") unless authority.nil?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
user_info = "#{@user_info}@" unless @user_info.nil?
|
31
|
+
port = ":#{@port}" unless @port.nil?
|
32
|
+
"#{user_info}#{@host}#{port}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_h
|
36
|
+
{
|
37
|
+
:user_info => user_info.nil? ? nil : @user_info.to_h,
|
38
|
+
:host => host.nil? ? nil : @host.to_h,
|
39
|
+
:port => @port
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
# ======================================================================= #
|
44
|
+
# = Attributes = #
|
45
|
+
# ======================================================================= #
|
46
|
+
|
47
|
+
def user_info
|
48
|
+
@user_info ||= UserInfo.new
|
49
|
+
end
|
50
|
+
|
51
|
+
def user_info=(user_info)
|
52
|
+
@user_info = UserInfo.parse(user_info)
|
53
|
+
end
|
54
|
+
|
55
|
+
def host
|
56
|
+
@host ||= Host.new
|
57
|
+
end
|
58
|
+
|
59
|
+
def host=(host)
|
60
|
+
@host = Host.parse(user_info)
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_reader :port
|
64
|
+
|
65
|
+
def port=(port)
|
66
|
+
@port = port.to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
# ======================================================================= #
|
70
|
+
# = Delegates = #
|
71
|
+
# ======================================================================= #
|
72
|
+
|
73
|
+
def username
|
74
|
+
self.user_info.username
|
75
|
+
end
|
76
|
+
|
77
|
+
def username=(username)
|
78
|
+
self.user_info.username = username
|
79
|
+
end
|
80
|
+
|
81
|
+
def password
|
82
|
+
self.user_info.password
|
83
|
+
end
|
84
|
+
|
85
|
+
def password=(password)
|
86
|
+
self.user_info.password = password
|
87
|
+
end
|
88
|
+
|
89
|
+
def subdomain
|
90
|
+
self.host.subdomain
|
91
|
+
end
|
92
|
+
|
93
|
+
def subdomain=(subdomain)
|
94
|
+
self.host.subdomain = subdomain
|
95
|
+
end
|
96
|
+
|
97
|
+
def domain
|
98
|
+
self.host.domain ||= Domain.new
|
99
|
+
end
|
100
|
+
|
101
|
+
def domain=(domain)
|
102
|
+
self.host.domain = Domain.parse(domain)
|
103
|
+
end
|
104
|
+
|
105
|
+
def sld
|
106
|
+
self.host.domain.sld
|
107
|
+
end
|
108
|
+
|
109
|
+
def sld=(sld)
|
110
|
+
self.host.domain.sld = sld
|
111
|
+
end
|
112
|
+
|
113
|
+
def tld
|
114
|
+
self.host.domain.tld
|
115
|
+
end
|
116
|
+
|
117
|
+
def tld=(sld)
|
118
|
+
self.host.domain.tld = tld
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'uniform_resource_identifier/parsable'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
require 'public_suffix_service'
|
4
|
+
|
5
|
+
class UniformResourceIdentifier
|
6
|
+
class Domain
|
7
|
+
extend Parsable
|
8
|
+
|
9
|
+
def initialize(domain)
|
10
|
+
if domain.respond_to?(:to_str)
|
11
|
+
begin
|
12
|
+
pss = PublicSuffixService.parse(domain)
|
13
|
+
|
14
|
+
@sld, @tld = pss.sld, pss.tld
|
15
|
+
rescue PublicSuffixService::DomainInvalid
|
16
|
+
# We couldn't parse your tld (public suffix) =(
|
17
|
+
@tld = domain
|
18
|
+
end
|
19
|
+
elsif domain.respond_to?(:to_hash)
|
20
|
+
domain.to_hash.symbolize_keys
|
21
|
+
@sld, @tld = domain.values_at(:sld, :tld)
|
22
|
+
else
|
23
|
+
raise(TypeError, "domain must either be a String or a Hash") unless domain.nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
sld = "#{@sld}." unless @sld.nil?
|
29
|
+
"#{sld}#{@tld}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_h
|
33
|
+
{ :sld => @sld, :tld => @tld }
|
34
|
+
end
|
35
|
+
# ======================================================================= #
|
36
|
+
# = Attributes = #
|
37
|
+
# ======================================================================= #
|
38
|
+
|
39
|
+
attr_reader :sld
|
40
|
+
attr_reader :tld
|
41
|
+
|
42
|
+
def sld=(sld)
|
43
|
+
@sld = sld.nil? ? nil : sld.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
def tld=(tld)
|
47
|
+
@tld = tld.nil? ? nil : tld.to_s
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'uniform_resource_identifier/parsable'
|
2
|
+
require 'uniform_resource_identifier/domain'
|
3
|
+
require 'active_support/core_ext/hash'
|
4
|
+
require 'public_suffix_service'
|
5
|
+
|
6
|
+
class UniformResourceIdentifier
|
7
|
+
class Host
|
8
|
+
extend Parsable
|
9
|
+
|
10
|
+
def initialize(host=nil)
|
11
|
+
if host.respond_to?(:to_str)
|
12
|
+
begin
|
13
|
+
pss = PublicSuffixService.parse(host)
|
14
|
+
|
15
|
+
@subdomain = pss.trd
|
16
|
+
@domain = Domain.new(:sld => pss.sld, :tld => pss.tld)
|
17
|
+
rescue PublicSuffixService::DomainInvalid
|
18
|
+
# We couldn't parse your tld (public suffix) =(
|
19
|
+
@domain = Domain.new(:sld => nil, :tld => host) # TODO: is this proper? see Domain#to_s
|
20
|
+
end
|
21
|
+
elsif host.respond_to?(:to_hash)
|
22
|
+
host = host.to_hash.symbolize_keys
|
23
|
+
|
24
|
+
@subdomain = host[:subdomain]
|
25
|
+
@domain = Domain.new(host[:domain])
|
26
|
+
else
|
27
|
+
raise(TypeError, "host must either be a String or a Hash") unless host.nil?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
subdomain = "#{@subdomain}." unless @subdomain.nil?
|
33
|
+
"#{subdomain}#{@domain}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_h
|
37
|
+
{
|
38
|
+
:subdomain => @subdomain,
|
39
|
+
:domain => @domain.nil? ? nil : @domain.to_h
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
# ======================================================================= #
|
44
|
+
# = Attributes = #
|
45
|
+
# ======================================================================= #
|
46
|
+
|
47
|
+
attr_reader :subdomain
|
48
|
+
|
49
|
+
def subdomain=(subdomain)
|
50
|
+
@subdomain = subdomain.nil? ? subdomain : subdomain.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def domain
|
54
|
+
@domain ||= Domain.new
|
55
|
+
end
|
56
|
+
|
57
|
+
def domain=(domain)
|
58
|
+
@domain = Domain.parse(domain)
|
59
|
+
end
|
60
|
+
|
61
|
+
# ======================================================================= #
|
62
|
+
# = Delegates = #
|
63
|
+
# ======================================================================= #
|
64
|
+
|
65
|
+
def sld
|
66
|
+
self.domain.sld
|
67
|
+
end
|
68
|
+
|
69
|
+
def sld=(sld)
|
70
|
+
self.domain.sld = sld
|
71
|
+
end
|
72
|
+
|
73
|
+
def tld
|
74
|
+
self.domain.tld
|
75
|
+
end
|
76
|
+
|
77
|
+
def tld=(sld)
|
78
|
+
self.domain.tld = tld
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class UniformResourceIdentifier
|
2
|
+
module Parser
|
3
|
+
STRICT = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/
|
4
|
+
LOOSE = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
|
5
|
+
|
6
|
+
# Simply returns a Hash containing the captures
|
7
|
+
# mode can either be :strict or :loose
|
8
|
+
def self.parse(uri, mode=:loose)
|
9
|
+
raise(ArgumentError, "mode must either be :loose or :strict") unless [:loose, :strict].include?(mode)
|
10
|
+
|
11
|
+
regexp = mode == :loose ? LOOSE : STRICT
|
12
|
+
match = uri.match(regexp)
|
13
|
+
keys = [:protocol, :authority, :user_info, :username, :password, :host,
|
14
|
+
:port, :relative, :path, :directory, :file, :query, :anchor]
|
15
|
+
|
16
|
+
keys.each.with_index.inject({}) do |memo, (key, index)|
|
17
|
+
memo[key] = match.captures[index]
|
18
|
+
memo
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'uniform_resource_identifier/parsable'
|
2
|
+
require 'uniform_resource_identifier/parser'
|
3
|
+
require 'active_support/core_ext/hash'
|
4
|
+
|
5
|
+
class UniformResourceIdentifier
|
6
|
+
class Path
|
7
|
+
extend Parsable
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
if path.respond_to?(:to_str)
|
11
|
+
parsed_uri = Parser.parse(path)
|
12
|
+
@directory, @file = parsed_uri.values_at(:directory, :file)
|
13
|
+
elsif path.respond_to?(:to_hash)
|
14
|
+
path.to_hash.symbolize_keys
|
15
|
+
@directory, @file = path.values_at(:directory, :file)
|
16
|
+
else
|
17
|
+
raise(TypeError, "path must either be a String or a Hash") unless path.nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"#{@directory}#{@file}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_h
|
26
|
+
{
|
27
|
+
:directory => @directory,
|
28
|
+
:file => @file
|
29
|
+
}
|
30
|
+
end
|
31
|
+
# ======================================================================= #
|
32
|
+
# = Attributes = #
|
33
|
+
# ======================================================================= #
|
34
|
+
|
35
|
+
attr_reader :directory
|
36
|
+
attr_reader :file
|
37
|
+
|
38
|
+
def directory=(directory)
|
39
|
+
@directory = directory.nil? ? nil : directory.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
def file=(file)
|
43
|
+
@file = file.nil? ? nil : file.to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'uniform_resource_identifier/parsable'
|
2
|
+
require 'active_support/core_ext/object/to_query'
|
3
|
+
require 'addressable/uri'
|
4
|
+
|
5
|
+
class UniformResourceIdentifier
|
6
|
+
class Query
|
7
|
+
extend Parsable
|
8
|
+
|
9
|
+
def initialize(query)
|
10
|
+
if query.respond_to?(:to_str)
|
11
|
+
query = "#{query =~ /^\?/ ? nil : '?'}#{query.to_str}" # Prepend a question mark if needed
|
12
|
+
@query = Addressable::URI.parse(query).query_values
|
13
|
+
elsif query.respond_to?(:to_hash)
|
14
|
+
@query = query.to_hash
|
15
|
+
else
|
16
|
+
raise(TypeError, "query must either be a String or a Hash") unless query.nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
@query.to_query
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
@query
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'uniform_resource_identifier/parsable'
|
2
|
+
require 'uniform_resource_identifier/parser'
|
3
|
+
require 'uniform_resource_identifier/path'
|
4
|
+
require 'uniform_resource_identifier/query'
|
5
|
+
require 'active_support/core_ext/hash'
|
6
|
+
|
7
|
+
class UniformResourceIdentifier
|
8
|
+
class Relative
|
9
|
+
extend Parsable
|
10
|
+
|
11
|
+
def initialize(relative=nil)
|
12
|
+
if relative.respond_to?(:to_str)
|
13
|
+
parsed_uri = Parser.parse(relative)
|
14
|
+
# TODO
|
15
|
+
elsif relative.respond_to?(:to_hash)
|
16
|
+
relative = relative.to_hash.symbolize_keys
|
17
|
+
|
18
|
+
@path = Path.parse(relative[:path]) if relative.has_key?(:path)
|
19
|
+
@query = Query.parse(relative[:query]) if relative.has_key?(:query)
|
20
|
+
@anchor = relative[:anchor].to_s.gsub(/^#/, '') if relative.has_key?(:anchor)
|
21
|
+
else
|
22
|
+
raise(TypeError, "relative must either be a String or a Hash") unless relative.nil?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
query = "?#{@query}" unless @query.nil?
|
28
|
+
anchor = "##{@anchor}" unless @anchor.nil?
|
29
|
+
"#{@path}#{query}#{anchor}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_h
|
33
|
+
{
|
34
|
+
:path => path.nil? ? nil : @path.to_h,
|
35
|
+
:query => query.nil? ? nil : @query.to_h,
|
36
|
+
:anchor => @anchor
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# ======================================================================= #
|
41
|
+
# = Attributes = #
|
42
|
+
# ======================================================================= #
|
43
|
+
|
44
|
+
def path
|
45
|
+
@path ||= Path.new
|
46
|
+
end
|
47
|
+
|
48
|
+
def path=(path)
|
49
|
+
@path = Path.parse(path)
|
50
|
+
end
|
51
|
+
|
52
|
+
def query
|
53
|
+
@query ||= Query.new
|
54
|
+
end
|
55
|
+
|
56
|
+
def query=(query)
|
57
|
+
@query = Query.parse(query)
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :anchor
|
61
|
+
|
62
|
+
def anchor=(anchor)
|
63
|
+
@anchor = anchor.nil? ? nil : anchor.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
# ======================================================================= #
|
67
|
+
# = Delegates = #
|
68
|
+
# ======================================================================= #
|
69
|
+
|
70
|
+
def directory
|
71
|
+
self.path.directory
|
72
|
+
end
|
73
|
+
|
74
|
+
def directory=(directory)
|
75
|
+
self.path.directory = directory
|
76
|
+
end
|
77
|
+
|
78
|
+
def file
|
79
|
+
self.path.file
|
80
|
+
end
|
81
|
+
|
82
|
+
def file=(file)
|
83
|
+
self.path.file = file
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
RSpec::Matchers.define(:have_uri_specification) do |uri_specification|
|
2
|
+
match do |uri_string|
|
3
|
+
url = UniformResourceIdentifier.parse(uri_string)
|
4
|
+
|
5
|
+
# ======================================================================= #
|
6
|
+
# = Protocol/Scheme = #
|
7
|
+
# ======================================================================= #
|
8
|
+
|
9
|
+
url.protocol.class.should == String
|
10
|
+
url.protocol.to_s.should == uri_specification[:protocol]
|
11
|
+
url.scheme.class.should == String # Alias
|
12
|
+
url.scheme.to_s.should == uri_specification[:protocol] # Alias
|
13
|
+
|
14
|
+
# ======================================================================= #
|
15
|
+
# = Authority = #
|
16
|
+
# ======================================================================= #
|
17
|
+
|
18
|
+
url.authority.class.should == UniformResourceIdentifier::Authority
|
19
|
+
url.authority.to_s.should == uri_specification[:authority]
|
20
|
+
|
21
|
+
url.authority.user_info.class.should == UniformResourceIdentifier::UserInfo
|
22
|
+
url.authority.user_info.to_s.should == uri_specification[:user_info]
|
23
|
+
url.user_info.class.should == UniformResourceIdentifier::UserInfo # Delegate
|
24
|
+
url.user_info.to_s.should == uri_specification[:user_info] # Delegate
|
25
|
+
|
26
|
+
url.authority.user_info.username.class.should == String
|
27
|
+
url.authority.user_info.username.to_s.should == uri_specification[:username]
|
28
|
+
url.user_info.username.class.should == String # Delegate
|
29
|
+
url.user_info.username.to_s.should == uri_specification[:username] # Delegate
|
30
|
+
url.username.class.should == String # Delegate
|
31
|
+
url.username.to_s.should == uri_specification[:username] # Delegate
|
32
|
+
|
33
|
+
url.authority.user_info.password.class.should == String
|
34
|
+
url.authority.user_info.password.to_s.should == uri_specification[:password]
|
35
|
+
url.user_info.password.class.should == String # Delegate
|
36
|
+
url.user_info.password.to_s.should == uri_specification[:password] # Delegate
|
37
|
+
url.password.class.should == String # Delegate
|
38
|
+
url.password.to_s.should == uri_specification[:password] # Delegate
|
39
|
+
|
40
|
+
url.authority.host.class.should == UniformResourceIdentifier::Host
|
41
|
+
url.authority.host.to_s.should == uri_specification[:host]
|
42
|
+
url.host.class.should == UniformResourceIdentifier::Host # Delegate
|
43
|
+
url.host.to_s.should == uri_specification[:host] # Delegate
|
44
|
+
|
45
|
+
url.authority.host.subdomain.class.should == String
|
46
|
+
url.authority.host.subdomain.to_s.should == uri_specification[:subdomain]
|
47
|
+
url.host.subdomain.class.should == String # Delegate
|
48
|
+
url.host.subdomain.to_s.should == uri_specification[:subdomain] # Delegate
|
49
|
+
url.subdomain.class.should == String # Delegate
|
50
|
+
url.subdomain.to_s.should == uri_specification[:subdomain] # Delegate
|
51
|
+
|
52
|
+
url.authority.host.domain.class.should == UniformResourceIdentifier::Domain
|
53
|
+
url.authority.host.domain.to_s.should == uri_specification[:domain]
|
54
|
+
url.host.domain.class.should == UniformResourceIdentifier::Domain # Delegate
|
55
|
+
url.host.domain.to_s.should == uri_specification[:domain] # Delegate
|
56
|
+
url.domain.class.should == UniformResourceIdentifier::Domain # Delegate
|
57
|
+
url.domain.to_s.should == uri_specification[:domain] # Delegate
|
58
|
+
|
59
|
+
url.authority.host.domain.sld.class.should == String
|
60
|
+
url.authority.host.sld.to_s.should == uri_specification[:sld]
|
61
|
+
url.host.sld.class.should == String # Delegate
|
62
|
+
url.host.sld.to_s.should == uri_specification[:sld] # Delegate
|
63
|
+
url.sld.class.should == String # Delegate
|
64
|
+
url.sld.to_s.should == uri_specification[:sld] # Delegate
|
65
|
+
|
66
|
+
url.authority.host.domain.tld.class.should == String
|
67
|
+
url.authority.host.tld.to_s.should == uri_specification[:tld]
|
68
|
+
url.host.tld.class.should == String # Delegate
|
69
|
+
url.host.tld.to_s.should == uri_specification[:tld] # Delegate
|
70
|
+
url.tld.class.should == String # Delegate
|
71
|
+
url.tld.to_s.should == uri_specification[:tld] # Delegate
|
72
|
+
|
73
|
+
url.authority.port.class.should == Fixnum
|
74
|
+
url.authority.port.to_s.should == uri_specification[:port]
|
75
|
+
url.port.class.should == Fixnum # Delegate
|
76
|
+
url.port.to_s.should == uri_specification[:port] # Delegate
|
77
|
+
|
78
|
+
# ======================================================================= #
|
79
|
+
# = Relative = #
|
80
|
+
# ======================================================================= #
|
81
|
+
|
82
|
+
url.relative.class.should == UniformResourceIdentifier::Relative
|
83
|
+
url.relative.to_s.should == uri_specification[:relative]
|
84
|
+
|
85
|
+
url.relative.path.class.should == UniformResourceIdentifier::Path
|
86
|
+
url.relative.path.to_s.should == uri_specification[:path]
|
87
|
+
url.path.class.should == UniformResourceIdentifier::Path # Delegate
|
88
|
+
url.path.to_s.should == uri_specification[:path] # Delegate
|
89
|
+
|
90
|
+
url.relative.path.directory.class.should == String
|
91
|
+
url.relative.path.directory.to_s.should == uri_specification[:directory]
|
92
|
+
url.relative.directory.class.should == String # Delegate
|
93
|
+
url.relative.directory.to_s.should == uri_specification[:directory] # Delegate
|
94
|
+
url.directory.class.should == String # Delegate
|
95
|
+
url.directory.to_s.should == uri_specification[:directory] # Delegate
|
96
|
+
|
97
|
+
url.relative.path.file.class.should == String
|
98
|
+
url.relative.path.file.to_s.should == uri_specification[:file]
|
99
|
+
url.relative.file.class.should == String # Delegate
|
100
|
+
url.relative.file.to_s.should == uri_specification[:file] # Delegate
|
101
|
+
url.file.class.should == String # Delegate
|
102
|
+
url.file.to_s.should == uri_specification[:file] # Delegate
|
103
|
+
|
104
|
+
url.relative.query.class.should == UniformResourceIdentifier::Query
|
105
|
+
url.relative.query.to_s.should == uri_specification[:query]
|
106
|
+
url.query.class.should == UniformResourceIdentifier::Query # Delegate
|
107
|
+
url.query.to_s.should == uri_specification[:query] # Delegate
|
108
|
+
|
109
|
+
url.relative.anchor.class.should == String
|
110
|
+
url.relative.anchor.to_s.should == uri_specification[:anchor]
|
111
|
+
url.anchor.class.should == String # Delegate
|
112
|
+
url.anchor.to_s.should == uri_specification[:anchor] # Delegate
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'uniform_resource_identifier/parsable'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
|
4
|
+
class UniformResourceIdentifier
|
5
|
+
class UserInfo
|
6
|
+
extend Parsable
|
7
|
+
|
8
|
+
def initialize(user_info=nil)
|
9
|
+
if user_info.respond_to?(:to_str)
|
10
|
+
@username, @password = user_info.to_str.split(":")
|
11
|
+
elsif user_info.respond_to?(:to_hash)
|
12
|
+
user_info.to_hash.symbolize_keys
|
13
|
+
@username, @password = user_info.values_at(:username, :password)
|
14
|
+
else
|
15
|
+
raise(TypeError, "user_info must either be a String or a Hash") unless user_info.nil?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{@username}:#{@password}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_h
|
24
|
+
{
|
25
|
+
:username => @username,
|
26
|
+
:password => @password
|
27
|
+
}
|
28
|
+
end
|
29
|
+
# ======================================================================= #
|
30
|
+
# = Attributes = #
|
31
|
+
# ======================================================================= #
|
32
|
+
|
33
|
+
attr_reader :username
|
34
|
+
attr_reader :password
|
35
|
+
|
36
|
+
def username=(username)
|
37
|
+
@username = username.nil? ? username : username.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def password=(password)
|
41
|
+
@password = password.nil? ? password : password.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UniformResourceIdentifier::Parser do
|
4
|
+
subject { UniformResourceIdentifier::Parser }
|
5
|
+
|
6
|
+
describe "#parse" do
|
7
|
+
it "should return a Hash containing the correct results" do
|
8
|
+
url = "http://usr:pwd@www.test.com:81/dir/dir.2/foo/bar/index.htm?q1=0&&test1&test2=value&arr[]=one&arr[]=two&hsh[foo]=bar&test3=val3#top"
|
9
|
+
|
10
|
+
result_hash = {
|
11
|
+
:protocol => "http",
|
12
|
+
:authority => "usr:pwd@www.test.com:81",
|
13
|
+
:user_info => "usr:pwd",
|
14
|
+
:username => "usr",
|
15
|
+
:password => "pwd",
|
16
|
+
:host => "www.test.com",
|
17
|
+
:port => "81",
|
18
|
+
:relative => "/dir/dir.2/foo/bar/index.htm?q1=0&&test1&test2=value&arr[]=one&arr[]=two&hsh[foo]=bar&test3=val3#top",
|
19
|
+
:path => "/dir/dir.2/foo/bar/index.htm",
|
20
|
+
:directory => "/dir/dir.2/foo/bar/",
|
21
|
+
:file => "index.htm",
|
22
|
+
:query => "q1=0&&test1&test2=value&arr[]=one&arr[]=two&hsh[foo]=bar&test3=val3",
|
23
|
+
:anchor => "top"
|
24
|
+
}
|
25
|
+
|
26
|
+
subject.parse(url, :loose).should == result_hash
|
27
|
+
subject.parse(url, :strict).should == result_hash
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Example URIs:
|
4
|
+
# ftp://ftp.is.co.za/rfc/rfc1808.txt
|
5
|
+
# http://www.ietf.org/rfc/rfc2396.txt
|
6
|
+
# ldap://[2001:db8::7]/c=GB?objectClass?one
|
7
|
+
# mailto:John.Doe@example.com
|
8
|
+
# news:comp.infosystems.www.servers.unix
|
9
|
+
# tel:+1-816-555-1212
|
10
|
+
# telnet://192.0.2.16:80/
|
11
|
+
# urn:oasis:names:specification:docbook:dtd:xml:4.1.2
|
12
|
+
# http://www.foobar.com/test/bar?q=some+thing
|
13
|
+
# www.foobar.com/
|
14
|
+
# foobar.com/contact_us
|
15
|
+
# admin.foobar.com/task/123
|
16
|
+
# admin.testpage.com
|
17
|
+
# /about
|
18
|
+
# index.htm
|
19
|
+
# awesome-things.org/thing/42
|
20
|
+
# foo-bar.org/mist
|
21
|
+
# water.com
|
22
|
+
# https://www.water.org/ice
|
23
|
+
# http://example.org/absolute/URI/with/absolute/path/to/resource.txt
|
24
|
+
# ftp://example.org/resource.txt
|
25
|
+
# http://en.wikipedia.org/wiki/URI#Examples_of_URI_references
|
26
|
+
# http://example.org/absolute/URI/with/absolute/path/to/resource.txt
|
27
|
+
# //example.org/scheme-relative/URI/with/absolute/path/to/resource.txt
|
28
|
+
# /relative/URI/with/absolute/path/to/resource.txt
|
29
|
+
# relative/path/to/resource.txt
|
30
|
+
# ../../../resource.txt
|
31
|
+
# ./resource.txt#frag01
|
32
|
+
# resource.txt
|
33
|
+
# #frag01
|
34
|
+
# http://en.wikipedia.org/wiki/Uniform_Resource_Identifier
|
35
|
+
# http://the_english_dept.tripod.com/north.html
|
36
|
+
|
37
|
+
describe UniformResourceIdentifier do
|
38
|
+
subject { UniformResourceIdentifier }
|
39
|
+
|
40
|
+
let(:url) do
|
41
|
+
"http://usr:pwd@www.test.com:81/dir/dir.2/foo/bar/index.htm?q1=0&&test1&test2=value&arr[]=one&arr[]=two&hsh[foo]=bar&test3=val3#top"
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#parse" do
|
45
|
+
it "should correctly parse the given URL" do
|
46
|
+
url.should have_uri_specification(
|
47
|
+
:protocol => "http",
|
48
|
+
:authority => "usr:pwd@www.test.com:81",
|
49
|
+
:user_info => "usr:pwd",
|
50
|
+
:username => "usr",
|
51
|
+
:password => "pwd",
|
52
|
+
:host => "www.test.com",
|
53
|
+
:subdomain => "www",
|
54
|
+
:domain => "test.com",
|
55
|
+
:sld => "test",
|
56
|
+
:tld => "com",
|
57
|
+
:port => "81",
|
58
|
+
:relative => "/dir/dir.2/foo/bar/index.htm?q1=0&test1=true&test2=value&arr[]=one&arr[]=two&hsh[foo]=bar&test3=val3#top",
|
59
|
+
:path => "/dir/dir.2/foo/bar/index.htm",
|
60
|
+
:directory => "/dir/dir.2/foo/bar/",
|
61
|
+
:file => "index.htm",
|
62
|
+
:query => "q1=0&test1=true&test2=value&arr[]=one&arr[]=two&hsh[foo]=bar&test3=val3",
|
63
|
+
:anchor => "top"
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#to_s" do
|
69
|
+
it "should return the normalized URI" do
|
70
|
+
subject.parse(url).to_s.should == "http://usr:pwd@www.test.com:81/dir/dir.2/foo/bar/index.htm?q1=0&test1=true&test2=value&arr[]=one&arr[]=two&hsh[foo]=bar&test3=val3#top"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#to_h" do
|
75
|
+
it "should return the correct Hash result" do
|
76
|
+
subject.parse(url).to_h.should == {
|
77
|
+
:protocol =>"http",
|
78
|
+
:authority => {
|
79
|
+
:user_info => {
|
80
|
+
:username => "usr",
|
81
|
+
:password => "pwd"
|
82
|
+
},
|
83
|
+
:host => {
|
84
|
+
:subdomain => "www",
|
85
|
+
:domain => {
|
86
|
+
:sld => "test",
|
87
|
+
:tld => "com"
|
88
|
+
}
|
89
|
+
},
|
90
|
+
:port => 81
|
91
|
+
},
|
92
|
+
:relative => {
|
93
|
+
:path => {
|
94
|
+
:directory => "/dir/dir.2/foo/bar/",
|
95
|
+
:file => "index.htm"
|
96
|
+
},
|
97
|
+
:query => { # TODO: Should the query_values be strings?
|
98
|
+
"q1" => "0",
|
99
|
+
"test1" => true,
|
100
|
+
"test2" => "value",
|
101
|
+
"arr" => ["one", "two"],
|
102
|
+
"hsh" => {
|
103
|
+
"foo" => "bar"
|
104
|
+
},
|
105
|
+
"test3" => "val3"
|
106
|
+
},
|
107
|
+
:anchor=>"top"
|
108
|
+
}
|
109
|
+
}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "The example from the README" do
|
114
|
+
it "should be correct, to say the least." do
|
115
|
+
url = "foo://usr:pwd@www.example.co.uk:8042/over/there.htm?name=ferret#nose"
|
116
|
+
uri = UniformResourceIdentifier.parse(url)
|
117
|
+
|
118
|
+
uri.protocol.should == "foo"
|
119
|
+
|
120
|
+
uri.authority.to_s.should == "usr:pwd@www.example.co.uk:8042"
|
121
|
+
|
122
|
+
uri.authority.user_info.to_s.should == "usr:pwd"
|
123
|
+
uri.user_info.to_s.should == "usr:pwd"
|
124
|
+
|
125
|
+
uri.authority.user_info.username.should == "usr"
|
126
|
+
uri.authority.user_info.password.should == "pwd"
|
127
|
+
uri.user_info.username.should == "usr"
|
128
|
+
uri.user_info.password.should == "pwd"
|
129
|
+
uri.username.should == "usr"
|
130
|
+
uri.password.should == "pwd"
|
131
|
+
|
132
|
+
uri.authority.host.to_s.should == "www.example.co.uk"
|
133
|
+
uri.host.to_s.should == "www.example.co.uk"
|
134
|
+
|
135
|
+
uri.authority.host.subdomain.should == "www"
|
136
|
+
uri.authority.subdomain.should == "www"
|
137
|
+
uri.subdomain.should == "www"
|
138
|
+
|
139
|
+
uri.authority.host.domain.to_s.should == "example.co.uk"
|
140
|
+
uri.authority.domain.to_s.should == "example.co.uk"
|
141
|
+
uri.domain.to_s.should == "example.co.uk"
|
142
|
+
|
143
|
+
uri.authority.host.domain.sld.should == "example"
|
144
|
+
uri.authority.domain.sld.should == "example"
|
145
|
+
uri.domain.sld.should == "example"
|
146
|
+
uri.sld.should == "example"
|
147
|
+
|
148
|
+
uri.authority.host.domain.tld.should == "co.uk"
|
149
|
+
uri.authority.domain.tld.should == "co.uk"
|
150
|
+
uri.domain.tld.should == "co.uk"
|
151
|
+
uri.tld.should == "co.uk"
|
152
|
+
|
153
|
+
uri.authority.port.should == 8042
|
154
|
+
uri.port.should == 8042
|
155
|
+
|
156
|
+
uri.relative.to_s.should == "/over/there.htm?name=ferret#nose"
|
157
|
+
|
158
|
+
uri.relative.path.to_s.should == "/over/there.htm"
|
159
|
+
uri.path.to_s.should == "/over/there.htm"
|
160
|
+
|
161
|
+
uri.relative.path.directory.to_s.should == "/over/"
|
162
|
+
uri.relative.directory.to_s.should == "/over/"
|
163
|
+
uri.directory.to_s.should == "/over/"
|
164
|
+
|
165
|
+
uri.relative.path.file.to_s.should == "there.htm"
|
166
|
+
uri.relative.file.to_s.should == "there.htm"
|
167
|
+
uri.file.to_s.should == "there.htm"
|
168
|
+
|
169
|
+
uri.relative.query.to_h.should == { "name" => "ferret" }
|
170
|
+
uri.relative.query.to_s.should == "name=ferret"
|
171
|
+
uri.query.to_h.should == { "name" => "ferret" }
|
172
|
+
uri.query.to_s.should == "name=ferret"
|
173
|
+
|
174
|
+
uri.relative.anchor.should == "nose"
|
175
|
+
uri.anchor.should == "nose"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
metadata
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: uniform_resource_identifier
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Scott Lewis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-31 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: public_suffix_service
|
16
|
+
requirement: &70216311725500 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70216311725500
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: active_support
|
27
|
+
requirement: &70216311725020 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70216311725020
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: addressable
|
38
|
+
requirement: &70216311724560 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.2.6
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70216311724560
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: &70216311724100 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.0
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70216311724100
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rspec
|
60
|
+
requirement: &70216311723640 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 2.6.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70216311723640
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fuubar
|
71
|
+
requirement: &70216311723180 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.0.6
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70216311723180
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: watchr
|
82
|
+
requirement: &70216311722720 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 0.7.0
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70216311722720
|
91
|
+
description: ! '`uniform_resource_identifier` splits URIs according to RFC 3986 using
|
92
|
+
regexp, attempts to check the public suffix using `public_suffix_service`, and serializes
|
93
|
+
the query string using `active_support` and `addressable`'
|
94
|
+
email: c00lryguy@gmail.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files:
|
98
|
+
- LICENSE
|
99
|
+
- VERSION
|
100
|
+
files:
|
101
|
+
- LICENSE
|
102
|
+
- VERSION
|
103
|
+
- lib/uniform_resource_identifier/authority.rb
|
104
|
+
- lib/uniform_resource_identifier/domain.rb
|
105
|
+
- lib/uniform_resource_identifier/host.rb
|
106
|
+
- lib/uniform_resource_identifier/parsable.rb
|
107
|
+
- lib/uniform_resource_identifier/parser.rb
|
108
|
+
- lib/uniform_resource_identifier/path.rb
|
109
|
+
- lib/uniform_resource_identifier/query.rb
|
110
|
+
- lib/uniform_resource_identifier/relative.rb
|
111
|
+
- lib/uniform_resource_identifier/rspec_matcher.rb
|
112
|
+
- lib/uniform_resource_identifier/user_info.rb
|
113
|
+
- lib/uniform_resource_identifier.rb
|
114
|
+
- spec/spec_helper.rb
|
115
|
+
- spec/uniform_resource_identifier/parser_spec.rb
|
116
|
+
- spec/uniform_resource_identifier_spec.rb
|
117
|
+
homepage: http://github.com/c00lryguy/uniform_resource_identifier
|
118
|
+
licenses: []
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ! '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
requirements: []
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 1.8.10
|
138
|
+
signing_key:
|
139
|
+
specification_version: 3
|
140
|
+
summary: A library to split URIs according to RFC 3986 as closely as possible.
|
141
|
+
test_files:
|
142
|
+
- spec/spec_helper.rb
|
143
|
+
- spec/uniform_resource_identifier/parser_spec.rb
|
144
|
+
- spec/uniform_resource_identifier_spec.rb
|