-
Notifications
You must be signed in to change notification settings - Fork 10
/
uri.rb
116 lines (102 loc) · 2.85 KB
/
uri.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
require 'uri'
module Springboard
class Client
##
# A wrapper around URI
class URI
##
# Returns a URI object based on the parsed string.
#
# @return [URI]
def self.parse(value)
return value.dup if value.is_a?(self)
new(::URI.parse(value.to_s))
end
##
# Creates a new URI object from an Addressable::URI
#
# @return [URI]
def initialize(uri)
@uri = uri
end
##
# Clones the URI object
#
# @return [URI]
def dup
self.class.new(@uri.dup)
end
##
# Returns a new URI with the given subpath appended to it. Ensures a single
# forward slash between the URI's path and the given subpath.
#
# @return [URI]
def subpath(subpath)
uri = dup
uri.path = "#{path}/" unless path.end_with?('/')
uri.path = uri.path + ::URI.encode(subpath.to_s.gsub(/^\//, ''))
uri
end
##
# Merges the given hash of query string parameters and values with the URI's
# existing query string parameters (if any).
def merge_query_values!(values)
old_query_values = self.query_values || {}
self.query_values = old_query_values.merge(normalize_query_hash(values))
end
##
# Checks if supplied URI matches current URI
#
# @return [boolean]
def ==(other_uri)
return false unless other_uri.is_a?(self.class)
uri == other_uri.__send__(:uri)
end
##
# Overwrites the query using the supplied query values
def query_values=(values)
self.query = ::URI.encode_www_form(normalize_query_hash(values).sort)
end
##
# Returns a hash of query string parameters and values
#
# @return [hash]
def query_values
return nil if query.nil?
::URI.decode_www_form(query).each_with_object({}) do |(k, v), hash|
if k.end_with?('[]')
hash[k] = Array(hash[k]) + [v]
else
hash[k] = v
end
end
end
private
attr_reader :uri
def self.delegate_and_wrap(*methods)
methods.each do |method|
define_method(method) do |*args, &block|
@uri.__send__(method, *args, &block)
end
end
end
delegate_and_wrap(
:path, :path=, :to_s, :query, :query=
)
def normalize_query_hash(hash)
hash.inject({}) do |copy, (k, v)|
k = "#{k}[]" if v.is_a?(Array) && !k.to_s.end_with?('[]')
copy[k.to_s] = normalized_query_hash_values(v)
copy
end
end
def normalized_query_hash_values(value)
case value
when Hash then normalize_query_hash(value)
when true, false then value.to_s
when Array then value.uniq
else value end
end
end
end
end