Class: Npolar::Api::Client::JsonApiClient

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/npolar/api/client/json_api_client.rb

Overview

Ruby client for api.npolar.no, based on Typhoeus and libcurl github.com/typhoeus/typhoeus

Constant Summary collapse

VERSION =
"0.10.pre"
BASE =
"https://api.npolar.no"
HEADER =
{ "User-Agent" => Npolar::Api::Client::USER_AGENT,
    "Content-Type" => "application/json",
    "Accept" => "application/json",
    "Accept-Charset" => "UTF-8",
    "Accept-Encoding" => "gzip,deflate",
    "Connection" => "keep-alive"
}
OPTIONS =

Typhoeus options => RENAME

{ :headers => HEADER,
  :timeout => nil, # 600 seconds or nil for never
  :forbid_reuse => true
}

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base = BASE, options = OPTIONS) ⇒ JsonApiClient

New client

Parameters:

  • base (String | URI) (defaults to: BASE)

    Base URI for all requests

  • options (Hash) (defaults to: OPTIONS)

    (for Typhoeus)



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/npolar/api/client/json_api_client.rb', line 63

def initialize(base=BASE, options=OPTIONS)
  # Prepend https://api.npolar.no if base is relative (like /service)    
  if base =~ /^\//
    path = base
    base = BASE+path
  end
  @base = base
  unless base.is_a? URI
    @uri = URI.parse(base)
  end
  @options = options
  init
end

Class Attribute Details

.keyObject

Returns the value of attribute key.



37
38
39
# File 'lib/npolar/api/client/json_api_client.rb', line 37

def key
  @key
end

Instance Attribute Details

#authorizationObject

Returns the value of attribute authorization.



39
40
41
# File 'lib/npolar/api/client/json_api_client.rb', line 39

def authorization
  @authorization
end

#concurrencyObject

Returns the value of attribute concurrency.



39
40
41
# File 'lib/npolar/api/client/json_api_client.rb', line 39

def concurrency
  @concurrency
end

#headerObject Also known as: headers

Request header Hash



126
127
128
# File 'lib/npolar/api/client/json_api_client.rb', line 126

def header
  @header
end

#logObject

Returns the value of attribute log.



39
40
41
# File 'lib/npolar/api/client/json_api_client.rb', line 39

def log
  @log
end

#modelObject

Returns the value of attribute model.



39
40
41
# File 'lib/npolar/api/client/json_api_client.rb', line 39

def model
  @model
end

#optionsObject (readonly)

Returns the value of attribute options.



40
41
42
# File 'lib/npolar/api/client/json_api_client.rb', line 40

def options
  @options
end

#paramObject

Returns the value of attribute param.



39
40
41
# File 'lib/npolar/api/client/json_api_client.rb', line 39

def param
  @param
end

#responseObject (readonly)

Returns the value of attribute response.



40
41
42
# File 'lib/npolar/api/client/json_api_client.rb', line 40

def response
  @response
end

#responsesObject (readonly)

Returns the value of attribute responses.



40
41
42
# File 'lib/npolar/api/client/json_api_client.rb', line 40

def responses
  @responses
end

#sliceObject

Returns the value of attribute slice.



39
40
41
# File 'lib/npolar/api/client/json_api_client.rb', line 39

def slice
  @slice
end

#uriObject (readonly)

Returns the value of attribute uri.



40
41
42
# File 'lib/npolar/api/client/json_api_client.rb', line 40

def uri
  @uri
end

Instance Method Details

#allObject Also known as: feed

All documents



87
88
89
90
91
92
93
# File 'lib/npolar/api/client/json_api_client.rb', line 87

def all
  mash = get_body("_feed", {:fields=>"*"})
  unless mash.key? "feed"
    raise "No feed returned"
  end
  mash.feed.entries
end

#baseObject

Base URI (without trailing slash)



97
98
99
100
101
# File 'lib/npolar/api/client/json_api_client.rb', line 97

def base
  unless @base.nil?
    @base.gsub(/\/$/, "")
  end
end

#delete(path = nil, param = {}, header = {}) ⇒ Object

DELETE



105
106
107
108
109
110
111
112
113
# File 'lib/npolar/api/client/json_api_client.rb', line 105

def delete(path=nil, param={}, header={})
  if param.key? "ids"
    delete_ids(uri, param["ids"])
  else
    execute(
      request(path, :delete, nil, param, header)
    )
  end
end

#delete_ids(endpoint, ids) ⇒ Object



115
116
117
# File 'lib/npolar/api/client/json_api_client.rb', line 115

def delete_ids(endpoint, ids)
  delete_uris(self.class.uris_from_ids(endpoint, ids))
end

