furi 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -10
- data/furi.gemspec +1 -1
- data/lib/furi.rb +22 -6
- data/lib/furi/uri.rb +75 -18
- data/lib/furi/version.rb +1 -1
- data/spec/furi/uri_spec.rb +12 -0
- data/spec/furi_spec.rb +186 -108
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9c81dc7acc1ab6c12a180cf8722a10e4bad93b8
|
4
|
+
data.tar.gz: 88787eb5df40194b9373c14375e94523cb9a0191
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92ae36c027f8f38d9c9617595b6aedade9db5b7f652021660a3502813e63ba6b4062669fed3b1ba7c7d01846a0ab0251ff77752ca7f47a15e3d8482353743ad2
|
7
|
+
data.tar.gz: 8e756624ec091e58981ed3c1d8c0e998b22168fef6c1a1b0e41cf31a3d39037efad32fb9a62fe725322c7efa65600fcff8824efbc321b0bd79d7af95ca327b13
|
data/README.md
CHANGED
@@ -36,9 +36,9 @@ Furi.port!("http://gusiev.com") # => 80
|
|
36
36
|
|
37
37
|
Furi.update("http://gusiev.com", protocol: '') # => "//gusiev.com"
|
38
38
|
Furi.update("http://gusiev.com?source=google", query: {email: "a@b.com"})
|
39
|
-
# => "http://gusiev.com?email=a@b.com"
|
40
|
-
Furi.merge("http://gusiev.com?source=google", query: {email: "a@b.com"})
|
41
39
|
# => "http://gusiev.com?source=google&email=a@b.com"
|
40
|
+
Furi.replace("http://gusiev.com?source=google", query: {email: "a@b.com"})
|
41
|
+
# => "http://gusiev.com?email=a@b.com"
|
42
42
|
|
43
43
|
Furi.build(protocol: '//', host: 'gusiev.com', path: '/assets/application.js')
|
44
44
|
# => "//gusiev.com/assets/application.js"
|
@@ -113,14 +113,6 @@ Giving credit...
|
|
113
113
|
* rfc3986 validation
|
114
114
|
* mailto protocol
|
115
115
|
* escaping in path
|
116
|
-
* case insensetivity:
|
117
|
-
* domain
|
118
|
-
* protocol
|
119
|
-
* case sensitivity:
|
120
|
-
* path
|
121
|
-
* query
|
122
|
-
* anchor
|
123
|
-
* basic auth data ?
|
124
116
|
|
125
117
|
## Contributing
|
126
118
|
|
data/furi.gemspec
CHANGED
@@ -21,5 +21,5 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.7"
|
22
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
23
|
spec.add_development_dependency "rspec"
|
24
|
-
spec.add_development_dependency "byebug"
|
24
|
+
spec.add_development_dependency "pry-byebug"
|
25
25
|
end
|
data/lib/furi.rb
CHANGED
@@ -35,6 +35,7 @@ module Furi
|
|
35
35
|
"tftp" => {port: 69},
|
36
36
|
"sftp" => {port: 22},
|
37
37
|
"ssh" => {port: 22, ssl: true},
|
38
|
+
"svn" => {port: 3690},
|
38
39
|
"svn+ssh" => {port: 22, ssl: true},
|
39
40
|
"telnet" => {port: 23},
|
40
41
|
"nntp" => {port: 119},
|
@@ -42,6 +43,10 @@ module Furi
|
|
42
43
|
"wais" => {port: 210},
|
43
44
|
"ldap" => {port: 389},
|
44
45
|
"prospero" => {port: 1525},
|
46
|
+
"file" => {port: nil},
|
47
|
+
"postgres" => {port: 5432},
|
48
|
+
"mysql" => {port: 3306},
|
49
|
+
"mailto" => {port: nil}
|
45
50
|
}
|
46
51
|
|
47
52
|
|
@@ -56,8 +61,9 @@ module Furi
|
|
56
61
|
ROOT = '/'
|
57
62
|
|
58
63
|
# Parses a given string and return an URL object
|
59
|
-
|
60
|
-
|
64
|
+
# Optionally accepts parts to update the parsed URL object
|
65
|
+
def self.parse(argument, parts = nil)
|
66
|
+
Uri.new(argument).update(parts)
|
61
67
|
end
|
62
68
|
|
63
69
|
# Builds an URL from given parts
|
@@ -83,6 +89,9 @@ module Furi
|
|
83
89
|
def self.update(string, parts)
|
84
90
|
parse(string).update(parts).to_s
|
85
91
|
end
|
92
|
+
class << self
|
93
|
+
alias :merge :update
|
94
|
+
end
|
86
95
|
|
87
96
|
# Puts the default values for given URL that are not defined
|
88
97
|
#
|
@@ -94,16 +103,17 @@ module Furi
|
|
94
103
|
|
95
104
|
# Replaces a given URL string with given parts.
|
96
105
|
# Same as update but works different for URL query parameter:
|
97
|
-
#
|
106
|
+
# replaces newly specified parameters instead of merging to existing ones
|
98
107
|
#
|
99
|
-
# Furi.
|
108
|
+
# Furi.update("/hello.html?a=1", host: 'gusiev.com', query: {b: 2})
|
100
109
|
# # => "gusiev.com/hello.html?a=1&b=2"
|
101
110
|
#
|
102
|
-
def self.
|
103
|
-
parse(string).
|
111
|
+
def self.replace(string, parts)
|
112
|
+
parse(string).replace(parts).to_s
|
104
113
|
end
|
105
114
|
|
106
115
|
|
116
|
+
|
107
117
|
# Parses a query into nested paramters hash using a rack convension with square brackets.
|
108
118
|
#
|
109
119
|
# Furi.parse_query("a[]=1&a[]=2") # => {a: [1,2]}
|
@@ -159,6 +169,12 @@ module Furi
|
|
159
169
|
serialize_tokens(query, namespace).join("&")
|
160
170
|
end
|
161
171
|
|
172
|
+
def self.join(*uris)
|
173
|
+
uris.map do |uri|
|
174
|
+
Furi.parse(uri)
|
175
|
+
end.reduce(:join)
|
176
|
+
end
|
177
|
+
|
162
178
|
class FormattingError < StandardError
|
163
179
|
end
|
164
180
|
|
data/lib/furi/uri.rb
CHANGED
@@ -21,21 +21,28 @@ module Furi
|
|
21
21
|
when String
|
22
22
|
parse_uri_string(argument)
|
23
23
|
when Hash
|
24
|
-
|
24
|
+
replace(argument)
|
25
|
+
when ::URI::Generic
|
26
|
+
parse_uri_string(argument.to_s)
|
27
|
+
else
|
28
|
+
raise ArgumentError, "wrong Uri argument"
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
28
|
-
def
|
29
|
-
parts
|
30
|
-
|
32
|
+
def replace(parts)
|
33
|
+
if parts
|
34
|
+
parts.each do |part, value|
|
35
|
+
self[part] = value
|
36
|
+
end
|
31
37
|
end
|
32
38
|
self
|
33
39
|
end
|
34
40
|
|
35
|
-
def
|
41
|
+
def update(parts)
|
42
|
+
return self unless parts
|
36
43
|
parts.each do |part, value|
|
37
44
|
case part.to_sym
|
38
|
-
when :query, :query_tokens
|
45
|
+
when :query, :query_tokens, :query_string
|
39
46
|
merge_query(value)
|
40
47
|
else
|
41
48
|
self[part] = value
|
@@ -91,7 +98,7 @@ module Furi
|
|
91
98
|
when "", nil
|
92
99
|
nil
|
93
100
|
else
|
94
|
-
host.to_s
|
101
|
+
host.to_s.downcase
|
95
102
|
end
|
96
103
|
end
|
97
104
|
|
@@ -166,7 +173,7 @@ module Furi
|
|
166
173
|
def to_s
|
167
174
|
result = []
|
168
175
|
result << location
|
169
|
-
result << (host ? path : path!)
|
176
|
+
result << (host || mailto? ? path : path!)
|
170
177
|
if query_tokens.any?
|
171
178
|
result << "?" << query_string
|
172
179
|
end
|
@@ -178,10 +185,12 @@ module Furi
|
|
178
185
|
|
179
186
|
def location
|
180
187
|
if protocol
|
181
|
-
|
188
|
+
if !host && !mailto?
|
182
189
|
raise Furi::FormattingError, "can not build URI with protocol but without host"
|
183
190
|
end
|
184
|
-
[
|
191
|
+
[
|
192
|
+
protocol.empty? ? "" : "#{protocol}:", authority
|
193
|
+
].join(mailto? ? "" : "//")
|
185
194
|
else
|
186
195
|
authority
|
187
196
|
end
|
@@ -196,12 +205,17 @@ module Furi
|
|
196
205
|
end
|
197
206
|
|
198
207
|
def request
|
208
|
+
return nil if !path && query_tokens.empty?
|
199
209
|
result = []
|
200
210
|
result << path!
|
201
211
|
result << "?" << query_string if query_tokens.any?
|
202
212
|
result.join
|
203
213
|
end
|
204
214
|
|
215
|
+
def request!
|
216
|
+
request || path!
|
217
|
+
end
|
218
|
+
|
205
219
|
def request=(string)
|
206
220
|
string = parse_anchor_and_query(string)
|
207
221
|
self.path = string
|
@@ -218,11 +232,13 @@ module Furi
|
|
218
232
|
|
219
233
|
|
220
234
|
def query=(value)
|
221
|
-
@query = nil
|
222
|
-
@query_tokens = []
|
223
235
|
case value
|
236
|
+
when true
|
237
|
+
# Assuming that current query needs to be parsed to Hash
|
238
|
+
query
|
224
239
|
when String, Array
|
225
240
|
self.query_tokens = value
|
241
|
+
@query = nil
|
226
242
|
when Hash
|
227
243
|
self.query_tokens = value
|
228
244
|
@query = value
|
@@ -283,9 +299,12 @@ module Furi
|
|
283
299
|
end
|
284
300
|
|
285
301
|
def protocol=(protocol)
|
286
|
-
@protocol = protocol ? protocol.gsub(%r{:?/?/?\Z}, "") : nil
|
302
|
+
@protocol = protocol ? protocol.gsub(%r{:?/?/?\Z}, "").downcase : nil
|
287
303
|
end
|
288
304
|
|
305
|
+
def protocol!
|
306
|
+
protocol || default_protocol_for_port || 'http' # Web Rules Them All!
|
307
|
+
end
|
289
308
|
|
290
309
|
def directory
|
291
310
|
path_tokens[0..-2].join("/")
|
@@ -361,11 +380,11 @@ module Furi
|
|
361
380
|
end
|
362
381
|
|
363
382
|
def default_port
|
364
|
-
|
383
|
+
Furi::PROTOCOLS.fetch(protocol, {})[:port]
|
365
384
|
end
|
366
385
|
|
367
386
|
def ssl?
|
368
|
-
!!(
|
387
|
+
!!(Furi::PROTOCOLS.fetch(protocol, {})[:ssl])
|
369
388
|
end
|
370
389
|
|
371
390
|
def ssl
|
@@ -395,7 +414,12 @@ module Furi
|
|
395
414
|
Furi::WEB_PROTOCOL.include?(protocol)
|
396
415
|
end
|
397
416
|
|
417
|
+
def abstract_protocol?
|
418
|
+
protocol == ""
|
419
|
+
end
|
420
|
+
|
398
421
|
def resource
|
422
|
+
return nil unless request
|
399
423
|
[request, anchor].compact.join("#")
|
400
424
|
end
|
401
425
|
|
@@ -412,7 +436,7 @@ module Furi
|
|
412
436
|
end
|
413
437
|
|
414
438
|
def resource!
|
415
|
-
|
439
|
+
resource || request!
|
416
440
|
end
|
417
441
|
|
418
442
|
def host!
|
@@ -440,12 +464,25 @@ module Furi
|
|
440
464
|
send(:"#{part}=", value)
|
441
465
|
end
|
442
466
|
|
467
|
+
def rfc?
|
468
|
+
rfc3986?
|
469
|
+
end
|
470
|
+
|
443
471
|
def rfc3986?
|
444
472
|
uri = to_s
|
445
|
-
!!(uri.match(URI::RFC3986_Parser::
|
473
|
+
!!(uri.match(URI::RFC3986_Parser::RFC3986_URI) ||
|
446
474
|
uri.match(URI::RFC3986_Parser::RFC3986_relative_ref))
|
447
475
|
end
|
448
476
|
|
477
|
+
def email=(email)
|
478
|
+
self.protocol ||= "mailto"
|
479
|
+
self.authority = email
|
480
|
+
end
|
481
|
+
|
482
|
+
def email
|
483
|
+
authority
|
484
|
+
end
|
485
|
+
|
449
486
|
protected
|
450
487
|
|
451
488
|
def file_tokens
|
@@ -461,6 +498,9 @@ module Furi
|
|
461
498
|
end
|
462
499
|
|
463
500
|
def parse_uri_string(string)
|
501
|
+
if string.empty?
|
502
|
+
raise Furi::FormattingError, "can not be an empty string"
|
503
|
+
end
|
464
504
|
string = parse_anchor_and_query(string)
|
465
505
|
|
466
506
|
string = parse_protocol(string)
|
@@ -499,8 +539,12 @@ module Furi
|
|
499
539
|
string
|
500
540
|
end
|
501
541
|
|
542
|
+
def join(uri)
|
543
|
+
Uri.new(::URI.join(to_s, uri.to_s))
|
544
|
+
end
|
545
|
+
|
502
546
|
def parse_protocol(string)
|
503
|
-
if string.include?("://")
|
547
|
+
if string.include?("://") || string.start_with?("mailto:")
|
504
548
|
protocol, string = string.split(":", 2)
|
505
549
|
self.protocol = protocol
|
506
550
|
end
|
@@ -529,5 +573,18 @@ module Furi
|
|
529
573
|
def host_tokens
|
530
574
|
host.split(".")
|
531
575
|
end
|
576
|
+
|
577
|
+
def default_protocol_for_port
|
578
|
+
return nil unless port
|
579
|
+
PROTOCOLS.each do |protocol, data|
|
580
|
+
if data[:port] == port
|
581
|
+
return protocol
|
582
|
+
end
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
def mailto?
|
587
|
+
protocol == "mailto"
|
588
|
+
end
|
532
589
|
end
|
533
590
|
end
|
data/lib/furi/version.rb
CHANGED
data/spec/furi_spec.rb
CHANGED
@@ -64,7 +64,13 @@ describe Furi do
|
|
64
64
|
|
65
65
|
|
66
66
|
|
67
|
-
describe "
|
67
|
+
describe ".parse" do
|
68
|
+
|
69
|
+
it "raises on empty string" do
|
70
|
+
expect {
|
71
|
+
Furi.parse("")
|
72
|
+
}.to raise_error(Furi::FormattingError)
|
73
|
+
end
|
68
74
|
|
69
75
|
it "parses URL with everything" do
|
70
76
|
expect("http://user:pass@www.gusiev.com:8080/articles/index.html?a=1&b=2#header").to have_parts(
|
@@ -105,8 +111,10 @@ describe Furi do
|
|
105
111
|
path: nil,
|
106
112
|
path!: '/',
|
107
113
|
port: nil,
|
108
|
-
request:
|
109
|
-
|
114
|
+
request: nil,
|
115
|
+
request!: '/',
|
116
|
+
resource: nil,
|
117
|
+
resource!: '/',
|
110
118
|
location: 'http://gusiev.com',
|
111
119
|
home_page?: true,
|
112
120
|
)
|
@@ -305,6 +313,14 @@ describe Furi do
|
|
305
313
|
)
|
306
314
|
end
|
307
315
|
|
316
|
+
it "downcases only protocol and host" do
|
317
|
+
expect("HTTP://GUSIEV.cOM/About").to have_parts(
|
318
|
+
protocol: 'http',
|
319
|
+
host: 'gusiev.com',
|
320
|
+
path: "/About",
|
321
|
+
)
|
322
|
+
end
|
323
|
+
|
308
324
|
describe "ipv6 host" do
|
309
325
|
it "parses host and port" do
|
310
326
|
expect("http://[2406:da00:ff00::6b14:8d43]:8080/").to have_parts(
|
@@ -333,123 +349,144 @@ describe Furi do
|
|
333
349
|
)
|
334
350
|
end
|
335
351
|
end
|
336
|
-
end
|
337
|
-
describe ".update" do
|
338
352
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
end
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
expect(Furi.
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
expect(Furi.
|
360
|
-
|
361
|
-
|
362
|
-
expect(Furi.
|
363
|
-
expect(Furi.
|
364
|
-
expect(Furi.
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
expect(Furi.
|
369
|
-
|
370
|
-
|
371
|
-
expect(Furi.
|
372
|
-
expect(Furi.
|
373
|
-
expect(Furi.
|
374
|
-
expect(Furi.
|
375
|
-
|
376
|
-
|
377
|
-
expect(Furi.
|
378
|
-
|
379
|
-
|
353
|
+
describe "mailto" do
|
354
|
+
it "without email" do
|
355
|
+
expect("mailto:?subject=Talkable%20is%20Hiring&body=https%3A%2F%2Fwww.talkable.com%2Fjobs").to have_parts(
|
356
|
+
protocol: 'mailto',
|
357
|
+
email: nil,
|
358
|
+
query: {
|
359
|
+
"subject" => "Talkable is Hiring",
|
360
|
+
"body" => "https://www.talkable.com/jobs"
|
361
|
+
}
|
362
|
+
)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
describe ".replace" do
|
367
|
+
|
368
|
+
it "support replace for query" do
|
369
|
+
expect(Furi.replace("/index.html?a=b", query: {c: 'd'})).to eq('/index.html?c=d')
|
370
|
+
end
|
371
|
+
|
372
|
+
it "replace hostname" do
|
373
|
+
expect(Furi.replace("www.gusiev.com/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
|
374
|
+
expect(Furi.replace("/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
|
375
|
+
expect(Furi.replace("http://www.gusiev.com/index.html", hostname: 'gusiev.com')).to eq('http://gusiev.com/index.html')
|
376
|
+
expect(Furi.replace("/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
|
377
|
+
expect(Furi.replace("gusiev.com/index.html?a=b", hostname: nil)).to eq('/index.html?a=b')
|
378
|
+
expect(Furi.replace("gusiev.com?a=b", hostname: nil)).to eq('/?a=b')
|
379
|
+
end
|
380
|
+
|
381
|
+
it "replace port" do
|
382
|
+
expect(Furi.replace("gusiev.com", port: 33)).to eq('gusiev.com:33')
|
383
|
+
expect(Furi.replace("gusiev.com/index.html", port: 33)).to eq('gusiev.com:33/index.html')
|
384
|
+
expect(Furi.replace("gusiev.com:33/index.html", port: 80)).to eq('gusiev.com:80/index.html')
|
385
|
+
expect(Furi.replace("http://gusiev.com:33/index.html", port: 80)).to eq('http://gusiev.com/index.html')
|
386
|
+
expect(Furi.replace("http://gusiev.com:33/index.html", port: nil)).to eq('http://gusiev.com/index.html')
|
387
|
+
expect(Furi.replace("http://gusiev.com:33/index.html", port: 0)).to eq('http://gusiev.com:0/index.html')
|
388
|
+
expect(Furi.replace("http://gusiev.com:33/index.html", port: '')).to eq('http://gusiev.com/index.html')
|
389
|
+
end
|
390
|
+
it "replace directory" do
|
391
|
+
expect(Furi.replace("gusiev.com", directory: 'articles')).to eq('gusiev.com/articles')
|
392
|
+
expect(Furi.replace("gusiev.com/", directory: 'articles')).to eq('gusiev.com/articles')
|
393
|
+
expect(Furi.replace("gusiev.com/index#header", directory: '/posts')).to eq('gusiev.com/posts/index#header')
|
394
|
+
expect(Furi.replace("gusiev.com/articles/#header", directory: nil)).to eq('gusiev.com/#header')
|
395
|
+
expect(Furi.replace("gusiev.com/articles/index?a=b", directory: 'posts')).to eq('gusiev.com/posts/index?a=b')
|
396
|
+
expect(Furi.replace("/articles/index?a=b", directory: '/posts')).to eq('/posts/index?a=b')
|
397
|
+
expect(Furi.replace("/articles/index.html?a=b", directory: '/posts/')).to eq('/posts/index.html?a=b')
|
398
|
+
end
|
399
|
+
it "replace filename" do
|
400
|
+
expect(Furi.replace("gusiev.com", filename: 'article')).to eq('gusiev.com/article')
|
401
|
+
expect(Furi.replace("gusiev.com/", filename: 'article')).to eq('gusiev.com/article')
|
402
|
+
expect(Furi.replace("gusiev.com/article1#header", filename: '/article2')).to eq('gusiev.com/article2#header')
|
403
|
+
expect(Furi.replace("gusiev.com/article#header", filename: nil)).to eq('gusiev.com/#header')
|
404
|
+
expect(Furi.replace("gusiev.com/articles/article1?a=b", filename: 'article2')).to eq('gusiev.com/articles/article2?a=b')
|
405
|
+
expect(Furi.replace("/articles/article1?a=b", filename: '/article2')).to eq('/articles/article2?a=b')
|
406
|
+
expect(Furi.replace("/articles/article1.xml?a=b", filename: 'article2.html')).to eq('/articles/article2.html?a=b')
|
407
|
+
end
|
408
|
+
it "replace extension" do
|
380
409
|
expect(->{
|
381
|
-
Furi.
|
410
|
+
Furi.replace("gusiev.com/", extension: 'xml')
|
382
411
|
}).to raise_error(Furi::FormattingError)
|
383
|
-
expect(Furi.
|
384
|
-
expect(Furi.
|
385
|
-
expect(Furi.
|
412
|
+
expect(Furi.replace("gusiev.com/article#header", extension: 'html')).to eq('gusiev.com/article.html#header')
|
413
|
+
expect(Furi.replace("gusiev.com/article.html?header", extension: nil)).to eq('gusiev.com/article?header')
|
414
|
+
expect(Furi.replace("gusiev.com/article.xml?a=b", extension: 'html')).to eq('gusiev.com/article.html?a=b')
|
386
415
|
end
|
387
|
-
it "
|
388
|
-
expect(Furi.
|
389
|
-
expect(Furi.
|
390
|
-
expect(Furi.
|
391
|
-
expect(Furi.
|
416
|
+
it "replace resource" do
|
417
|
+
expect(Furi.replace("gusiev.com", resource: '/article?a=1#hello')).to eq('gusiev.com/article?a=1#hello')
|
418
|
+
expect(Furi.replace("gusiev.com/article1#header", resource: '/article2')).to eq('gusiev.com/article2')
|
419
|
+
expect(Furi.replace("gusiev.com/article#header", resource: nil)).to eq('gusiev.com')
|
420
|
+
expect(Furi.replace("gusiev.com/article1?a=b", resource: 'article2')).to eq('gusiev.com/article2')
|
392
421
|
end
|
393
|
-
it "
|
394
|
-
expect(Furi.
|
395
|
-
expect(Furi.
|
396
|
-
expect(Furi.
|
397
|
-
expect(Furi.
|
422
|
+
it "replace path" do
|
423
|
+
expect(Furi.replace("gusiev.com", path: '/article')).to eq('gusiev.com/article')
|
424
|
+
expect(Furi.replace("gusiev.com/article1#header", path: '/article2')).to eq('gusiev.com/article2#header')
|
425
|
+
expect(Furi.replace("gusiev.com/article#header", path: nil)).to eq('gusiev.com#header')
|
426
|
+
expect(Furi.replace("gusiev.com/article1?a=b", path: 'article2')).to eq('gusiev.com/article2?a=b')
|
398
427
|
end
|
399
428
|
|
400
|
-
it "
|
401
|
-
expect(Furi.
|
402
|
-
expect(Furi.
|
403
|
-
expect(Furi.
|
404
|
-
expect(Furi.
|
429
|
+
it "replace ssl" do
|
430
|
+
expect(Furi.replace("http://gusiev.com", ssl: true)).to eq('https://gusiev.com')
|
431
|
+
expect(Furi.replace("https://gusiev.com", ssl: true)).to eq('https://gusiev.com')
|
432
|
+
expect(Furi.replace("https://gusiev.com", ssl: false)).to eq('http://gusiev.com')
|
433
|
+
expect(Furi.replace("http://gusiev.com", ssl: false)).to eq('http://gusiev.com')
|
405
434
|
end
|
406
435
|
|
407
|
-
it "
|
408
|
-
expect(Furi.
|
409
|
-
expect(Furi.
|
410
|
-
expect(Furi.
|
411
|
-
expect(Furi.
|
412
|
-
expect(Furi.
|
413
|
-
expect(Furi.
|
414
|
-
expect(Furi.
|
436
|
+
it "replace protocol" do
|
437
|
+
expect(Furi.replace("http://gusiev.com", protocol: '')).to eq('//gusiev.com')
|
438
|
+
expect(Furi.replace("http://gusiev.com", protocol: nil)).to eq('gusiev.com')
|
439
|
+
expect(Furi.replace("http://gusiev.com", protocol: 'https')).to eq('https://gusiev.com')
|
440
|
+
expect(Furi.replace("gusiev.com", protocol: 'http')).to eq('http://gusiev.com')
|
441
|
+
expect(Furi.replace("gusiev.com", protocol: 'http:')).to eq('http://gusiev.com')
|
442
|
+
expect(Furi.replace("gusiev.com", protocol: 'http:/')).to eq('http://gusiev.com')
|
443
|
+
expect(Furi.replace("gusiev.com", protocol: 'http://')).to eq('http://gusiev.com')
|
415
444
|
end
|
416
445
|
|
417
|
-
it "
|
418
|
-
expect(Furi.
|
419
|
-
expect(Furi.
|
420
|
-
expect(Furi.
|
421
|
-
expect(Furi.
|
446
|
+
it "replace userinfo" do
|
447
|
+
expect(Furi.replace("http://gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
|
448
|
+
expect(Furi.replace("http://aa:bb@gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
|
449
|
+
expect(Furi.replace("http://aa:bb@gusiev.com", userinfo: nil)).to eq('http://gusiev.com')
|
450
|
+
expect(Furi.replace("http://aa@gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
|
422
451
|
end
|
423
452
|
|
424
|
-
it "
|
425
|
-
expect(Furi.
|
453
|
+
it "replace authority" do
|
454
|
+
expect(Furi.replace("http://user:pass@gusiev.com:8080/index.html", authority: 'gusiev.com')).to eq('http://gusiev.com/index.html')
|
426
455
|
end
|
427
456
|
|
428
|
-
it "
|
429
|
-
expect(Furi.
|
457
|
+
it "replace request" do
|
458
|
+
expect(Furi.replace("http://gusiev.com:8080/index.html?c=d", request: '/blog.html?a=b')).to eq('http://gusiev.com:8080/blog.html?a=b')
|
430
459
|
end
|
431
460
|
|
432
|
-
it "
|
433
|
-
expect(Furi.
|
434
|
-
expect(Furi.
|
435
|
-
expect(Furi.
|
461
|
+
it "replace domainzone" do
|
462
|
+
expect(Furi.replace("http://gusiev.com:8080", domainzone: 'com.ua')).to eq('http://gusiev.com.ua:8080')
|
463
|
+
expect(Furi.replace("http://gusiev.com.ua:8080", domainzone: 'com')).to eq('http://gusiev.com:8080')
|
464
|
+
expect(Furi.replace("http://gusiev.com.ua:8080", domainzone: nil)).to eq('http://gusiev:8080')
|
436
465
|
end
|
437
466
|
|
438
|
-
it "
|
439
|
-
expect(Furi.
|
440
|
-
expect(Furi.
|
467
|
+
it "replace domainname" do
|
468
|
+
expect(Furi.replace("http://gusiev.com", domainname: 'google')).to eq('http://google.com')
|
469
|
+
expect(Furi.replace("http://gusiev.com", domainname: nil)).to eq('http://com')
|
441
470
|
end
|
442
|
-
it "
|
443
|
-
expect(Furi.
|
444
|
-
expect(Furi.
|
471
|
+
it "replace subdomain" do
|
472
|
+
expect(Furi.replace("http://gusiev.com", subdomain: 'blog')).to eq('http://blog.gusiev.com')
|
473
|
+
expect(Furi.replace("http://blog.gusiev.com", subdomain: nil)).to eq('http://gusiev.com')
|
445
474
|
end
|
446
475
|
|
447
|
-
it "
|
448
|
-
expect(Furi.
|
449
|
-
expect(Furi.
|
450
|
-
expect(Furi.
|
451
|
-
expect(Furi.
|
452
|
-
expect(Furi.
|
476
|
+
it "replace location" do
|
477
|
+
expect(Furi.replace("/index.html", location: 'http://gusiev.com')).to eq('http://gusiev.com/index.html')
|
478
|
+
expect(Furi.replace("/index.html", location: 'http://gusiev.com/')).to eq('http://gusiev.com/index.html')
|
479
|
+
expect(Furi.replace("gusiev.com:433/index.html", location: 'gusiev.com:80')).to eq('gusiev.com:80/index.html')
|
480
|
+
expect(Furi.replace("gusiev.com:433/index.html", location: nil)).to eq('/index.html')
|
481
|
+
expect(Furi.replace("http://gusiev.com:433/index.html", location: nil)).to eq('/index.html')
|
482
|
+
end
|
483
|
+
|
484
|
+
it "replace query" do
|
485
|
+
expect(Furi.replace("/", query: {a: 1})).to eq('/?a=1')
|
486
|
+
expect(Furi.replace("/", query: {a: [1,2]})).to eq('/?a%5B%5D=1&a%5B%5D=2')
|
487
|
+
expect(Furi.replace("/", query: {a: 1, b: 2})).to eq('/?a=1&b=2')
|
488
|
+
expect(Furi.replace("/?a=1", query: {a: 2})).to eq('/?a=2')
|
489
|
+
expect(Furi.replace("/?a=1&a=1", query: true)).to eq('/?a=1')
|
453
490
|
end
|
454
491
|
|
455
492
|
end
|
@@ -475,15 +512,26 @@ describe Furi do
|
|
475
512
|
Furi.build(host: 'localhost', password: 'pass')
|
476
513
|
}).to raise_error(Furi::FormattingError)
|
477
514
|
end
|
515
|
+
|
516
|
+
it "builds protocol" do
|
517
|
+
expect(Furi.build(protocol: 'http', host: 'hello.com', port: 80)).to eq('http://hello.com')
|
518
|
+
expect(Furi.build(protocol: 'mailto', username: "bogdan", host: 'gusiev.com')).to eq('mailto:bogdan@gusiev.com')
|
519
|
+
expect(Furi.build(email: "bogdan@gusiev.com")).to eq('mailto:bogdan@gusiev.com')
|
520
|
+
expect(Furi.build(protocol: 'mailto', query: {subject: 'Hello', body: "Welcome"})).to eq('mailto:?subject=Hello&body=Welcome')
|
521
|
+
|
522
|
+
end
|
478
523
|
end
|
479
524
|
|
480
|
-
describe ".
|
481
|
-
it "
|
482
|
-
expect(Furi.
|
483
|
-
expect(Furi.
|
484
|
-
expect(Furi.
|
485
|
-
expect(Furi.
|
486
|
-
expect(Furi.
|
525
|
+
describe ".update" do
|
526
|
+
it "updates query" do
|
527
|
+
expect(Furi.update("//gusiev.com", query: {a: 1})).to eq('//gusiev.com?a=1')
|
528
|
+
expect(Furi.update("//gusiev.com?a=1", query: {b: 2})).to eq('//gusiev.com?a=1&b=2')
|
529
|
+
expect(Furi.update("//gusiev.com?a=1", query: {a: 2})).to eq('//gusiev.com?a=2')
|
530
|
+
expect(Furi.update("//gusiev.com?a=1", query: [['a', 2], ['b', 3]])).to eq('//gusiev.com?a=1&a=2&b=3')
|
531
|
+
expect(Furi.update("//gusiev.com?a=1&b=2", query: '?a=3')).to eq('//gusiev.com?a=1&b=2&a=3')
|
532
|
+
end
|
533
|
+
it "updates query_string" do
|
534
|
+
expect(Furi.update("//gusiev.com?a=1&b=2", query_string: '?a=3')).to eq('//gusiev.com?a=1&b=2&a=3')
|
487
535
|
end
|
488
536
|
end
|
489
537
|
|
@@ -515,8 +563,32 @@ describe Furi do
|
|
515
563
|
expect(Furi.parse('http://gusiev.com') == Furi.parse('http://gusiev.com')).to be_truthy
|
516
564
|
expect(Furi.parse('http://gusiev.com.ua') == Furi.parse('http://gusiev.com')).to be_falsey
|
517
565
|
expect(Furi.parse('http://gusiev.com?a=1&a=1') == Furi.parse('http://gusiev.com?a=1')).to be_falsey
|
518
|
-
|
519
|
-
|
566
|
+
end
|
567
|
+
|
568
|
+
it "works with query parameters" do
|
569
|
+
expect(Furi.parse('/?b=1&a=1') == Furi.parse('/?b=1&a=1')).to be_truthy
|
570
|
+
expect(Furi.parse('/?a=1&a=1') == Furi.parse('/?a=1')).to be_falsey
|
571
|
+
expect(Furi.parse('/') == Furi.parse('/?a=1')).to be_falsey
|
572
|
+
expect(Furi.parse('/') == Furi.parse('http://gusiev.com?a=1')).to be_falsey
|
573
|
+
|
574
|
+
end
|
575
|
+
|
576
|
+
it "ignores case only on protocol and host" do
|
577
|
+
expect(Furi.parse('hTTp://gUSiev.cOm') == Furi.parse('http://gusiev.com')).to be_truthy
|
578
|
+
expect(Furi.parse('/hello') == Furi.parse('/Hello')).to be_falsey
|
579
|
+
expect(Furi.parse('/hello?a=1') == Furi.parse('/hello?A=1')).to be_falsey
|
580
|
+
expect(Furi.parse('hTTp://gusiev.cOm') == Furi.parse('http://gusiev.com')).to be_truthy
|
581
|
+
expect(Furi.parse('/#h1') == Furi.parse('/#H1')).to be_falsey
|
582
|
+
expect(Furi.parse('hello@gusiev.com') == Furi.parse('Hello@gusiev.com')).to be_falsey
|
583
|
+
expect(Furi.parse('hello:psswd@gusiev.com') == Furi.parse('hello:Psswd@gusiev.com')).to be_falsey
|
584
|
+
end
|
585
|
+
|
586
|
+
end
|
587
|
+
|
588
|
+
describe "#abstract_protocol" do
|
589
|
+
it "works" do
|
590
|
+
expect(Furi.parse('http://gUSiev.cOm')).to_not be_abstract_protocol
|
591
|
+
expect(Furi.parse('//gUSiev.cOm')).to be_abstract_protocol
|
520
592
|
end
|
521
593
|
end
|
522
594
|
|
@@ -580,7 +652,7 @@ describe Furi do
|
|
580
652
|
end
|
581
653
|
end
|
582
654
|
|
583
|
-
describe "parse_query" do
|
655
|
+
describe ".parse_query" do
|
584
656
|
it "should work" do
|
585
657
|
Furi.parse_query("foo").
|
586
658
|
should eq "foo" => nil
|
@@ -665,4 +737,10 @@ describe Furi do
|
|
665
737
|
expect(Furi.parse('http://google.com').inspect).to eq("#<Furi::Uri \"http://google.com\">")
|
666
738
|
end
|
667
739
|
|
740
|
+
|
741
|
+
describe ".join" do
|
742
|
+
it "works" do
|
743
|
+
expect(Furi.join("http://gusiev.com/slides", "../photos")).to eq("http://gusiev.com/photos")
|
744
|
+
end
|
745
|
+
end
|
668
746
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: furi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bogdan Gusiev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: byebug
|
56
|
+
name: pry-byebug
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -86,6 +86,7 @@ files:
|
|
86
86
|
- lib/furi/uri.rb
|
87
87
|
- lib/furi/utils.rb
|
88
88
|
- lib/furi/version.rb
|
89
|
+
- spec/furi/uri_spec.rb
|
89
90
|
- spec/furi_spec.rb
|
90
91
|
- spec/spec_helper.rb
|
91
92
|
homepage: ''
|
@@ -108,10 +109,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
109
|
version: '0'
|
109
110
|
requirements: []
|
110
111
|
rubyforge_project:
|
111
|
-
rubygems_version: 2.
|
112
|
+
rubygems_version: 2.6.7
|
112
113
|
signing_key:
|
113
114
|
specification_version: 4
|
114
115
|
summary: Make URI processing as easy as it should be
|
115
116
|
test_files:
|
117
|
+
- spec/furi/uri_spec.rb
|
116
118
|
- spec/furi_spec.rb
|
117
119
|
- spec/spec_helper.rb
|