Module: URI
- Defined in:
- lib/standard/facets/uri.rb,
lib/standard/facets/uri/query.rb,
lib/standard/facets/uri/decode.rb,
lib/standard/facets/uri/cgi_escape.rb,
lib/standard/facets/uri/parameters.rb
Defined Under Namespace
Constant Summary collapse
- KEY_VALUE_SEPARATOR =
";"
Class Method Summary collapse
-
.cgi_escape(string) ⇒ Object
CGI escape.
- .cgi_parse(query) ⇒ Object
- .cgi_unescape(string) ⇒ Object
-
.decode(uri) ⇒ Object
Decode the uri components.
-
.nested_parameters(value, key = nil, hash = {}) ⇒ Object
We cannot send nested hash as a param in HTTP requests.
-
.parameters(hash) ⇒ Object
Allows for taking a hash and turning it into URI/CGI params Since 1.8.x does not have ordered hashes the params might not be ordered.
-
.query(parameters) ⇒ Object
Given a hash with parameter/value pairs construct a standard query string.
-
.query_chomp(uri) ⇒ Object
Removes the query string from a
uri
. -
.query_get(uri) ⇒ String
(also: get_query_string)
This method returns the query string of a uri.
-
.query_hash(query_string) ⇒ Object
Extend the basic query string parser provided by the cgi module.
-
.query_update(uri, parameters) ⇒ Object
Get a uri and a hash of parameters.
-
.update_request_uri(request, parameters) ⇒ Object
Gets the request uri, injects extra parameters in the query string and returns a new uri.
Instance Method Summary collapse
-
#cgi_escape(string) ⇒ Object
private
CGI escape.
- #cgi_parse(query) ⇒ Object private
- #cgi_unescape(string) ⇒ Object private
-
#decode(uri) ⇒ Object
private
Decode the uri components.
- #get_query_string ⇒ Object private
-
#query(parameters) ⇒ Object
private
Given a hash with parameter/value pairs construct a standard query string.
-
#query_chomp(uri) ⇒ Object
private
Removes the query string from a
uri
. -
#query_get(uri) ⇒ String
private
This method returns the query string of a uri.
-
#query_hash(query_string) ⇒ Object
private
Extend the basic query string parser provided by the cgi module.
-
#query_update(uri, parameters) ⇒ Object
private
Get a uri and a hash of parameters.
-
#update_request_uri(request, parameters) ⇒ Object
private
Gets the request uri, injects extra parameters in the query string and returns a new uri.
Class Method Details
.cgi_escape(string) ⇒ Object
CGI escape
12 13 14 15 16 |
# File 'lib/standard/facets/uri/cgi_escape.rb', line 12 def cgi_escape(string) string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do '%' + $1.unpack('H2' * $1.size).join('%').upcase end.tr(' ', '+') end |
.cgi_parse(query) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/standard/facets/uri/cgi_escape.rb', line 30 def cgi_parse(query) params = Hash.new([].freeze) query.split(/[&;]/n).each do |pairs| key, value = pairs.split('=',2).collect{|v| cgi_unescape(v) } if params.has_key?(key) params[key].push(value) else params[key] = [value] end end params end |
.cgi_unescape(string) ⇒ Object
21 22 23 24 25 |
# File 'lib/standard/facets/uri/cgi_escape.rb', line 21 def cgi_unescape(string) string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do [$1.delete('%')].pack('H*') end end |
.decode(uri) ⇒ Object
Decode the uri components.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/standard/facets/uri/decode.rb', line 9 def decode(uri) ## gmosx: hmm is this needed? ## guard against invalid filenames for example pictures with ## spaces uploaded by users escaped_uri = uri.gsub(/ /, "+") if md = URI::REGEXP::REL_URI.match(escaped_uri) path = "#{md[5]}#{md[6]}" type = File.extname(path) query_string = md[7] ## real_path = "#{$root_dir}/#{path}" parameters = URI.query_to_hash(query_string) path.gsub!(/\+/, " ") return [path, type, parameters, query_string] end ## this is usefull for uncovering bugs! raise ArgumentError.new("the parameter '#{uri}' is not a valid uri") end |
.nested_parameters(value, key = nil, hash = {}) ⇒ Object
We cannot send nested hash as a param in HTTP requests. For example, when we would like to send something like this:
{:key => "value", :nested => {:nest => "value"}}
It would be (or should be) mapped like this:
/url/?key=value&nested=%7B%3Anest%3D%3E%5C%22value%5C%22%7D
Doesn’t look to good ;) However there is a simple way to convert a nested hash into a params acceptable form. We can convert it to a form, that can be mapped into params like this:
/url/?key=value&nested[nest]=value
Here is method to convert any nested hash to a “one level” equivalent:
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/standard/facets/uri/parameters.rb', line 42 def self.nested_parameters(value, key=nil, hash={}) case value when Hash value.each do |k,v| akey = key.nil? ? :"#{k}" : :"#{key}[#{k}]" nested_parameters(v, akey, hash) end out_hash when Array value.each do |v| nested_parameters(v, "#{key}[]", hash) end hash when nil then '' else hash[key] = value hash end parameters(hash) end |
.parameters(hash) ⇒ Object
URI.parameters needs URI escaping.
Allows for taking a hash and turning it into URI/CGI params Since 1.8.x does not have ordered hashes the params might not be ordered.
13 14 15 16 17 18 19 20 21 |
# File 'lib/standard/facets/uri/parameters.rb', line 13 def self.parameters(hash) hash.map do |k,v| if v.respond_to?(:join) "#{k}=#{v.join(",")}" else "#{k}=#{v}" end end.join("&") end |
.query(parameters) ⇒ Object
Given a hash with parameter/value pairs construct a standard query string.
URI.hash_to_query(:a => 1, :b => 2)
#=> "a=1;b=2"
23 24 25 26 27 28 29 30 |
# File 'lib/standard/facets/uri/query.rb', line 23 def query(parameters) return '' unless parameters pairs = [] parameters.each do |param, value| pairs << "#{param}=#{cgi_escape(value.to_s)}" end return pairs.join(KEY_VALUE_SEPARATOR) end |
.query_chomp(uri) ⇒ Object
Removes the query string from a uri
.
Returns the chomped uri.
92 93 94 95 96 |
# File 'lib/standard/facets/uri/query.rb', line 92 def query_chomp(uri) return nil unless uri query_string = self.get_query_string(uri) return uri.dup.chomp("?#{query_string}") end |
.query_get(uri) ⇒ String Also known as: get_query_string
This method returns the query string of a uri.
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/standard/facets/uri/query.rb', line 73 def query_get(uri) return nil unless uri # gmosx: INVESTIGATE ruby's URI seems to differently handle # abs and rel uris. if md = URI::REGEXP::ABS_URI.match(uri) return md[8] elsif md = URI::REGEXP::REL_URI.match(uri) return md[7] end return nil end |
.query_hash(query_string) ⇒ Object
Extend the basic query string parser provided by the cgi module. converts single valued params (the most common case) to objects instead of arrays
Returns hash of parameters, contains arrays for multivalued parameters (multiselect, checkboxes , etc).
If no query string is provided (nil or “”) returns an empty hash.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/standard/facets/uri/query.rb', line 45 def query_hash(query_string) return {} unless query_string query_parameters = cgi_parse(query_string) query_parameters.each { |key, val| ## replace the array with an object query_parameters[key] = val[0] if 1 == val.length } ## set default value to nil! cgi sets this to [] query_parameters.default = nil return query_parameters end |
.query_update(uri, parameters) ⇒ Object
Optimize this method.
Get a uri and a hash of parameters. Inject the hash values as parameters in the query sting path. Returns the full uri.
uri - the uri to filter (String) parameter - hash of parameters to update
Returns the full updated query string.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/standard/facets/uri/query.rb', line 111 def query_update(uri, parameters) query_string = self.query_get(uri) rest = uri.dup.gsub(/\?#{query_string}/, "") hash = self.query_string_to_hash(query_string) hash.update(parameters) query_string = self.hash_to_query_string(hash) unless query_string.strip.empty? return "#{rest}?#{query_string}" else return rest end end |
.update_request_uri(request, parameters) ⇒ Object
Gets the request uri, injects extra parameters in the query string and returns a new uri. The request object is not modified. There is always a qs string so an extra test is skipped.
TODO: find a better name?
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/standard/facets/uri/query.rb', line 135 def update_request_uri(request, parameters) hash = request.parameters.dup() hash.update(parameters) ## use this in hash_to_query query_string = hash.collect { |k, v| "#{k}=#{v}" }.join(";") ## return "#{request.translated_uri}?#{query_string}" return "#{request.path}?#{query_string}" end |
Instance Method Details
#cgi_escape(string) ⇒ Object (private)
CGI escape
12 13 14 15 16 |
# File 'lib/standard/facets/uri/cgi_escape.rb', line 12 def cgi_escape(string) string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do '%' + $1.unpack('H2' * $1.size).join('%').upcase end.tr(' ', '+') end |
#cgi_parse(query) ⇒ Object (private)
30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/standard/facets/uri/cgi_escape.rb', line 30 def cgi_parse(query) params = Hash.new([].freeze) query.split(/[&;]/n).each do |pairs| key, value = pairs.split('=',2).collect{|v| cgi_unescape(v) } if params.has_key?(key) params[key].push(value) else params[key] = [value] end end params end |
#cgi_unescape(string) ⇒ Object (private)
21 22 23 24 25 |
# File 'lib/standard/facets/uri/cgi_escape.rb', line 21 def cgi_unescape(string) string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do [$1.delete('%')].pack('H*') end end |
#decode(uri) ⇒ Object (private)
Decode the uri components.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/standard/facets/uri/decode.rb', line 9 def decode(uri) ## gmosx: hmm is this needed? ## guard against invalid filenames for example pictures with ## spaces uploaded by users escaped_uri = uri.gsub(/ /, "+") if md = URI::REGEXP::REL_URI.match(escaped_uri) path = "#{md[5]}#{md[6]}" type = File.extname(path) query_string = md[7] ## real_path = "#{$root_dir}/#{path}" parameters = URI.query_to_hash(query_string) path.gsub!(/\+/, " ") return [path, type, parameters, query_string] end ## this is usefull for uncovering bugs! raise ArgumentError.new("the parameter '#{uri}' is not a valid uri") end |
#get_query_string ⇒ Object (private)
85 |
# File 'lib/standard/facets/uri/query.rb', line 85 alias_method :get_query_string, :query_get |
#query(parameters) ⇒ Object (private)
Given a hash with parameter/value pairs construct a standard query string.
URI.hash_to_query(:a => 1, :b => 2)
#=> "a=1;b=2"
23 24 25 26 27 28 29 30 |
# File 'lib/standard/facets/uri/query.rb', line 23 def query(parameters) return '' unless parameters pairs = [] parameters.each do |param, value| pairs << "#{param}=#{cgi_escape(value.to_s)}" end return pairs.join(KEY_VALUE_SEPARATOR) end |
#query_chomp(uri) ⇒ Object (private)
Removes the query string from a uri
.
Returns the chomped uri.
92 93 94 95 96 |
# File 'lib/standard/facets/uri/query.rb', line 92 def query_chomp(uri) return nil unless uri query_string = self.get_query_string(uri) return uri.dup.chomp("?#{query_string}") end |
#query_get(uri) ⇒ String (private)
This method returns the query string of a uri.
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/standard/facets/uri/query.rb', line 73 def query_get(uri) return nil unless uri # gmosx: INVESTIGATE ruby's URI seems to differently handle # abs and rel uris. if md = URI::REGEXP::ABS_URI.match(uri) return md[8] elsif md = URI::REGEXP::REL_URI.match(uri) return md[7] end return nil end |
#query_hash(query_string) ⇒ Object (private)
Extend the basic query string parser provided by the cgi module. converts single valued params (the most common case) to objects instead of arrays
Returns hash of parameters, contains arrays for multivalued parameters (multiselect, checkboxes , etc).
If no query string is provided (nil or “”) returns an empty hash.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/standard/facets/uri/query.rb', line 45 def query_hash(query_string) return {} unless query_string query_parameters = cgi_parse(query_string) query_parameters.each { |key, val| ## replace the array with an object query_parameters[key] = val[0] if 1 == val.length } ## set default value to nil! cgi sets this to [] query_parameters.default = nil return query_parameters end |
#query_update(uri, parameters) ⇒ Object (private)
Optimize this method.
Get a uri and a hash of parameters. Inject the hash values as parameters in the query sting path. Returns the full uri.
uri - the uri to filter (String) parameter - hash of parameters to update
Returns the full updated query string.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/standard/facets/uri/query.rb', line 111 def query_update(uri, parameters) query_string = self.query_get(uri) rest = uri.dup.gsub(/\?#{query_string}/, "") hash = self.query_string_to_hash(query_string) hash.update(parameters) query_string = self.hash_to_query_string(hash) unless query_string.strip.empty? return "#{rest}?#{query_string}" else return rest end end |
#update_request_uri(request, parameters) ⇒ Object (private)
Gets the request uri, injects extra parameters in the query string and returns a new uri. The request object is not modified. There is always a qs string so an extra test is skipped.
TODO: find a better name?
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/standard/facets/uri/query.rb', line 135 def update_request_uri(request, parameters) hash = request.parameters.dup() hash.update(parameters) ## use this in hash_to_query query_string = hash.collect { |k, v| "#{k}=#{v}" }.join(";") ## return "#{request.translated_uri}?#{query_string}" return "#{request.path}?#{query_string}" end |