lib/httpx/transcoder.rb in httpx-0.16.1 vs lib/httpx/transcoder.rb in httpx-0.17.0

- old
+ new

@@ -2,11 +2,15 @@ module HTTPX module Transcoder extend Registry - def self.normalize_keys(key, value, cond = nil, &block) + using RegexpExtensions unless Regexp.method_defined?(:match?) + + module_function + + def normalize_keys(key, value, cond = nil, &block) if (cond && cond.call(value)) block.call(key.to_s, value) elsif value.respond_to?(:to_ary) if value.empty? block.call("#{key}[]") @@ -20,9 +24,66 @@ normalize_keys("#{key}[#{child_key}]", child_value, cond, &block) end else block.call(key.to_s, value) end + end + + # based on https://github.com/rack/rack/blob/d15dd728440710cfc35ed155d66a98dc2c07ae42/lib/rack/query_parser.rb#L82 + def normalize_query(params, name, v, depth) + raise Error, "params depth surpasses what's supported" if depth <= 0 + + name =~ /\A[\[\]]*([^\[\]]+)\]*/ + k = Regexp.last_match(1) || "" + after = Regexp.last_match ? Regexp.last_match.post_match : "" + + if k.empty? + return Array(v) if !v.empty? && name == "[]" + + return + end + + case after + when "" + params[k] = v + when "[" + params[name] = v + when "[]" + params[k] ||= [] + raise Error, "expected Array (got #{params[k].class}) for param '#{k}'" unless params[k].is_a?(Array) + + params[k] << v + when /^\[\]\[([^\[\]]+)\]$/, /^\[\](.+)$/ + child_key = Regexp.last_match(1) + params[k] ||= [] + raise Error, "expected Array (got #{params[k].class}) for param '#{k}'" unless params[k].is_a?(Array) + + if params[k].last.is_a?(Hash) && !params_hash_has_key?(params[k].last, child_key) + normalize_query(params[k].last, child_key, v, depth - 1) + else + params[k] << normalize_query({}, child_key, v, depth - 1) + end + else + params[k] ||= {} + raise Error, "expected Hash (got #{params[k].class}) for param '#{k}'" unless params[k].is_a?(Hash) + + params[k] = normalize_query(params[k], after, v, depth - 1) + end + + params + end + + def params_hash_has_key?(hash, key) + return false if /\[\]/.match?(key) + + key.split(/[\[\]]+/).inject(hash) do |h, part| + next h if part == "" + return false unless h.is_a?(Hash) && h.key?(part) + + h[part] + end + + true end end end require "httpx/transcoder/body"