Module: RestCore::Client

Includes:
RestCore
Defined in:
lib/rest-core/client.rb

Constant Summary

Unserializable =
[Proc, Method, IO]

Constants included from RestCore

ASYNC, DRY, FAIL, FUTURE, LOG, REQUEST_HEADERS, REQUEST_METHOD, REQUEST_PATH, REQUEST_PAYLOAD, REQUEST_QUERY, RESPONSE_BODY, RESPONSE_HEADERS, RESPONSE_STATUS, RootFiber, TIMER, Universal, VERSION

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from RestCore

eagerload

Instance Attribute Details

- (Object) app (readonly)

Returns the value of attribute app



53
54
55
# File 'lib/rest-core/client.rb', line 53

def app
  @app
end

- (Object) dry (readonly)

Returns the value of attribute dry



53
54
55
# File 'lib/rest-core/client.rb', line 53

def dry
  @dry
end

- (Object) futures (readonly)

Returns the value of attribute futures



53
54
55
# File 'lib/rest-core/client.rb', line 53

def futures
  @futures
end

Class Method Details

+ (Object) included(mod)



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
# File 'lib/rest-core/client.rb', line 11

def self.included mod
  # honor default attributes
  src = mod.members.map{ |name|
    <<-RUBY
      def #{name}
        if (r = super).nil?
          self.#{name} = default_#{name}
        else
          r
        end
      end

      def default_#{name} app=app
        if self.class.respond_to?("default_#{name}")
          self.class.default_#{name}      # old class default style
        elsif app.respond_to?(:#{name})
          app.#{name}({})                 # middleware instance value
        elsif app.respond_to?(:wrapped)
          default_#{name}(app.wrapped) || # wrapper value
          default_#{name}(app.app)        # walk into it
        elsif app.respond_to?(:app)
          default_#{name}(app.app)        # walk into next app
        else
          nil
        end
      end
      private :default_#{name}
    RUBY
  }
  # if RUBY_VERSION < '1.9.2'
  src << <<-RUBY if mod.members.first.kind_of?(String)
    def members
      super.map(&:to_sym)
    end
  RUBY
  # end
  accessor = Module.new
  accessor.module_eval(src.join("\n"), __FILE__, __LINE__)
  mod.const_set('Accessor', accessor)
  mod.send(:include, accessor)
end

Instance Method Details

- (Object) attributes



62
63
64
# File 'lib/rest-core/client.rb', line 62

def attributes
  Hash[each_pair.map{ |k, v| [k, send(k)] }]
end

- (Object) build_env(env = {})



198
199
200
201
# File 'lib/rest-core/client.rb', line 198

def build_env env={}
  default_env.merge(
    Middleware.string_keys(attributes).merge(Middleware.string_keys(env)))
end

- (Object) default_env



203
204
205
206
207
208
209
210
211
# File 'lib/rest-core/client.rb', line 203

def default_env
  {REQUEST_METHOD  => :get,
   REQUEST_PATH    => '/' ,
   REQUEST_QUERY   => {}  ,
   REQUEST_PAYLOAD => {}  ,
   REQUEST_HEADERS => {}  ,
   FAIL            => []  ,
   LOG             => []  }
end

- (Object) delete(path, query = {}, opts = {}, &cb)



124
125
126
127
128
129
# File 'lib/rest-core/client.rb', line 124

def delete path, query={}, opts={}, &cb
  request(
    {REQUEST_METHOD  => :delete,
     REQUEST_PATH    => path   ,
     REQUEST_QUERY   => query  }.merge(opts), &cb)
end

- (Object) get(path, query = {}, opts = {}, &cb)



117
118
119
120
121
122
# File 'lib/rest-core/client.rb', line 117

def get    path, query={}, opts={}, &cb
  request(
    {REQUEST_METHOD  => :get   ,
     REQUEST_PATH    => path   ,
     REQUEST_QUERY   => query  }.merge(opts), &cb)
end

- (Object) head(path, query = {}, opts = {}, &cb)



131
132
133
134
135
136
# File 'lib/rest-core/client.rb', line 131

def head path, query={}, opts={}, &cb
  request(
    {REQUEST_METHOD  => :head  ,
     REQUEST_PATH    => path   ,
     REQUEST_QUERY   => query  }.merge(opts), RESPONSE_HEADERS, &cb)
end

- (Object) initialize(o = {})



54
55
56
57
58
59
60
# File 'lib/rest-core/client.rb', line 54

def initialize o={}
  @app ||= self.class.builder.to_app # lighten! would reinitialize anyway
  @dry ||= self.class.builder.to_app(Dry)
  @futures = []  # don't record any futures in lighten!
  @mutex   = nil # for locking futures, lazily initialized for serialization
  o.each{ |key, value| send("#{key}=", value) if respond_to?("#{key}=") }
end

- (Object) inspect



66
67
68
69
70
71
72
73
74
75
# File 'lib/rest-core/client.rb', line 66

def inspect
  fields = if size > 0
             ' ' + attributes.map{ |k, v|
               "#{k}=#{v.inspect.sub(/(?<=.{12}).{4,}/, '...')}"
             }.join(', ')
           else
             ''
           end
  "#<struct #{self.class.name}#{fields}>"
end

- (Object) lighten(o = {})



90
91
92
# File 'lib/rest-core/client.rb', line 90

def lighten o={}
  dup.lighten!(o)
end

- (Object) lighten!(o = {})



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rest-core/client.rb', line 77

def lighten! o={}
  attributes.each{ |k, v| vv = case v;
                                 when  Hash; lighten_hash(v)
                                 when Array; lighten_array(v)
                                 when *Unserializable; nil
                                 else v
                               end
                          send("#{k}=", vv)}
  initialize(o)
  @app, @dry = lighten_app(app), lighten_app(dry)
  self
end

- (Object) options(path, query = {}, opts = {}, &cb)



138
139
140
141
142
143
# File 'lib/rest-core/client.rb', line 138

def options path, query={}, opts={}, &cb
  request(
    {REQUEST_METHOD  => :options,
     REQUEST_PATH    => path   ,
     REQUEST_QUERY   => query  }.merge(opts), &cb)
end

- (Object) patch(path, payload = {}, query = {}, opts = {}, &cb)



161
162
163
164
165
166
167
# File 'lib/rest-core/client.rb', line 161

def patch  path, payload={}, query={}, opts={}, &cb
  request(
    {REQUEST_METHOD  => :patch ,
     REQUEST_PATH    => path   ,
     REQUEST_QUERY   => query  ,
     REQUEST_PAYLOAD => payload}.merge(opts), &cb)
end

- (Object) post(path, payload = {}, query = {}, opts = {}, &cb)



145
146
147
148
149
150
151
# File 'lib/rest-core/client.rb', line 145

def post   path, payload={}, query={}, opts={}, &cb
  request(
    {REQUEST_METHOD  => :post  ,
     REQUEST_PATH    => path   ,
     REQUEST_QUERY   => query  ,
     REQUEST_PAYLOAD => payload}.merge(opts), &cb)
end

- (Object) put(path, payload = {}, query = {}, opts = {}, &cb)



153
154
155
156
157
158
159
# File 'lib/rest-core/client.rb', line 153

def put    path, payload={}, query={}, opts={}, &cb
  request(
    {REQUEST_METHOD  => :put   ,
     REQUEST_PATH    => path   ,
     REQUEST_QUERY   => query  ,
     REQUEST_PAYLOAD => payload}.merge(opts), &cb)
end

- (Object) request(env, key = RESPONSE_BODY, app = app)



169
170
171
172
173
174
175
176
177
# File 'lib/rest-core/client.rb', line 169

def request env, key=RESPONSE_BODY, app=app
  if block_given?
    request_full(env, app){ |response|
      yield(response[key])
    }
  else
    request_full(env, app)[key]
  end
end

- (Object) request_full(env, app = app, &k)



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/rest-core/client.rb', line 179

def request_full env, app=app, &k
  response = app.call(build_env({ASYNC => !!k}.merge(env)),
                      &(k || Middleware.id))

  # under ASYNC callback, response might not be a response hash
  # in that case (maybe in a user created engine), Client#wait
  # won't work because we have no way to track the future.
  if response.kind_of?(Hash) && RestCore.const_defined?(:Future) &&
     response[FUTURE].kind_of?(Future)
    mutex.synchronize{ futures << WeakRef.new(response[FUTURE]) }
  end

  if block_given?
    self
  else
    response
  end
end

- (Object) url(path, query = {}, opts = {})



110
111
112
113
114
115
# File 'lib/rest-core/client.rb', line 110

def url path, query={}, opts={}
  dry.call(build_env({
    REQUEST_PATH  => path,
    REQUEST_QUERY => query,
    DRY           => true}.merge(opts)), &Middleware.method(:request_uri))
end

- (Object) wait



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/rest-core/client.rb', line 94

def wait
  return self if futures.empty?
  current_futures = nil
  mutex.synchronize{
    current_futures = futures.dup
    futures.clear
  }
  current_futures.each{ |f|
    begin
      f.wait
    rescue WeakRef::RefError # it's gc'ed after we think it's alive
    end if f.weakref_alive?
  }
  wait
end