Module: RestClient::Utils
- Defined in:
- lib/restclient/utils.rb
Overview
Various utility methods
Class Method Summary collapse
-
._cgi_parseparam(s) ⇒ Object
deprecated
Deprecated.
This method is deprecated and only exists to support Ruby 2.0, which is not supported by HTTP::Accept.
-
.cgi_parse_header(line) ⇒ Array(String, Hash)
Parse a Content-Type like header.
-
.deprecated_cgi_parse_header(line) ⇒ Array(String, Hash)
deprecated
Deprecated.
This method is deprecated and only exists to support Ruby 2.0, which is not supported by HTTP::Accept.
-
.encode_query_string(object) ⇒ String
Serialize a ruby object into HTTP query string parameters.
-
.escape(string) ⇒ Object
Encode string for safe transport by URI or form encoding.
-
.flatten_params(object, uri_escape = false, parent_key = nil) ⇒ Object
Transform deeply nested param containers into a flat array of [key, value] pairs.
-
.get_encoding_from_headers(headers) ⇒ String?
Return encoding from an HTTP header hash.
Class Method Details
._cgi_parseparam(s) ⇒ Object
This method is deprecated and only exists to support Ruby 2.0, which is not supported by HTTP::Accept.
remove this method when dropping support for Ruby 2.0
Parse semi-colon separated, potentially quoted header string iteratively.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/restclient/utils.rb', line 75 def self._cgi_parseparam(s) return enum_for(__method__, s) unless block_given? while s[0] == ';' s = s[1..-1] ends = s.index(';') while ends && ends > 0 \ && (s[0...ends].count('"') - s[0...ends].scan('\"').count) % 2 != 0 ends = s.index(';', ends + 1) end if ends.nil? ends = s.length end f = s[0...ends] yield f.strip s = s[ends..-1] end nil end |
.cgi_parse_header(line) ⇒ Array(String, Hash)
Parse a Content-Type like header.
Return the main content-type and a hash of params.
56 57 58 59 60 61 62 63 64 |
# File 'lib/restclient/utils.rb', line 56 def self.cgi_parse_header(line) types = HTTP::Accept::MediaTypes.parse(line) if types.empty? raise HTTP::Accept::ParseError.new("Found no types in header line") end [types.first.mime_type, types.first.parameters] end |
.deprecated_cgi_parse_header(line) ⇒ Array(String, Hash)
This method is deprecated and only exists to support Ruby 2.0, which is not supported by HTTP::Accept.
remove this method when dropping support for Ruby 2.0
Parse a Content-Type like header.
Return the main content-type and a hash of options.
This method was ported directly from Python’s cgi.parse_header(). It probably doesn’t read or perform particularly well in ruby. github.com/python/cpython/blob/3.4/Lib/cgi.py#L301-L331
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/restclient/utils.rb', line 112 def self.deprecated_cgi_parse_header(line) parts = _cgi_parseparam(';' + line) key = parts.next pdict = {} begin while (p = parts.next) i = p.index('=') if i name = p[0...i].strip.downcase value = p[i+1..-1].strip if value.length >= 2 && value[0] == '"' && value[-1] == '"' value = value[1...-1] value = value.gsub('\\\\', '\\').gsub('\\"', '"') end pdict[name] = value end end rescue StopIteration end [key, pdict] end |
.encode_query_string(object) ⇒ String
Serialize a ruby object into HTTP query string parameters.
There is no standard for doing this, so we choose our own slightly idiosyncratic format. The output closely matches the format understood by Rails, Rack, and PHP.
If you don’t want handling of complex objects and only want to handle simple flat hashes, you may want to use ‘URI.encode_www_form` instead, which implements HTML5-compliant URL encoded form data.
Notable differences from the ActiveSupport implementation:
-
Empty hash and empty array are treated the same as nil instead of being omitted entirely from the output. Rather than disappearing, they will appear to be nil instead.
It’s most common to pass a Hash as the object to serialize, but you can also use a ParamsArray if you want to be able to pass the same key with multiple values and not use the rack/rails array convention.
206 207 208 |
# File 'lib/restclient/utils.rb', line 206 def self.encode_query_string(object) flatten_params(object, true).map {|k, v| v.nil? ? k : "#{k}=#{v}" }.join('&') end |
.escape(string) ⇒ Object
Encode string for safe transport by URI or form encoding. This uses a CGI style escape, which transforms ‘ ` into `+` and various special characters into percent encoded forms.
This calls URI.encode_www_form_component for the implementation. The only difference between this and CGI.escape is that it does not escape ‘*`. stackoverflow.com/questions/25085992/
270 271 272 |
# File 'lib/restclient/utils.rb', line 270 def self.escape(string) URI.encode_www_form_component(string) end |
.flatten_params(object, uri_escape = false, parent_key = nil) ⇒ Object
Transform deeply nested param containers into a flat array of [key, value] pairs.
225 226 227 228 229 230 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 |
# File 'lib/restclient/utils.rb', line 225 def self.flatten_params(object, uri_escape=false, parent_key=nil) unless object.is_a?(Hash) || object.is_a?(ParamsArray) || (parent_key && object.is_a?(Array)) raise ArgumentError.new('expected Hash or ParamsArray, got: ' + object.inspect) end # transform empty collections into nil, where possible if object.empty? && parent_key return [[parent_key, nil]] end # This is essentially .map(), but we need to do += for nested containers object.reduce([]) { |result, item| if object.is_a?(Array) # item is already the value k = nil v = item else # item is a key, value pair k, v = item k = escape(k.to_s) if uri_escape end processed_key = parent_key ? "#{parent_key}[#{k}]" : k case v when Array, Hash, ParamsArray result.concat flatten_params(v, uri_escape, processed_key) else v = escape(v.to_s) if uri_escape && v result << [processed_key, v] end } end |
.get_encoding_from_headers(headers) ⇒ String?
Return encoding from an HTTP header hash.
We use the RFC 7231 specification and do not impose a default encoding on text. This differs from the older RFC 2616 behavior, which specifies using ISO-8859-1 for text/* content types without a charset.
Strings will use the default encoding when this method returns nil. This default is likely to be UTF-8 for Ruby >= 2.0
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/restclient/utils.rb', line 25 def self.get_encoding_from_headers(headers) type_header = headers[:content_type] return nil unless type_header # TODO: remove this hack once we drop support for Ruby 2.0 if RUBY_VERSION.start_with?('2.0') _content_type, params = deprecated_cgi_parse_header(type_header) if params.include?('charset') return params.fetch('charset').gsub(/(\A["']*)|(["']*\z)/, '') end else begin _content_type, params = cgi_parse_header(type_header) rescue HTTP::Accept::ParseError return nil else params['charset'] end end end |