furi 0.2.0 → 0.2.1
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 +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
|