furi 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -12
- data/lib/furi.rb +17 -8
- data/lib/furi/query_token.rb +3 -3
- data/lib/furi/uri.rb +13 -13
- data/lib/furi/version.rb +1 -1
- data/spec/furi_spec.rb +32 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e47171efdec80d8610e7dea95a1eed17876ea14b
|
4
|
+
data.tar.gz: 33a2e11ef018c0d5c9d6695ced7c15e9f3dd3fb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e0c644b931d878b69b6d902aad0772aefa16a5ff4066db3bab871912dbe1e0b4ed91b41d4fb1b921ddfe36119f60293081e6b924cab8747865c1aa1451d3ebe
|
7
|
+
data.tar.gz: 1bbc865cbe5551b416a28243260e01e01409b600f32fd83b8b3a3da320cc7f9f6ce1bdc82363d92a1b8dd1941de99356e38a4d2903a57ad2f8ef956db4a22f23
|
data/README.md
CHANGED
@@ -29,21 +29,34 @@ Here are basic:
|
|
29
29
|
### Utility Methods
|
30
30
|
|
31
31
|
|
32
|
+
Parsing the URI fragments:
|
33
|
+
|
32
34
|
``` ruby
|
33
35
|
Furi.host("http://gusiev.com") # => "gusiev.com"
|
34
36
|
Furi.port("http://gusiev.com") # => nil
|
35
37
|
Furi.port!("http://gusiev.com") # => 80
|
38
|
+
```
|
36
39
|
|
40
|
+
Updating the URI parts:
|
41
|
+
|
42
|
+
```
|
37
43
|
Furi.update("http://gusiev.com", protocol: '') # => "//gusiev.com"
|
38
44
|
Furi.update("http://gusiev.com?source=google", query: {email: "a@b.com"})
|
39
45
|
# => "http://gusiev.com?source=google&email=a@b.com"
|
40
46
|
Furi.replace("http://gusiev.com?source=google", query: {email: "a@b.com"})
|
41
47
|
# => "http://gusiev.com?email=a@b.com"
|
42
48
|
|
49
|
+
Furi.defaults("http://gusiev.com", subdomain: 'www') # => "http://www.gusiev.com"
|
50
|
+
Furi.defaults("http://blog.gusiev.com", subdomain: 'www') # => "http://blog.gusiev.com"
|
51
|
+
|
52
|
+
```
|
53
|
+
|
54
|
+
Building an URI from initial parts:
|
55
|
+
|
56
|
+
``` ruby
|
57
|
+
|
43
58
|
Furi.build(protocol: '//', host: 'gusiev.com', path: '/assets/application.js')
|
44
59
|
# => "//gusiev.com/assets/application.js"
|
45
|
-
|
46
|
-
Furi.defaults("http://gusiev.com", subdomain: 'www') # => "http://www.gusiev.com"
|
47
60
|
```
|
48
61
|
|
49
62
|
### Working with Object
|
@@ -93,13 +106,13 @@ uri.merge_query(person: {email: 'a@b.com'})
|
|
93
106
|
/ __|___ __|__ ______|______ | _________|__________ ____|____ |
|
94
107
|
/ / \ / \ / \ / \/ \ / \ / \
|
95
108
|
http://username:zhongguo@www.example.com:80/hello/world/article.html?name=bogdan#info
|
96
|
-
\_/ \_/ \___/ \_/ \__________/
|
97
|
-
| | | | |
|
98
|
-
protocol subdomain | domainzone directory
|
99
|
-
| |
|
100
|
-
domainname /
|
101
|
-
\___/
|
102
|
-
|
|
109
|
+
\_/ \_/ \___/ \_/ \__________/\ / \_/
|
110
|
+
| | | | | \___/ |
|
111
|
+
protocol subdomain | domainzone directory | extension
|
112
|
+
| | filename |
|
113
|
+
domainname / \_____/
|
114
|
+
\___/ |
|
115
|
+
| file
|
103
116
|
domain
|
104
117
|
```
|
105
118
|
|
@@ -110,9 +123,8 @@ Giving credit...
|
|
110
123
|
|
111
124
|
## TODO
|
112
125
|
|
113
|
-
*
|
114
|
-
*
|
115
|
-
* escaping in path
|
126
|
+
* Improve URI.join algorithm to match the one used in Addressible library
|
127
|
+
* Implement filename
|
116
128
|
|
117
129
|
## Contributing
|
118
130
|
|
data/lib/furi.rb
CHANGED
@@ -14,7 +14,7 @@ module Furi
|
|
14
14
|
COMBINED_PARTS = [
|
15
15
|
:hostinfo, :userinfo, :authority, :ssl, :domain, :domainname,
|
16
16
|
:domainzone, :request, :location, :query,
|
17
|
-
:extension, :
|
17
|
+
:directory, :extension, :file
|
18
18
|
]
|
19
19
|
PARTS = ESSENTIAL_PARTS + COMBINED_PARTS
|
20
20
|
|
@@ -152,7 +152,7 @@ module Furi
|
|
152
152
|
QueryToken.parse(p)
|
153
153
|
end
|
154
154
|
else
|
155
|
-
raise
|
155
|
+
raise QueryParseError, "can not parse #{query.inspect} query tokens"
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -175,7 +175,16 @@ module Furi
|
|
175
175
|
end.reduce(:join)
|
176
176
|
end
|
177
177
|
|
178
|
-
class
|
178
|
+
class Error < StandardError
|
179
|
+
end
|
180
|
+
|
181
|
+
class FormattingError < Error
|
182
|
+
end
|
183
|
+
|
184
|
+
class ParseError < Error
|
185
|
+
end
|
186
|
+
|
187
|
+
class QueryParseError < Error
|
179
188
|
end
|
180
189
|
|
181
190
|
protected
|
@@ -195,13 +204,13 @@ module Furi
|
|
195
204
|
result
|
196
205
|
when Array
|
197
206
|
if namespace.nil? || namespace.empty?
|
198
|
-
raise
|
207
|
+
raise FormattingError, "Can not serialize Array without namespace"
|
199
208
|
end
|
200
209
|
|
201
210
|
namespace = "#{namespace}[]"
|
202
211
|
query.map do |item|
|
203
212
|
if item.is_a?(Array)
|
204
|
-
raise
|
213
|
+
raise FormattingError, "Can not serialize #{item.inspect} as element of an Array"
|
205
214
|
end
|
206
215
|
serialize_tokens(item, namespace)
|
207
216
|
end
|
@@ -227,14 +236,14 @@ module Furi
|
|
227
236
|
elsif after == "[]"
|
228
237
|
current ||= []
|
229
238
|
unless current.is_a?(Array)
|
230
|
-
raise
|
239
|
+
raise QueryParseError, "expected Array (got #{current.class}) for param `#{namespace}'"
|
231
240
|
end
|
232
241
|
current << value
|
233
242
|
elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
|
234
243
|
child_key = $1
|
235
244
|
current ||= []
|
236
245
|
unless current.is_a?(Array)
|
237
|
-
raise
|
246
|
+
raise QueryParseError, "expected Array (got #{current.class}) for param `#{namespace}'"
|
238
247
|
end
|
239
248
|
if current.last.is_a?(Hash) && !current.last.key?(child_key)
|
240
249
|
parse_query_token(current.last, child_key, value)
|
@@ -244,7 +253,7 @@ module Furi
|
|
244
253
|
else
|
245
254
|
current ||= {}
|
246
255
|
unless current.is_a?(Hash)
|
247
|
-
raise
|
256
|
+
raise QueryParseError, "expected Hash (got #{current.class}) for param `#{namespace}'"
|
248
257
|
end
|
249
258
|
current = parse_query_token(current, after, value)
|
250
259
|
end
|
data/lib/furi/query_token.rb
CHANGED
@@ -20,7 +20,7 @@ module Furi
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.raise_parse_error(token)
|
23
|
-
raise
|
23
|
+
raise QueryParseError, "Can not parse query token #{token.inspect}"
|
24
24
|
end
|
25
25
|
|
26
26
|
def initialize(name, value)
|
@@ -40,8 +40,8 @@ module Furi
|
|
40
40
|
|
41
41
|
def to_s
|
42
42
|
encoded_key = ::URI.encode_www_form_component(name.to_s)
|
43
|
-
|
44
|
-
!value.nil? ?
|
43
|
+
|
44
|
+
!value.nil? ?
|
45
45
|
"#{encoded_key}=#{::URI.encode_www_form_component(value.to_s)}" :
|
46
46
|
encoded_key
|
47
47
|
end
|
data/lib/furi/uri.rb
CHANGED
@@ -25,7 +25,7 @@ module Furi
|
|
25
25
|
when ::URI::Generic
|
26
26
|
parse_uri_string(argument.to_s)
|
27
27
|
else
|
28
|
-
raise
|
28
|
+
raise ParseError, "wrong Uri argument"
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -77,7 +77,7 @@ module Furi
|
|
77
77
|
self.query_tokens += Furi.query_tokens(query)
|
78
78
|
when nil
|
79
79
|
else
|
80
|
-
raise
|
80
|
+
raise QueryParseError, "#{query.inspect} can not be merged"
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -244,7 +244,7 @@ module Furi
|
|
244
244
|
@query = value
|
245
245
|
when nil
|
246
246
|
else
|
247
|
-
raise
|
247
|
+
raise QueryParseError, 'Query can only be Hash or String'
|
248
248
|
end
|
249
249
|
end
|
250
250
|
|
@@ -312,14 +312,14 @@ module Furi
|
|
312
312
|
|
313
313
|
def directory=(string)
|
314
314
|
string ||= "/"
|
315
|
-
if
|
315
|
+
if file && string !~ %r{/\z}
|
316
316
|
string += '/'
|
317
317
|
end
|
318
|
-
self.path = string +
|
318
|
+
self.path = string + file.to_s
|
319
319
|
end
|
320
320
|
|
321
321
|
def extension
|
322
|
-
return nil unless
|
322
|
+
return nil unless file
|
323
323
|
file_tokens.size > 1 ? file_tokens.last : nil
|
324
324
|
end
|
325
325
|
|
@@ -327,7 +327,7 @@ module Furi
|
|
327
327
|
tokens = file_tokens
|
328
328
|
case tokens.size
|
329
329
|
when 0
|
330
|
-
raise Furi::FormattingError, "can not assign extension when there is no
|
330
|
+
raise Furi::FormattingError, "can not assign extension when there is no file"
|
331
331
|
when 1
|
332
332
|
tokens.push(string)
|
333
333
|
else
|
@@ -337,10 +337,10 @@ module Furi
|
|
337
337
|
tokens.pop
|
338
338
|
end
|
339
339
|
end
|
340
|
-
self.
|
340
|
+
self.file = tokens.join(".")
|
341
341
|
end
|
342
342
|
|
343
|
-
def
|
343
|
+
def file=(name)
|
344
344
|
unless name
|
345
345
|
return unless path
|
346
346
|
else
|
@@ -395,13 +395,13 @@ module Furi
|
|
395
395
|
self.protocol = find_protocol_for_ssl(ssl)
|
396
396
|
end
|
397
397
|
|
398
|
-
def
|
398
|
+
def file
|
399
399
|
result = path_tokens.last
|
400
400
|
result == "" ? nil : result
|
401
401
|
end
|
402
402
|
|
403
|
-
def
|
404
|
-
|
403
|
+
def file!
|
404
|
+
file || ''
|
405
405
|
end
|
406
406
|
|
407
407
|
def default_web_port?
|
@@ -486,7 +486,7 @@ module Furi
|
|
486
486
|
protected
|
487
487
|
|
488
488
|
def file_tokens
|
489
|
-
|
489
|
+
file ? file.split('.') : []
|
490
490
|
end
|
491
491
|
|
492
492
|
def query_level?
|
data/lib/furi/version.rb
CHANGED
data/spec/furi_spec.rb
CHANGED
@@ -90,7 +90,7 @@ describe Furi do
|
|
90
90
|
|
91
91
|
resource: '/articles/index.html?a=1&b=2#header',
|
92
92
|
path: "/articles/index.html",
|
93
|
-
|
93
|
+
file: 'index.html',
|
94
94
|
extension: 'html',
|
95
95
|
query_string: "a=1&b=2",
|
96
96
|
query_tokens: [['a', '1'], ['b', '2']],
|
@@ -139,7 +139,7 @@ describe Furi do
|
|
139
139
|
resource: '/posts/index.html?a=b#zz',
|
140
140
|
request: '/posts/index.html?a=b',
|
141
141
|
location: 'http://gusiev.com',
|
142
|
-
|
142
|
+
file: 'index.html',
|
143
143
|
extension: 'html',
|
144
144
|
)
|
145
145
|
end
|
@@ -161,8 +161,8 @@ describe Furi do
|
|
161
161
|
expect("/posts/").to have_parts(
|
162
162
|
path: '/posts/',
|
163
163
|
directory: '/posts',
|
164
|
-
|
165
|
-
'
|
164
|
+
file: nil,
|
165
|
+
'file!' => '',
|
166
166
|
extension: nil,
|
167
167
|
home_page?: false,
|
168
168
|
)
|
@@ -396,14 +396,14 @@ describe Furi do
|
|
396
396
|
expect(Furi.replace("/articles/index?a=b", directory: '/posts')).to eq('/posts/index?a=b')
|
397
397
|
expect(Furi.replace("/articles/index.html?a=b", directory: '/posts/')).to eq('/posts/index.html?a=b')
|
398
398
|
end
|
399
|
-
it "replace
|
400
|
-
expect(Furi.replace("gusiev.com",
|
401
|
-
expect(Furi.replace("gusiev.com/",
|
402
|
-
expect(Furi.replace("gusiev.com/article1#header",
|
403
|
-
expect(Furi.replace("gusiev.com/article#header",
|
404
|
-
expect(Furi.replace("gusiev.com/articles/article1?a=b",
|
405
|
-
expect(Furi.replace("/articles/article1?a=b",
|
406
|
-
expect(Furi.replace("/articles/article1.xml?a=b",
|
399
|
+
it "replace file" do
|
400
|
+
expect(Furi.replace("gusiev.com", file: 'article')).to eq('gusiev.com/article')
|
401
|
+
expect(Furi.replace("gusiev.com/", file: 'article')).to eq('gusiev.com/article')
|
402
|
+
expect(Furi.replace("gusiev.com/article1#header", file: '/article2')).to eq('gusiev.com/article2#header')
|
403
|
+
expect(Furi.replace("gusiev.com/article#header", file: nil)).to eq('gusiev.com/#header')
|
404
|
+
expect(Furi.replace("gusiev.com/articles/article1?a=b", file: 'article2')).to eq('gusiev.com/articles/article2?a=b')
|
405
|
+
expect(Furi.replace("/articles/article1?a=b", file: '/article2')).to eq('/articles/article2?a=b')
|
406
|
+
expect(Furi.replace("/articles/article1.xml?a=b", file: 'article2.html')).to eq('/articles/article2.html?a=b')
|
407
407
|
end
|
408
408
|
it "replace extension" do
|
409
409
|
expect(->{
|
@@ -554,6 +554,21 @@ describe Furi do
|
|
554
554
|
expect(Furi.defaults("//gusiev.com", query_string: 'b=2')).to eq('//gusiev.com?b=2')
|
555
555
|
expect(Furi.defaults("//gusiev.com?a=1&b=2", query: '?a=3')).to eq('//gusiev.com?a=1&b=2')
|
556
556
|
end
|
557
|
+
it "should set file" do
|
558
|
+
expect(Furi.defaults("gusiev.com?a=1", file: 'index.html')).to eq('gusiev.com/index.html?a=1')
|
559
|
+
expect(Furi.defaults("gusiev.com/posts?a=1", file: 'index.html')).to eq('gusiev.com/posts?a=1')
|
560
|
+
expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
561
|
+
expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
562
|
+
end
|
563
|
+
it "should set extension" do
|
564
|
+
expect {
|
565
|
+
Furi.defaults("gusiev.com?a=1", extension: 'html')
|
566
|
+
}.to raise_error(Furi::FormattingError)
|
567
|
+
expect(Furi.defaults("gusiev.com?a=1", file: 'index.html', extension: 'html')).to eq('gusiev.com/index.html?a=1')
|
568
|
+
expect(Furi.defaults("gusiev.com/posts?a=1", extension: 'html')).to eq('gusiev.com/posts.html?a=1')
|
569
|
+
#expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
570
|
+
#expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
571
|
+
end
|
557
572
|
end
|
558
573
|
|
559
574
|
describe "#==" do
|
@@ -623,10 +638,10 @@ describe Furi do
|
|
623
638
|
expect(a: [1,{c: 2, b: 3}, 4]).to serialize_as(["a[]=1", "a[][c]=2", "a[][b]=3", "a[]=4"])
|
624
639
|
expect(->{
|
625
640
|
Furi.serialize([1,2])
|
626
|
-
}).to raise_error(
|
641
|
+
}).to raise_error(Furi::FormattingError)
|
627
642
|
expect(->{
|
628
643
|
Furi.serialize(a: [1,[2]])
|
629
|
-
}).to raise_error(
|
644
|
+
}).to raise_error(Furi::FormattingError)
|
630
645
|
|
631
646
|
|
632
647
|
params = { b:{ c:3, d:[4,5], e:{ x:[6], y:7, z:[8,9] }}};
|
@@ -722,13 +737,13 @@ describe Furi do
|
|
722
737
|
should eq "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}
|
723
738
|
|
724
739
|
lambda { Furi.parse_query("x[y]=1&x[y]z=2") }.
|
725
|
-
should raise_error(
|
740
|
+
should raise_error(Furi::QueryParseError, "expected Hash (got String) for param `y'")
|
726
741
|
|
727
742
|
lambda { Furi.parse_query("x[y]=1&x[]=1") }.
|
728
|
-
should raise_error(
|
743
|
+
should raise_error(Furi::QueryParseError, /expected Array \(got [^)]*\) for param `x'/)
|
729
744
|
|
730
745
|
lambda { Furi.parse_query("x[y]=1&x[y][][w]=2") }.
|
731
|
-
should raise_error(
|
746
|
+
should raise_error(Furi::QueryParseError, "expected Array (got String) for param `y'")
|
732
747
|
end
|
733
748
|
|
734
749
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bogdan Gusiev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|