#delete_uris(uris) ⇒ Object



119
120
121
122
123
# File 'lib/npolar/api/client/json_api_client.rb', line 119

def delete_uris(uris)
  @responses=[]
  multi_request("DELETE", uris, nil, param, header).run
  responses
end

#errors(document_or_id) ⇒ Array

Validation errors

Returns:

  • (Array)


139
140
141
# File 'lib/npolar/api/client/json_api_client.rb', line 139

def errors(document_or_id)
  @errors ||= model.merge(document_or_id).errors
end

#execute(request = nil) ⇒ Object



326
327
328
329
# File 'lib/npolar/api/client/json_api_client.rb', line 326

def execute(request=nil)
  log.debug log_message(request)
  @response = request.run
end

#get(path = nil) ⇒ Object

GET



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/npolar/api/client/json_api_client.rb', line 180

def get(path=nil)
  if param.key? "ids"
    get_ids(uri, param["ids"])
  else
    request = request(path, :get, nil, param, header)
  
    request.on_success do |response|
      if response.headers["Content-Type"] =~ /application\/json/
        parsed = JSON.parse(response.body)
        if model?
          begin
            # hmm => will loose model!
            @modelwas = model
            @model = model.class.new(parsed)
            @mash = model
          rescue
            @model = @modelwas
            # Parsing only for JSON objects
          end
        end
      end
    end
  
  execute(request)
  end
end

#get_body(uri, param = {}) ⇒ Object

deprecated



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/npolar/api/client/json_api_client.rb', line 144

def get_body(uri, param={})
  @param = param
  response = get(uri)
  unless response.success?
    raise "Could not GET #{uri} status: #{response.code}"
  end
  
  begin 
    body = JSON.parse(response.body)
    if body.is_a? Hash
      
      if model? and not body.key? "feed"
        body = model.class.new(body)
      else
        body = Hashie::Mash.new(body)
      end
    end
    
  rescue
    body = response.body
  end
  
  body
  
  #if response.headers["Content-Type"] =~ /application\/json/
  #  #if model?
  #  JSON.parse(body)
  #  #
  #  #model
  #else
  #  body
  #end

end

#get_ids(endpoint, ids) ⇒ Object



207
208
209
# File 'lib/npolar/api/client/json_api_client.rb', line 207

def get_ids(endpoint, ids)
  get_uris(self.class.uris_from_ids(endpoint, ids))
end

#get_uris(uris) ⇒ Object Also known as: multi_get



211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/npolar/api/client/json_api_client.rb', line 211

def get_uris(uris)
  @responses=[]
  multi_request("GET", uris).run
  responses
  ## set on success =>
  #json = responses.select {|r| r.success? and r.headers["Content-Type"] =~ /application\/(\w+[+])?json/ }
  #if json.size == responses.size
  #  responses.map {|r| r.body }
  #else
  #  raise "Failed "
  #end
end

#head(path = nil, param = {}, header = {}) ⇒ Object

HEAD



226
227
228
# File 'lib/npolar/api/client/json_api_client.rb', line 226

def head(path=nil, param={}, header={})
  execute(request(path, :head, nil, param, header))
end

#http_methodObject Also known as: verb



132
133
134
# File 'lib/npolar/api/client/json_api_client.rb', line 132

def http_method
  @method
end

#idsObject

All ids



231
232
233
# File 'lib/npolar/api/client/json_api_client.rb', line 231

def ids
  get_body("_ids").ids
end

#initObject



77
78
79
80
81
82
83
84
# File 'lib/npolar/api/client/json_api_client.rb', line 77

def init
  @model = Hashie::Mash.new
  @log = ENV["NPOLAR_ENV"] == "test" ? ::Logger.new("/dev/null") : ::Logger.new(STDERR)
  @concurrency = 5
  @slice = 1000
  @param={}
  @header={}
end

#invalidObject

All invalid documents



236
237
238
# File 'lib/npolar/api/client/json_api_client.rb', line 236

def invalid
  valid(false)
end

#model?Boolean

Model?

Returns:

  • (Boolean)


241
242
243
# File 'lib/npolar/api/client/json_api_client.rb', line 241

def model?
  not @model.nil?
end

#on_completeObject



404
405
406
# File 'lib/npolar/api/client/json_api_client.rb', line 404

def on_complete
  @on_complete ||= lambda {|response|} #noop
end

#on_failureObject



391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/npolar/api/client/json_api_client.rb', line 391

def on_failure
  @on_failure ||= lambda {|response|
    if response.code == 0
      # No response, something's wrong.
      log.error "#{request.verb} #{request.uri.path} failed with message: #{response.return_message}"
    elsif response.timed_out?
      log.error "#{request.verb} #{request.uri.path} timed out in #{response.total_time} seconds"
    else
      log.error log_message(response)
    end
  }
