Module: RestBuilder::Middleware

Included in:
Dry, Engine
Defined in:
lib/rest-builder/middleware.rb

Constant Summary collapse

METHODS_WITH_PAYLOAD =
[:post, :put, :patch, :delete]
UNRESERVED =
/[^a-zA-Z0-9\-\.\_\~]+/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.contain_binary?(payload) ⇒ Boolean

Returns:

  • (Boolean)


100
101
102
103
104
105
106
107
108
109
# File 'lib/rest-builder/middleware.rb', line 100

def contain_binary? payload
  return false unless payload
  return true  if     payload.respond_to?(:read)
  return true  if     payload.find{ |k, v|
    # if payload is an array, then v would be nil
    (v || k).respond_to?(:read) ||
    # if v is an array, it could contain binary data
    (v.kind_of?(Array) && v.any?{ |vv| vv.respond_to?(:read) }) }
  return false
end

.escape(string) ⇒ Object



88
89
90
91
92
# File 'lib/rest-builder/middleware.rb', line 88

def escape string
  string.gsub(UNRESERVED) do |s|
    "%#{s.unpack('H2' * s.bytesize).join('%')}".upcase
  end
end

.has_payload?(env) ⇒ Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/rest-builder/middleware.rb', line 95

def has_payload? env
  METHODS_WITH_PAYLOAD.include?(env[REQUEST_METHOD])
end

.included(mod) ⇒ Object



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
# File 'lib/rest-builder/middleware.rb', line 6

def self.included mod
  mod.send(:attr_reader, :app)
  mem = if mod.respond_to?(:members) then mod.members else [] end
  src = mem.map{ |member| <<-RUBY }
    attr_writer :#{member}
    def #{member} env
      if    env.key?('#{member}')
        env['#{member}']
      else
            @#{member}
      end
    end
  RUBY
  args      = [:app] + mem
  para_list = args.map{ |a| "#{a}=nil"}.join(', ')
  args_list = args                     .join(', ')
  ivar_list = args.map{ |a| "@#{a}"   }.join(', ')
  src << <<-RUBY
    def initialize #{para_list}
      #{ivar_list} = #{args_list}
    end
  RUBY
  accessor = Module.new
  accessor.module_eval(src.join("\n"), __FILE__, __LINE__)
  mod.const_set(:Accessor, accessor)
  mod.send(:include, accessor)
end

.merge_hash(*hashes) ⇒ Object

this method is intended to merge payloads if they are non-empty hashes, but prefer the right most one if they are not hashes.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/rest-builder/middleware.rb', line 130

def merge_hash *hashes
  hashes.reverse_each.inject do |r, i|
    if r.kind_of?(Hash)
      if i.kind_of?(Hash)
        Middleware.string_keys(i).merge(Middleware.string_keys(r))
      elsif r.empty?
        i # prefer non-empty ones
      else
        r # don't try to merge non-hashes
      end
    else
      r
    end
  end
end

.percent_encode(query) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/rest-builder/middleware.rb', line 76

def percent_encode query
  query.sort.map{ |(k, v)|
    if v.kind_of?(Array)
      v.map{ |vv| "#{escape(k.to_s)}=#{escape(vv.to_s)}" }.join('&')
    else
      "#{escape(k.to_s)}=#{escape(v.to_s)}"
    end
  }.join('&')
end

.request_uri(env) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/rest-builder/middleware.rb', line 65

def request_uri env
  # compacting the hash
  if (query = (env[REQUEST_QUERY] || {}).select{ |k, v| v }).empty?
    env[REQUEST_PATH].to_s
  else
    q = if env[REQUEST_PATH] =~ /\?/ then '&' else '?' end
    "#{env[REQUEST_PATH]}#{q}#{percent_encode(query)}"
  end
end

.string_keys(hash) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rest-builder/middleware.rb', line 112

def string_keys hash
  hash.inject({}){ |r, (k, v)|
    if v.kind_of?(Hash)
      r[k.to_s] = case k.to_s
                    when REQUEST_QUERY, REQUEST_PAYLOAD, REQUEST_HEADERS
                      string_keys(v)
                    else;         v
                  end
    else
      r[k.to_s] = v
    end
    r
  }
