Module: HTTPUtil
- Defined in:
- lib/stella/utils/httputil.rb
Constant Summary collapse
- VALID_METHODS =
%w{GET HEAD POST PUT DELETE}
- @@timeout =
20
Class Method Summary collapse
-
.escape(s) ⇒ Object
Performs URI escaping so that you can construct proper query strings faster.
- .hash_to_query(parameters) ⇒ Object
-
.parse_form_data(io, boundary) ⇒ Object
Based on WEBrick::HTTPutils::parse_form_data.
-
.parse_header(raw) ⇒ Object
Takes a string.
-
.parse_header_body(data = []) ⇒ Object
Process everything after the first line of an HTTP request or response: GET / HTTP/1.1 HTTP/1.1 200 OK etc…
-
.parse_http_request(data, host = :unknown, port = 80) ⇒ Object
Takes a string or array.
-
.parse_http_response(data = []) ⇒ Object
Takes a string or array.
- .parse_query(request_method, query_string, content_type = '', body = '') ⇒ Object
-
.parse_query_from_string(qs, d = '&;') ⇒ Object
Parses a query string by breaking it up at the ‘&’ and ‘;’ characters.
-
.query_to_hash(query_string) ⇒ Object
Extend the basic query string parser provided by the cgi module.
-
.unescape(s) ⇒ Object
Unescapes a URI escaped string.
- .validate_method(meth = 'GET') ⇒ Object
Class Method Details
.escape(s) ⇒ Object
Performs URI escaping so that you can construct proper query strings faster. Use this rather than the cgi.rb version since it’s faster. (Stolen from Mongrel/Camping).
250 251 252 253 254 |
# File 'lib/stella/utils/httputil.rb', line 250 def HTTPUtil.escape(s) s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { '%'+$1.unpack('H2'*$1.size).join('%').upcase }.tr(' ', '+') end |
.hash_to_query(parameters) ⇒ Object
235 236 237 238 239 240 241 242 243 |
# File 'lib/stella/utils/httputil.rb', line 235 def HTTPUtil.hash_to_query(parameters) return '' unless parameters pairs = [] parameters.each do |param, value| pairs << "#{param}=#{URI.escape(value.to_s)}" end return pairs.join('&') #return pairs.join(";") end |
.parse_form_data(io, boundary) ⇒ Object
Based on WEBrick::HTTPutils::parse_form_data
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/stella/utils/httputil.rb', line 180 def HTTPUtil.parse_form_data(io, boundary) boundary_regexp = /\A--#{boundary}(--)?#{$/}\z/ form_data = Hash.new return form_data unless io data = nil io.each_line{|line| if boundary_regexp =~ line if data data.chop! key = data.name.tr('-', '_').to_sym if form_data.has_key?(key) form_data[key].append_data(data) else form_data[key] = data end end data = FormData.new next else if data data << line end end } return form_data end |
.parse_header(raw) ⇒ Object
Takes a string. See WEBrick::parse_header(string).
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/stella/utils/httputil.rb', line 11 def HTTPUtil.parse_header(raw) header = Hash.new([].freeze) raw.each_line do |line| case line when /\A(.+?):\s+(.+)\z/om name, value = $1, $2 name = name.tr('-', '_').to_sym value.strip! header[name] = [] unless header.has_key?(name) header[name] << value end end header end |
.parse_header_body(data = []) ⇒ Object
Process everything after the first line of an HTTP request or response: GET / HTTP/1.1 HTTP/1.1 200 OK etc… Used by parse_http_request and parse_http_response but can be used separately. Takes a string or array of strings. A string should be formatted like an HTTP request or response. If a body is present it should be separated by two newlines. An array of string should contain an empty or nil element between the header and body content. This will happen naturally if the raw lines were split by a single line terminator. (i.e. /n/ rather than /nn/) Returns header (hash), body (string)
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/stella/utils/httputil.rb', line 109 def HTTPUtil.parse_header_body(data=[]) header, body = {}, nil data = data.split(/\r?\n/) unless data.kind_of? Array data.shift while (data[0].nil? || data[0].empty?) # Remove leading empties return header, body unless data && !data.empty? #puts data.to_yaml # Skip that first line if it exists data.shift if data[0].match(/\AHTTP|GET|POST|DELETE|PUT|HEAD/mo) header_lines = [] header_lines << data.shift while (!data[0].nil? && !data[0].empty?) header = HTTPUtil::parse_header(header_lines.join($/)) # We omit the blank line that delimits the header from the body body = data[1..-1].join($/) unless data.empty? return header, body end |
.parse_http_request(data, host = :unknown, port = 80) ⇒ Object
Takes a string or array. See parse_header_body for further info. Returns method
, http_version
, uri
, header
, body
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 |
# File 'lib/stella/utils/httputil.rb', line 29 def HTTPUtil.parse_http_request(data, host=:unknown, port=80) return unless data && !data.empty? data = data.split(/\r?\n/) unless data.kind_of? Array data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties request_line = data.shift # i.e. GET /path HTTP/1.1 method, path, http_version = nil # With WEBrick and other proxies, the entire URI is included in HTTP requests. # i.e. GET http://stellaaahhhh.com/streetcar.png HTTP/1.1 # The parser is expecting just the absolute path. if request_line =~ /^(\S+)\s+(http:\/\/.+)\s+(HTTP.+)?/mo uri = URI.parse($2) request_line = "#{$1} #{uri.request_uri} #{$3}" host = uri.host end if request_line =~ /^(\S+)\s+(\S+)(?:\s+HTTP\/(\d+\.\d+))?/mo method = $1 http_version = $3 # Comes before $2 b/c the split resets the numbered vars path, query_string = $2.split('?') # We only process the header and body data when we know we're # starting from the beginning of a request string. We don't # want no partials. header, body = HTTPUtil.parse_header_body(data) query = HTTPUtil.parse_query(method, query_string) # TODO: Parse username/password uri = URI::HTTP.build({ :scheme => 'http', :host => header[:Host][0] || host.to_s, :port => port, :path => path, :query => query_string }) else rl = request_line.sub(/\x0d?\x0a\z/o, '') raise "Bad Request-Line `#{rl}'." end return method, http_version, uri, header, body end |
.parse_http_response(data = []) ⇒ Object
Takes a string or array. See parse_header_body for further info. Returns status
, http_version
, message
, header
, body
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/stella/utils/httputil.rb', line 77 def HTTPUtil.parse_http_response(data=[]) return unless data && !data.empty? data = data.split(/\r?\n/) unless data.kind_of? Array data.shift while (data[0].empty? || data[0].nil?) # Remove leading empties status_line = data.shift # ie. HTTP/1.1 200 OK http_version, status, = nil if status_line =~ /^HTTP\/(\d.+?)(\s+(\d\d\d)\s+(.+))?$/mo http_version = $1 status = $2 = $4 header, body, query = HTTPUtil.parse_header_body(data) else raise "Bad Response-Line `#{status_line}'." end return status, http_version, , header, body end |
.parse_query(request_method, query_string, content_type = '', body = '') ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/stella/utils/httputil.rb', line 131 def HTTPUtil.parse_query(request_method, query_string, content_type='', body='') query = Hash.new([].freeze) if request_method == "GET" || request_method == "HEAD" query = HTTPUtil::parse_query_from_string(query_string) elsif content_type =~ /^application\/x-www-form-urlencoded/ query = HTTPUtil::parse_query_from_string(body) elsif content_type =~ /^multipart\/form-data; boundary=(.+)/ boundary = $1.tr('"', '') query = HTTPUtil::parse_form_data(body, boundary) else query end query end |
.parse_query_from_string(qs, d = '&;') ⇒ Object
Parses a query string by breaking it up at the ‘&’ and ‘;’ characters. You can also use this to parse cookies by changing the characters used in the second parameter (which defaults to ‘&;’. Stolen from Mongrel
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/stella/utils/httputil.rb', line 157 def HTTPUtil.parse_query_from_string(qs, d = '&;') params = {} (qs||'').split(/[#{d}] */n).inject(params) { |h,p| k, v=unescape(p).split('=',2) next unless k k = k.tr('-', '_').to_sym if cur = params[k] if cur.class == Array params[k] << v else params[k] = [cur, v] end else params[k] = v end } return params end |
.query_to_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
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.
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/stella/utils/httputil.rb', line 219 def HTTPUtil.query_to_hash(query_string) return {} unless query_string query_parameters = HTTPUtil.parse_query(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 |
.unescape(s) ⇒ Object
Unescapes a URI escaped string. (Stolen from Mongrel/Camping).
258 259 260 261 262 |
# File 'lib/stella/utils/httputil.rb', line 258 def HTTPUtil.unescape(s) s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){ [$1.delete('%')].pack('H*') } end |
.validate_method(meth = 'GET') ⇒ Object
148 149 150 |
# File 'lib/stella/utils/httputil.rb', line 148 def HTTPUtil.validate_method(meth='GET') (VALID_METHODS.member? meth.upcase) ? meth : VALID_METHODS[0] end |