end

#on_successObject



408
409
410
411
412
# File 'lib/npolar/api/client/json_api_client.rb', line 408

def on_success
  @on_success ||= lambda {|response|
    log.info log_message(response)
  }
end

#passwordObject



317
318
319
320
# File 'lib/npolar/api/client/json_api_client.rb', line 317

def password
  # export NPOLAR_HTTP_PASSWORD=http_password
  @password ||= ENV["NPOLAR_API_PASSWORD"]
end

#password=(password) ⇒ Object



322
323
324
# File 'lib/npolar/api/client/json_api_client.rb', line 322

def password=(password)
  @password=password
end

#post(body, path = nil, param = {}, header = {}) ⇒ Object

POST

Parameters:

  • body (Array, Hash, String)


247
248
249
250
251
252
253
254
255
# File 'lib/npolar/api/client/json_api_client.rb', line 247

def post(body, path=nil, param={}, header={})        
  if header["Content-Type"] =~ /application\/(\w+[+])?json/
    chunk_save(path, "POST", body, param, header)
  else
    execute(
      request(path, :post, body, param, header)
    )
  end
end

#put(body, path = nil, param = {}, header = {}) ⇒ Object

PUT



258
259
260
261
262
# File 'lib/npolar/api/client/json_api_client.rb', line 258

def put(body, path=nil, param={}, header={})
  execute(
    request(path, :put, body, param, header)
  )
end

#request(path = nil, method = :get, body = nil, params = {}, headers = {}) ⇒ Object

Returns [].

Returns:



332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/npolar/api/client/json_api_client.rb', line 332

def request(path=nil, method=:get, body=nil, params={}, headers={})
  
  if path =~ /^http(s)?[:]\/\//
    # Absolute URI
    uri = path
    
  elsif path.nil?
    # Use base URI if path is nil
    uri = base

  elsif path =~ /^\/\w+/
    # Support /relative URIs by prepending base
    uri = base+path
    
  elsif path =~ /^\w+/ and base =~ /^http(s)?[:]\/\//          
    uri = base+"/"+path
  else
    # Invalid URI
    raise ArgumentError, "Path is invalid: #{path}"
  end

  unless uri.is_a? URI
    uri = URI.parse(uri)
  end

  @uri = uri
  @param = param
  @header = headers
  method = method.downcase.to_sym

  context = { method: method,
    body: body,
    params: params,
    headers: headers
  }
  if true == authorization or [:delete, :post, :put].include? method
    context[:userpwd] = "#{username}:#{password}"
  end
  
  request = Typhoeus::Request.new(uri.to_s, context)

  request.on_complete do |response|
    on_complete.call(response)
  end

  request.on_failure do |response|
    on_failure.call(response)
  end

  request.on_success do |response|
    on_success.call(response)
  end

  @request = request

  request
  
end

#statusObject



264
265
266
# File 'lib/npolar/api/client/json_api_client.rb', line 264

def status
  response.code
end

#urisObject



268
269
270
# File 'lib/npolar/api/client/json_api_client.rb', line 268

def uris
  ids.map {|id| base+"/"+id }
end

#usernameObject



308
309
310
311
# File 'lib/npolar/api/client/json_api_client.rb', line 308

def username
  # export NPOLAR_HTTP_USERNAME=http_username
  @username ||= ENV["NPOLAR_API_USERNAME"]
end

#username=(username) ⇒ Object



313
314
315
# File 'lib/npolar/api/client/json_api_client.rb', line 313

def username=(username)
  @username=username
end

#valid(condition = true) ⇒ Object

All valid documents



273
274
275
# File 'lib/npolar/api/client/json_api_client.rb', line 273

def valid(condition=true)
  all.select {|d| condition == valid?(d) }.map {|d| model.class.new(d)}
end

#valid?(document_or_id) ⇒ Boolean

Valid?

Returns:

  • (Boolean)


278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/npolar/api/client/json_api_client.rb', line 278

def valid?(document_or_id)
  # FIXME Hashie::Mash will always respond to #valid? 
  if not model? or not model.respond_to?(:valid?)
    return true
  end

  validator = model.class.new(document_or_id)

  # Return true if validator is a Hash with errors key !
  # FIXME Hashie::Mash will always respond to #valid? 
  if validator.key? :valid? or validator.key? :errors
    return true
  end
  
  valid = validator.valid?
  
  if validator.errors.nil?
    return true
  end

  @errors = validator.errors # store to avoid revalidating
  valid = case valid
    when true, nil
      true
    when false
      false
  end
  valid
end