URI utilities collection.

Design

Implement as a module to avoid class polution. You can still use Ruby’s advanced features to include the module in your class. Passing the object to act upon allows to check for nil, which isn’t possible if you use self.

The uris passed as parameters are typically strings.

Methods
Public Class methods
chomp_query_string(uri)

Removes the query string from a uri

Input: the uri

Output: the chomped uri.

     # File lib/glue/uri.rb, line 135
135:   def self.chomp_query_string(uri)
136:     return nil unless uri
137:     query_string = self.get_query_string(uri)
138:     return uri.dup.chomp("?#{query_string}")
139:   end
decode(uri)

Decode the uri components.

    # File lib/glue/uri.rb, line 26
26:   def self.decode(uri)    
27:     # gmosx: hmm is this needed?
28:     # guard against invalid filenames for example pictures with 
29:     # spaces uploaded by users
30:     escaped_uri = uri.gsub(/ /, "+")
31: 
32:     if md = URI::REGEXP::REL_URI.match(escaped_uri)
33: 
34:       path = "#{md[5]}#{md[6]}"
35:       type = File.extname(path)
36:       query_string = md[7]
37: 
38: #      real_path = "#{$root_dir}/#{path}"
39: 
40:       parameters = Glue::UriUtils.query_string_to_hash(query_string)
41:       path.gsub!(/\+/, " ")
42: 
43:       return [path, type, parameters, query_string]
44: 
45:     end # match
46: 
47:     # this is usefull for uncovering bugs!
48:     raise ArgumentError.new("the parameter '#{uri}' is not a valid uri")
49:   end
get_query_string(uri)

This method returns the query string of a uri

Input: the uri

Output: the query string. returns nil if no query string

     # File lib/glue/uri.rb, line 115
115:   def self.get_query_string(uri)
116:     return nil unless uri
117:     # gmosx: INVESTIGATE ruby's URI seems to differently handle
118:     # abs and rel uris.
119:     if md = URI::REGEXP::ABS_URI.match(uri)
120:       return md[8]
121:     elsif md = URI::REGEXP::REL_URI.match(uri)
122:       return md[7]
123:     end
124:     return nil
125:   end
hash_to_query_string(parameters)

Given a hash with parameter/value pairs construct a standard query string. This method only encodes simple types (Numeric, String) to avoid query string polution with marshal, etc.

gmosx, FIXME: only numeric and strings are passed to the latest code, so update old code and optimize this!

Input: the parameter hash

Output: the query string

     # File lib/glue/uri.rb, line 93
 93:   def self.hash_to_query_string(parameters)
 94:     return nil unless parameters
 95:     pairs = []
 96:     parameters.each { |param, value|
 97:       # only encode simple classes !
 98: 
 99:       if value.is_a?(Numeric) or value.is_a?(String)
100:         pairs << "#{param}=#{CGI.escape(value.to_s)}"
101:       end
102:     }
103:     return pairs.join(";")
104:   end
query_string_to_hash(query_string)

Extend the basic query string parser provided by the cgi module. converts single valued params (the most common case) to objects instead of arrays

Input: the query string

Output: hash of parameters, contains arrays for multivalued parameters (multiselect, checkboxes , etc) If no query string is provided (nil or "") returns an empty hash.

    # File lib/glue/uri.rb, line 63
63:   def self.query_string_to_hash(query_string)
64:     return {} unless query_string
65: 
66:     query_parameters = CGI::parse(query_string)
67: 
68:     query_parameters.each { |key, val|
69:       # replace the array with an object
70:       query_parameters[key] = val[0] if 1 == val.length
71:     }
72: 
73:     # set default value to nil! cgi sets this to []
74:     query_parameters.default = nil
75: 
76:     return query_parameters
77:   end
update_query_string(uri, parameters)

Get a uri and a hash of parameters. Inject the hash values as parameters in the query sting path. Returns the full uri.

Input: the uri to filter (String) hash of parameters to update

Output: the full updated query string

TODO:

optimize this a litle bit.

     # File lib/glue/uri.rb, line 155
155:   def self.update_query_string(uri, parameters)
156:     query_string = self.get_query_string(uri)
157:     rest = uri.dup.gsub(/\?#{query_string}/, "")
158: 
159:     hash = self.query_string_to_hash(query_string)
160:     hash.update(parameters)
161:     query_string = self.hash_to_query_string(hash)
162: 
163:     unless query_string.blank?
164:       return "#{rest}?#{query_string}"
165:     else
166:       return rest
167:     end
168:   end
update_request_uri(request, parameters)

TODO: find a better name. 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.

     # File lib/glue/uri.rb, line 175
175:   def self.update_request_uri(request, parameters)
176:     hash = request.parameters.dup()
177:     hash.update(parameters)
178: 
179:     # use this in hash_to_querystring.    
180:     query_string = hash.collect { |k, v|
181:       "#{k}=#{v}"
182:     }.join(";")
183:     
184:     return "#{request.translated_uri}?#{query_string}"
185:   end