Module: Furi
- Defined in:
- lib/furi.rb,
lib/furi/uri.rb,
lib/furi/utils.rb,
lib/furi/version.rb,
lib/furi/query_token.rb
Defined Under Namespace
Classes: Error, FormattingError, ParseError, QueryParseError, QueryToken, Uri, Utils
Constant Summary collapse
- ESSENTIAL_PARTS =
[ :anchor, :protocol, :query_tokens, :path, :host, :port, :username, :password, :filename, ]
- COMBINED_PARTS =
[ :hostinfo, :userinfo, :authority, :ssl, :domain, :domainname, :domainzone, :request, :location, :endpoint, :query, :directory, :extension, :file ]
- PARTS =
ESSENTIAL_PARTS + COMBINED_PARTS
- ALIASES =
{ protocol: [:schema, :scheme], anchor: [:fragment], host: [:hostname], username: [:user], request: [:request_uri] }
- DELEGATES =
[:port!, :host!, :path!, :home_page?]
- PROTOCOLS =
{ "http" => {port: 80, ssl: false}, "https" => {port: 443, ssl: true}, "ftp" => {port: 21}, "tftp" => {port: 69}, "sftp" => {port: 22}, "ssh" => {port: 22, ssl: true}, "svn" => {port: 3690}, "svn+ssh" => {port: 22, ssl: true}, "telnet" => {port: 23}, "nntp" => {port: 119}, "gopher" => {port: 70}, "wais" => {port: 210}, "ldap" => {port: 389}, "prospero" => {port: 1525}, "file" => {port: nil}, "postgres" => {port: 5432}, "mysql" => {port: 3306}, "mailto" => {port: nil} }
- SSL_MAPPING =
{ 'http' => 'https', 'ftp' => 'sftp', 'svn' => 'svn+ssh', }
- WEB_PROTOCOL =
['http', 'https']
- ROOT =
'/'- VERSION =
"0.2.8"
Class Method Summary collapse
-
.build(argument) ⇒ Object
Builds an URL from given parts.
-
.defaults(string, parts) ⇒ Object
Puts the default values for given URL that are not defined.
- .join(*uris) ⇒ Object
-
.parse(argument, parts = nil) ⇒ Object
Parses a given string and return an URL object Optionally accepts parts to update the parsed URL object.
-
.parse_query(query) ⇒ Object
Parses a query into nested paramters hash using a rack convension with square brackets.
- .parse_query_token(params, name, value) ⇒ Object
-
.query_tokens(query) ⇒ Object
Parses query key/value pairs from query string and returns them raw without organising them into hashes and without normalising them.
-
.replace(string, parts) ⇒ Object
Replaces a given URL string with given parts.
-
.serialize(query, namespace = nil) ⇒ Object
Serializes query parameters into query string.
- .serialize_tokens(query, namespace = nil) ⇒ Object
-
.update(string, parts) ⇒ Object
(also: merge)
Replaces a given URL string with given parts.
Class Method Details
.build(argument) ⇒ Object
Builds an URL from given parts
Furi.build(path: "/dashboard", host: 'example.com', protocol: "https")
# => "https://example.com/dashboard"
76 77 78 |
# File 'lib/furi.rb', line 76 def self.build(argument) Uri.new(argument).to_s end |
.defaults(string, parts) ⇒ Object
Puts the default values for given URL that are not defined
Furi.defaults("gusiev.com/hello.html", protocol: 'http', path: '/index.html')
# => "http://gusiev.com/hello.html"
103 104 105 |
# File 'lib/furi.rb', line 103 def self.defaults(string, parts) parse(string).defaults(parts).to_s end |
.join(*uris) ⇒ Object
175 176 177 178 179 180 181 |
# File 'lib/furi.rb', line 175 def self.join(*uris) uris.map do |uri| Furi.parse(uri) end.reduce do |memo, uri| memo.send(:join, uri) end end |
.parse(argument, parts = nil) ⇒ Object
Parses a given string and return an URL object Optionally accepts parts to update the parsed URL object
68 69 70 |
# File 'lib/furi.rb', line 68 def self.parse(argument, parts = nil) Uri.new(argument).update(parts) end |
.parse_query(query) ⇒ Object
Parses a query into nested paramters hash using a rack convension with square brackets.
Furi.parse_query("a[]=1&a[]=2") # => {a: [1,2]}
Furi.parse_query("p[email]=a&a[two]=2") # => {a: {one: 1, two: 2}}
Furi.parse_query("p[one]=1&a[two]=2") # => {a: {one: 1, two: 2}}
Furi.serialize({p: {name: 'Bogdan Gusiev', email: '[email protected]', data: {one: 1, two: 2}}})
# => "p%5Bname%5D=Bogdan&p%5Bemail%5D=bogdan%40example.com&p%5Bdata%5D%5Bone%5D=1&p%5Bdata%5D%5Btwo%5D=2"
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/furi.rb', line 127 def self.parse_query(query) return Furi::Utils.stringify_keys(query) if query.is_a?(Hash) params = {} query_tokens(query).each do |token| parse_query_token(params, token.name, token.value) end return params end |
.parse_query_token(params, name, value) ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/furi.rb', line 231 def self.parse_query_token(params, name, value) name =~ %r(\A[\[\]]*([^\[\]]+)\]*) namespace = $1 || '' after = $' || '' return if namespace.empty? current = params[namespace] if after == "" current = value elsif after == "[]" current ||= [] unless current.is_a?(Array) raise QueryParseError, "expected Array (got #{current.class}) for param `#{namespace}'" end current << value elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) child_key = $1 current ||= [] unless current.is_a?(Array) raise QueryParseError, "expected Array (got #{current.class}) for param `#{namespace}'" end if current.last.is_a?(Hash) && !current.last.key?(child_key) parse_query_token(current.last, child_key, value) else current << parse_query_token({}, child_key, value) end else current ||= {} unless current.is_a?(Hash) raise QueryParseError, "expected Hash (got #{current.class}) for param `#{namespace}'" end current = parse_query_token(current, after, value) end params[namespace] = current return params end |
.query_tokens(query) ⇒ Object
Parses query key/value pairs from query string and returns them raw without organising them into hashes and without normalising them.
Furi.query_tokens("a=1&b=2").map {|k,v| "#{k} -> #{v}"} # => ['a -> 1', 'b -> 2']
Furi.query_tokens("a=1&a=1&a=2").map {|k,v| "#{k} -> #{v}"} # => ['a -> 1', 'a -> 1', 'a -> 2']
Furi.query_tokens("name=Bogdan&email=bogdan%40example.com") # => [name=Bogdan, [email protected]]
Furi.query_tokens("a[one]=1&a[two]=2") # => [a[one]=1, a[two]=2]
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/furi.rb', line 145 def self.query_tokens(query) case query when Enumerable, Enumerator query.map do |token| QueryToken.parse(token) end when nil, '' [] when String query.gsub(/\A\?/, '').split(/[&;] */n, -1).map do |p| QueryToken.parse(p) end else raise QueryParseError, "can not parse #{query.inspect} query tokens" end end |
.replace(string, parts) ⇒ Object
114 115 116 |
# File 'lib/furi.rb', line 114 def self.replace(string, parts) parse(string).replace(parts).to_s end |
.serialize(query, namespace = nil) ⇒ Object
Serializes query parameters into query string. Optionaly accepts a basic name space.
Furi.serialize({a: 1, b: 2}) # => "a=1&b=2"
Furi.serialize({a: [1,2]}) # => "a[]=1&a[]=2"
Furi.serialize({a: {b: 1, c:2}}) # => "a[b]=1&a[c]=2"
Furi.serialize({name: 'Bogdan', email: '[email protected]'}, "person")
# => "person[name]=Bogdan&person[email]=bogdan%40example.com"
171 172 173 |
# File 'lib/furi.rb', line 171 def self.serialize(query, namespace = nil) serialize_tokens(query, namespace).join("&") end |
.serialize_tokens(query, namespace = nil) ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/furi.rb', line 197 def self.serialize_tokens(query, namespace = nil) case query when Hash result = query.map do |key, value| unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty? serialize_tokens(value, namespace ? "#{namespace}[#{key}]" : key) else nil end end result.flatten! result.compact! result when Array if namespace.nil? || namespace.empty? raise FormattingError, "Can not serialize Array without namespace" end namespace = "#{namespace}[]" query.map do |item| if item.is_a?(Array) raise FormattingError, "Can not serialize #{item.inspect} as element of an Array" end serialize_tokens(item, namespace) end else if namespace QueryToken.new(namespace, query) else [] end end end |
.update(string, parts) ⇒ Object Also known as: merge
Replaces a given URL string with given parts
Furi.update("http://gusiev.com", protocol: 'https', subdomain: 'www')
# => "https://www.gusiev.com"
92 93 94 |
# File 'lib/furi.rb', line 92 def self.update(string, parts) parse(string).update(parts).to_s end |