nimbu-api 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/nimbu-api.rb +43 -0
- data/lib/nimbu-api/authentication.rb +76 -0
- data/lib/nimbu-api/builder.rb +31 -0
- data/lib/nimbu-api/client.rb +26 -0
- data/lib/nimbu-api/configuration.rb +109 -0
- data/lib/nimbu-api/connection.rb +88 -0
- data/lib/nimbu-api/endpoint.rb +199 -0
- data/lib/nimbu-api/endpoints/authorizations.rb +113 -0
- data/lib/nimbu-api/endpoints/channels.rb +31 -0
- data/lib/nimbu-api/endpoints/channels/entries.rb +50 -0
- data/lib/nimbu-api/endpoints/sites.rb +34 -0
- data/lib/nimbu-api/endpoints/videos.rb +26 -0
- data/lib/nimbu-api/errors.rb +31 -0
- data/lib/nimbu-api/errors/bad_request.rb +14 -0
- data/lib/nimbu-api/errors/client_error.rb +20 -0
- data/lib/nimbu-api/errors/forbidden.rb +14 -0
- data/lib/nimbu-api/errors/internal_server_error.rb +15 -0
- data/lib/nimbu-api/errors/invalid_options.rb +18 -0
- data/lib/nimbu-api/errors/not_acceptable.rb +15 -0
- data/lib/nimbu-api/errors/not_found.rb +14 -0
- data/lib/nimbu-api/errors/required_params.rb +18 -0
- data/lib/nimbu-api/errors/service_error.rb +65 -0
- data/lib/nimbu-api/errors/service_unavailable.rb +15 -0
- data/lib/nimbu-api/errors/unauthorized.rb +15 -0
- data/lib/nimbu-api/errors/unknown_value.rb +18 -0
- data/lib/nimbu-api/errors/unprocessable_entity.rb +14 -0
- data/lib/nimbu-api/errors/validations.rb +18 -0
- data/lib/nimbu-api/pagination.rb +106 -0
- data/lib/nimbu-api/pagination/page_iterator.rb +157 -0
- data/lib/nimbu-api/pagination/page_links.rb +48 -0
- data/lib/nimbu-api/pagination/paged_request.rb +41 -0
- data/lib/nimbu-api/pagination/pagination.rb +102 -0
- data/lib/nimbu-api/request.rb +81 -0
- data/lib/nimbu-api/request/arguments.rb +171 -0
- data/lib/nimbu-api/request/basic_auth.rb +31 -0
- data/lib/nimbu-api/request/json.rb +46 -0
- data/lib/nimbu-api/request/normalizer.rb +29 -0
- data/lib/nimbu-api/request/oauth2.rb +42 -0
- data/lib/nimbu-api/request/parameter_filter.rb +34 -0
- data/lib/nimbu-api/request/validations.rb +25 -0
- data/lib/nimbu-api/request/validations/format.rb +26 -0
- data/lib/nimbu-api/request/validations/presence.rb +32 -0
- data/lib/nimbu-api/request/validations/required.rb +26 -0
- data/lib/nimbu-api/request/validations/token.rb +35 -0
- data/lib/nimbu-api/response.rb +34 -0
- data/lib/nimbu-api/response/header.rb +76 -0
- data/lib/nimbu-api/response/json.rb +29 -0
- data/lib/nimbu-api/response/mashify.rb +24 -0
- data/lib/nimbu-api/response/raise_error.rb +18 -0
- data/lib/nimbu-api/response/wrapper.rb +149 -0
- data/lib/nimbu-api/response/xmlize.rb +26 -0
- data/lib/nimbu-api/utils/all.rb +6 -0
- data/lib/nimbu-api/utils/constants.rb +37 -0
- data/lib/nimbu-api/utils/descendants.rb +11 -0
- data/lib/nimbu-api/utils/extend_array.rb +17 -0
- data/lib/nimbu-api/utils/extend_hash.rb +73 -0
- data/lib/nimbu-api/utils/json.rb +19 -0
- data/lib/nimbu-api/utils/url.rb +56 -0
- data/lib/nimbu-api/version.rb +3 -0
- data/nimbu-api.gemspec +31 -0
- metadata +294 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
module Nimbu
|
2
|
+
module Pagination
|
3
|
+
class PageLinks
|
4
|
+
include Nimbu::Utils::Constants
|
5
|
+
|
6
|
+
DELIM_LINKS = ",".freeze # :nodoc:
|
7
|
+
|
8
|
+
# Hold the extracted values for URI from the Link header
|
9
|
+
# for the first, last, next and previous page.
|
10
|
+
attr_accessor :first, :last, :next, :prev
|
11
|
+
|
12
|
+
# Parses links from executed request
|
13
|
+
#
|
14
|
+
def initialize(response_headers)
|
15
|
+
link_header = response_headers[HEADER_LINK]
|
16
|
+
if link_header
|
17
|
+
return unless link_header =~ /(next|first|last|prev)/
|
18
|
+
|
19
|
+
link_header.split(DELIM_LINKS).each do |link|
|
20
|
+
if link.strip =~ /<([^>]+)>; rel=\"([^\"]+)\"/
|
21
|
+
url_part, meta_part = $1, $2
|
22
|
+
next if !url_part || !meta_part
|
23
|
+
case meta_part
|
24
|
+
when META_FIRST
|
25
|
+
self.first = url_part
|
26
|
+
when META_LAST
|
27
|
+
self.last = url_part
|
28
|
+
when META_NEXT
|
29
|
+
self.next = url_part
|
30
|
+
when META_PREV
|
31
|
+
self.prev = url_part
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
# When on the first page
|
37
|
+
self.next = response_headers[HEADER_NEXT]
|
38
|
+
self.last = response_headers[HEADER_LAST]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def any?
|
43
|
+
self.first || self.last || self.next || self.prev
|
44
|
+
end
|
45
|
+
|
46
|
+
end # PageLinks
|
47
|
+
end # Pagination
|
48
|
+
end # Nimbu
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nimbu
|
4
|
+
module Pagination
|
5
|
+
# A module that adds http get request to response pagination
|
6
|
+
module PagedRequest
|
7
|
+
include Nimbu::Utils::Constants
|
8
|
+
|
9
|
+
FIRST_PAGE = 1 # Default request page if none provided
|
10
|
+
|
11
|
+
PER_PAGE = 30 # Default number of items as specified by API
|
12
|
+
|
13
|
+
NOT_FOUND = -1 # Either page or per_page parameter not present
|
14
|
+
|
15
|
+
# Check if current api instance has default per_page param set,
|
16
|
+
# otherwise use global default.
|
17
|
+
#
|
18
|
+
def default_page_size
|
19
|
+
current_api.per_page ? current_api.per_page : PER_PAGE
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_page
|
23
|
+
current_api.page ? current_api.page : FIRST_PAGE
|
24
|
+
end
|
25
|
+
|
26
|
+
# Perform http get request with paginatoin parameters
|
27
|
+
#
|
28
|
+
def page_request(path, params={})
|
29
|
+
if params[PARAM_PER_PAGE] == NOT_FOUND
|
30
|
+
params[PARAM_PER_PAGE] = default_page_size
|
31
|
+
end
|
32
|
+
if params[PARAM_PAGE] && params[PARAM_PAGE] == NOT_FOUND
|
33
|
+
params[PARAM_PAGE] = default_page
|
34
|
+
end
|
35
|
+
|
36
|
+
current_api.get_request(path, params)
|
37
|
+
end
|
38
|
+
|
39
|
+
end # PagedRequest
|
40
|
+
end # Pagination
|
41
|
+
end # Nimbu
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Nimbu
|
4
|
+
|
5
|
+
# A module that decorates response with pagination helpers
|
6
|
+
module Pagination
|
7
|
+
include Nimbu::Utils::Constants
|
8
|
+
|
9
|
+
# Return page links
|
10
|
+
def links
|
11
|
+
@links = Nimbu::Pagination::PageLinks.new(env[:response_headers])
|
12
|
+
end
|
13
|
+
|
14
|
+
# Retrive number of total pages base on current :per_page parameter
|
15
|
+
def count_pages
|
16
|
+
page_iterator.count.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
# Iterate over results set pages by automatically calling `next_page`
|
20
|
+
# until all pages are exhausted. Caution needs to be exercised when
|
21
|
+
# using this feature - 100 pages iteration will perform 100 API calls.
|
22
|
+
# By default this is off. You can set it on the client, individual API
|
23
|
+
# instances or just per given request.
|
24
|
+
#
|
25
|
+
def auto_paginate(auto=false)
|
26
|
+
if current_api.auto_pagination? || auto
|
27
|
+
resources_bodies = []
|
28
|
+
each_page { |resource| resources_bodies += resource.body }
|
29
|
+
self.body = resources_bodies
|
30
|
+
end
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Iterator like each for response pages. If there are no pages to
|
35
|
+
# iterate over this method will return current page.
|
36
|
+
def each_page
|
37
|
+
yield self
|
38
|
+
while page_iterator.has_next?
|
39
|
+
yield next_page
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Retrives the result of the first page. Returns <tt>nil</tt> if there is
|
44
|
+
# no first page - either because you are already on the first page
|
45
|
+
# or there are no pages at all in the result.
|
46
|
+
def first_page
|
47
|
+
first_request = page_iterator.first
|
48
|
+
self.instance_eval { @env = first_request.env } if first_request
|
49
|
+
first_request
|
50
|
+
end
|
51
|
+
|
52
|
+
# Retrives the result of the next page. Returns <tt>nil</tt> if there is
|
53
|
+
# no next page or no pages at all.
|
54
|
+
def next_page
|
55
|
+
next_request = page_iterator.next
|
56
|
+
self.instance_eval { @env = next_request.env } if next_request
|
57
|
+
next_request
|
58
|
+
end
|
59
|
+
|
60
|
+
# Retrives the result of the previous page. Returns <tt>nil</tt> if there is
|
61
|
+
# no previous page or no pages at all.
|
62
|
+
def prev_page
|
63
|
+
prev_request = page_iterator.prev
|
64
|
+
self.instance_eval { @env = prev_request.env } if prev_request
|
65
|
+
prev_request
|
66
|
+
end
|
67
|
+
alias :previous_page :prev_page
|
68
|
+
|
69
|
+
# Retrives the result of the last page. Returns <tt>nil</tt> if there is
|
70
|
+
# no last page - either because you are already on the last page,
|
71
|
+
# there is only one page or there are no pages at all in the result.
|
72
|
+
def last_page
|
73
|
+
last_request = page_iterator.last
|
74
|
+
self.instance_eval { @env = last_request.env } if last_request
|
75
|
+
last_request
|
76
|
+
end
|
77
|
+
|
78
|
+
# Retrives a specific result for a page given page number.
|
79
|
+
# The <tt>page_number</tt> parameter is not validate, hitting a page
|
80
|
+
# that does not exist will return Nimbu API error. Consequently, if
|
81
|
+
# there is only one page, this method returns nil
|
82
|
+
def page(page_number)
|
83
|
+
request = page_iterator.get_page(page_number)
|
84
|
+
self.instance_eval { @env = request.env } if request
|
85
|
+
request
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns <tt>true</tt> if there is another page in the result set,
|
89
|
+
# otherwise <tt>false</tt>
|
90
|
+
def has_next_page?
|
91
|
+
page_iterator.has_next?
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Internally used page iterator
|
97
|
+
def page_iterator # :nodoc:
|
98
|
+
@page_iterator = Nimbu::Pagination::PageIterator.new(links, current_api)
|
99
|
+
end
|
100
|
+
|
101
|
+
end # Pagination
|
102
|
+
end # Nimbu
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'nimbu-api/request/oauth2'
|
4
|
+
require 'nimbu-api/request/basic_auth'
|
5
|
+
require 'nimbu-api/request/json'
|
6
|
+
require 'nimbu-api/request/validations'
|
7
|
+
require 'nimbu-api/request/arguments'
|
8
|
+
|
9
|
+
module Nimbu
|
10
|
+
|
11
|
+
# Defines HTTP verbs
|
12
|
+
module Request
|
13
|
+
include Nimbu::Utils::Constants
|
14
|
+
|
15
|
+
METHODS = [:get, :post, :put, :delete, :patch]
|
16
|
+
METHODS_WITH_BODIES = [ :post, :put, :patch ]
|
17
|
+
|
18
|
+
def get_request(path, params={}, options={})
|
19
|
+
request(:get, path, params, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def patch_request(path, params={}, options={})
|
23
|
+
request(:patch, path, params, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def post_request(path, params={}, options={})
|
27
|
+
request(:post, path, params, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def put_request(path, params={}, options={})
|
31
|
+
request(:put, path, params, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_request(path, params={}, options={})
|
35
|
+
request(:delete, path, params, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def request(method, path, params, options) # :nodoc:
|
39
|
+
if !METHODS.include?(method)
|
40
|
+
raise ArgumentError, "unkown http method: #{method}"
|
41
|
+
end
|
42
|
+
|
43
|
+
puts "EXECUTED: #{method} - #{path} with #{params} and #{options}" if ENV['DEBUG']
|
44
|
+
|
45
|
+
conn = connection(options.merge(current_options))
|
46
|
+
if conn.path_prefix != '/' && path.index(conn.path_prefix) != 0
|
47
|
+
path = (conn.path_prefix + path).gsub(/\/(\/)*/, '/')
|
48
|
+
end
|
49
|
+
|
50
|
+
response = conn.send(method) do |request|
|
51
|
+
unless options[:with_attachments]
|
52
|
+
case method.to_sym
|
53
|
+
when *(METHODS - METHODS_WITH_BODIES)
|
54
|
+
request.body = params.delete('data') if params.has_key?('data')
|
55
|
+
request.url(path, params)
|
56
|
+
when *METHODS_WITH_BODIES
|
57
|
+
request.path = path
|
58
|
+
request.body = extract_data_from_params(params) unless params.empty?
|
59
|
+
end
|
60
|
+
else
|
61
|
+
request.path = path
|
62
|
+
request.body = params
|
63
|
+
end
|
64
|
+
end
|
65
|
+
Response::Wrapper.new(response, self).auto_paginate
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def extract_data_from_params(params) # :nodoc:
|
71
|
+
return params['data'] if params.has_key?('data') and !params['data'].nil?
|
72
|
+
return params
|
73
|
+
end
|
74
|
+
|
75
|
+
def _extract_mime_type(params, options) # :nodoc:
|
76
|
+
options['resource'] = params['resource'] ? params.delete('resource') : ''
|
77
|
+
options['mime_type'] = params['resource'] ? params.delete('mime_type') : ''
|
78
|
+
end
|
79
|
+
|
80
|
+
end # Request
|
81
|
+
end # Nimbu
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'nimbu-api/request/normalizer'
|
4
|
+
require 'nimbu-api/request/parameter_filter'
|
5
|
+
|
6
|
+
module Nimbu
|
7
|
+
module Request
|
8
|
+
# Request arguments handler
|
9
|
+
class Arguments
|
10
|
+
|
11
|
+
include Normalizer
|
12
|
+
include ParameterFilter
|
13
|
+
include Validations
|
14
|
+
|
15
|
+
AUTO_PAGINATION = 'auto_pagination'.freeze
|
16
|
+
|
17
|
+
# Parameters passed to request
|
18
|
+
attr_reader :params
|
19
|
+
|
20
|
+
attr_reader :remaining
|
21
|
+
|
22
|
+
# The request api
|
23
|
+
#
|
24
|
+
attr_reader :api
|
25
|
+
|
26
|
+
# Required arguments
|
27
|
+
#
|
28
|
+
attr_reader :required
|
29
|
+
private :required
|
30
|
+
|
31
|
+
# Optional arguments
|
32
|
+
#
|
33
|
+
attr_reader :optional
|
34
|
+
private :optional
|
35
|
+
|
36
|
+
# Takes api, filters and required arguments
|
37
|
+
#
|
38
|
+
# = Parameters
|
39
|
+
# :required - arguments that must be present before request is fired
|
40
|
+
#
|
41
|
+
def initialize(api, options={})
|
42
|
+
normalize! options
|
43
|
+
@api = api
|
44
|
+
@required = options.fetch('required', []).map(&:to_s)
|
45
|
+
@optional = options.fetch('optional', []).map(&:to_s)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Parse arguments to allow for flexible api calls.
|
49
|
+
# Arguments can be part of parameters hash or be simple string arguments.
|
50
|
+
#
|
51
|
+
def parse(*args, &block)
|
52
|
+
options = args.extract_options!
|
53
|
+
normalize! options
|
54
|
+
|
55
|
+
if !args.size.zero?
|
56
|
+
parse_arguments *args
|
57
|
+
else
|
58
|
+
# Arguments are inside the parameters hash
|
59
|
+
parse_options options
|
60
|
+
end
|
61
|
+
@params = options
|
62
|
+
@remaining = extract_remaining(args)
|
63
|
+
extract_pagination(options)
|
64
|
+
yield_or_eval(&block)
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Remove unkown keys from parameters hash.
|
69
|
+
#
|
70
|
+
# = Parameters
|
71
|
+
# :recursive - boolean that toggles whether nested filtering should be applied
|
72
|
+
#
|
73
|
+
def sift(keys, key=nil, options={})
|
74
|
+
filter! keys, (key.nil? ? params : params[key]), options if keys.any?
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
# Check if required keys are present inside parameters hash.
|
79
|
+
#
|
80
|
+
def assert_required(required)
|
81
|
+
assert_required_keys required, params
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
# Check if parameters match expected values.
|
86
|
+
#
|
87
|
+
def assert_values(values, key=nil)
|
88
|
+
assert_valid_values values, (key.nil? ? params : params[key])
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# Check and set all requried arguments.
|
95
|
+
#
|
96
|
+
def parse_arguments(*args)
|
97
|
+
assert_presence_of *args
|
98
|
+
required.each_with_index do |req, indx|
|
99
|
+
api.set req, args[indx]
|
100
|
+
end
|
101
|
+
check_requirement!(*args)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Find remaining arguments
|
105
|
+
#
|
106
|
+
def extract_remaining(args)
|
107
|
+
args[required.size..-1]
|
108
|
+
end
|
109
|
+
|
110
|
+
# Fine auto_pagination parameter in options hash
|
111
|
+
#
|
112
|
+
def extract_pagination(options)
|
113
|
+
if (value = options.delete(AUTO_PAGINATION))
|
114
|
+
api.auto_pagination = value
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Remove required arguments from parameters and
|
119
|
+
# validate their presence(if not nil or empty string).
|
120
|
+
#
|
121
|
+
def parse_options(options)
|
122
|
+
options.each { |key, val| remove_required(options, key, val) }
|
123
|
+
provided_args = check_assignment!(options)
|
124
|
+
check_requirement!(*provided_args.keys)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Remove required argument from parameters
|
128
|
+
#
|
129
|
+
def remove_required(options, key, val)
|
130
|
+
key = key.to_s
|
131
|
+
if required.include? key
|
132
|
+
assert_presence_of val
|
133
|
+
options.delete key
|
134
|
+
api.set key, val
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Check if required arguments have been set on instance.
|
139
|
+
#
|
140
|
+
def check_assignment!(options)
|
141
|
+
result = required.inject({}) { |hash, arg|
|
142
|
+
if api.respond_to?(:"#{arg}") && (value = api.send(:"#{arg}"))
|
143
|
+
hash[arg] = value
|
144
|
+
end
|
145
|
+
hash
|
146
|
+
}
|
147
|
+
assert_presence_of result
|
148
|
+
result
|
149
|
+
end
|
150
|
+
|
151
|
+
# Check if required arguments are present.
|
152
|
+
#
|
153
|
+
def check_requirement!(*args)
|
154
|
+
args_length = args.length
|
155
|
+
required_length = required.length
|
156
|
+
|
157
|
+
if args_length < required_length
|
158
|
+
::Kernel.raise ArgumentError, "wrong number of arguments (#{args_length} for #{required_length})"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Evaluate block
|
163
|
+
#
|
164
|
+
def yield_or_eval(&block)
|
165
|
+
return unless block
|
166
|
+
block.arity > 0 ? yield(self) : self.instance_eval(&block)
|
167
|
+
end
|
168
|
+
|
169
|
+
end # Arguments
|
170
|
+
end # Request
|
171
|
+
end # Nimbu
|