File: transcoder.rb

package info (click to toggle)
ruby-httpx 1.7.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,816 kB
  • sloc: ruby: 12,209; makefile: 4
file content (89 lines) | stat: -rw-r--r-- 2,618 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# frozen_string_literal: true

module HTTPX
  module Transcoder
    module_function

    def normalize_keys(key, value, transcoder = self, &block)
      if value.respond_to?(:to_ary)
        if value.empty?
          block.call("#{key}[]")
        else
          value.to_ary.each do |element|
            transcoder.normalize_keys("#{key}[]", element, transcoder, &block)
          end
        end
      elsif value.respond_to?(:to_hash)
        value.to_hash.each do |child_key, child_value|
          transcoder.normalize_keys("#{key}[#{child_key}]", child_value, transcoder, &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 key.include?("[]")

      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"
require "httpx/transcoder/form"
require "httpx/transcoder/json"
require "httpx/transcoder/chunker"
require "httpx/transcoder/deflate"
require "httpx/transcoder/gzip"