end

Instance Method Details

#call(env, &k) ⇒ Object



34
# File 'lib/rest-builder/middleware.rb', line 34

def call env, &k; app.call(env, &(k || :itself.to_proc)); end

#contain_binary?(payload) ⇒ Object



100
101
102
103
104
105
106
107
108
109
# File 'lib/rest-builder/middleware.rb', line 100

def contain_binary? payload
  return false unless payload
  return true  if     payload.respond_to?(:read)
  return true  if     payload.find{ |k, v|
    # if payload is an array, then v would be nil
    (v || k).respond_to?(:read) ||
    # if v is an array, it could contain binary data
    (v.kind_of?(Array) && v.any?{ |vv| vv.respond_to?(:read) }) }
  return false
end

#error_callback(res, err) ⇒ Object



56
57
58
59
# File 'lib/rest-builder/middleware.rb', line 56

def error_callback res, err
  res[CLIENT].error_callback.call(err) if
    res[CLIENT] && res[CLIENT].error_callback
end

#escape(string) ⇒ Object



88
89
90
91
92
# File 'lib/rest-builder/middleware.rb', line 88

def escape string
  string.gsub(UNRESERVED) do |s|
    "%#{s.unpack('H2' * s.bytesize).join('%')}".upcase
  end
end

#fail(env, obj) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/rest-builder/middleware.rb', line 35

def fail env, obj
  if obj
    env.merge(FAIL => (env[FAIL] || []) + [obj])
  else
    env
  end
end

#give_promise(res) ⇒ Object



60
61
62
# File 'lib/rest-builder/middleware.rb', line 60

def give_promise res
  res[CLIENT].give_promise(res) if res[CLIENT]
end

#has_payload?(env) ⇒ Object



95
96
97
# File 'lib/rest-builder/middleware.rb', line 95

def has_payload? env
  METHODS_WITH_PAYLOAD.include?(env[REQUEST_METHOD])
end

#log(env, obj) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/rest-builder/middleware.rb', line 42

def log env, obj
  if obj
    env.merge(LOG  => (env[LOG]  || []) + [obj])
  else
    env
  end
end

#merge_hash(*hashes) ⇒ Object

this method is intended to merge payloads if they are non-empty hashes, but prefer the right most one if they are not hashes.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/rest-builder/middleware.rb', line 130

def merge_hash *hashes
  hashes.reverse_each.inject do |r, i|
    if r.kind_of?(Hash)
      if i.kind_of?(Hash)
        Middleware.string_keys(i).merge(Middleware.string_keys(r))
      elsif r.empty?
        i # prefer non-empty ones
      else
        r # don't try to merge non-hashes
      end
    else
      r
    end
  end
end

#percent_encode(query) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/rest-builder/middleware.rb', line 76

def percent_encode query
  query.sort.map{ |(k, v)|
    if v.kind_of?(Array)
      v.map{ |vv| "#{escape(k.to_s)}=#{escape(vv.to_s)}" }.join('&')
    else
      "#{escape(k.to_s)}=#{escape(v.to_s)}"
    end
  }.join('&')
end

#request_uri(env) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/rest-builder/middleware.rb', line 65

def request_uri env
  # compacting the hash
  if (query = (env[REQUEST_QUERY] || {}).select{ |k, v| v }).empty?
    env[REQUEST_PATH].to_s
  else
    q = if env[REQUEST_PATH] =~ /\?/ then '&' else '?' end
    "#{env[REQUEST_PATH]}#{q}#{percent_encode(query)}"
  end
end

#run(a = app) ⇒ Object



49
50
51
52
53
54
55
# File 'lib/rest-builder/middleware.rb', line 49

def run a=app
  if a.respond_to?(:app) && a.app
    run(a.app)
  else
    a
  end
end

#string_keys(hash) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rest-builder/middleware.rb', line 112

def string_keys hash
  hash.inject({}){ |r, (k, v)|
    if v.kind_of?(Hash)
      r[k.to_s] = case k.to_s
                    when REQUEST_QUERY, REQUEST_PAYLOAD, REQUEST_HEADERS
                      string_keys(v)
                    else;         v
                  end
    else
      r[k.to_s] = v
    end
    r
  }
end