clx_api 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +55 -0
- data/Rakefile +7 -0
- data/clx_api.gemspec +26 -0
- data/doc/CLX.html +305 -0
- data/doc/CLX/API.html +1491 -0
- data/doc/CLX/CLXAPIException.html +411 -0
- data/doc/CLX/CLXException.html +134 -0
- data/doc/CLX/HTTPAdapter.html +1294 -0
- data/doc/CLX/HTTPClient.html +1058 -0
- data/doc/ClxApi.html +141 -0
- data/doc/_index.html +161 -0
- data/doc/class_list.html +58 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.README.html +112 -0
- data/doc/file_list.html +60 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +112 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +181 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +279 -0
- data/doc/top-level-namespace.html +112 -0
- data/examples/get_gateway_by_id.rb +16 -0
- data/examples/get_gateways.rb +18 -0
- data/examples/get_operator_by_id.rb +21 -0
- data/examples/get_operators.rb +23 -0
- data/examples/get_price_entries_by_gateway_id.rb +19 -0
- data/examples/get_price_entries_by_gateway_id_and_operator_id.rb +17 -0
- data/examples/get_price_entries_by_gateway_id_and_operator_id_and_date.rb +18 -0
- data/examples/readme.md +167 -0
- data/lib/clx_api.rb +35 -0
- data/lib/clx_api/api.rb +132 -0
- data/lib/clx_api/exceptions/clx_api_exception.rb +25 -0
- data/lib/clx_api/exceptions/clx_exception.rb +8 -0
- data/lib/clx_api/http_adapter.rb +129 -0
- data/lib/clx_api/http_client.rb +163 -0
- data/lib/clx_api/version.rb +4 -0
- data/test/adapter/test_adapter.rb +67 -0
- data/test/api_test.rb +306 -0
- data/test/http_adapter_test.rb +211 -0
- data/test/http_client_test.rb +173 -0
- data/test/test_helper.rb +7 -0
- metadata +168 -0
data/lib/clx_api/api.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
module CLX
|
2
|
+
|
3
|
+
# Library class for CLX Networks REST API
|
4
|
+
class API
|
5
|
+
|
6
|
+
# @!attribute [r]
|
7
|
+
# Mostly for testing
|
8
|
+
attr_accessor :http_client
|
9
|
+
|
10
|
+
# Initialize a new API client
|
11
|
+
# @param [String] username
|
12
|
+
# @param [String] password
|
13
|
+
# @param [HTTPAdapter] http_adapter
|
14
|
+
# Used for testing
|
15
|
+
# @return [CLX::API]
|
16
|
+
# @example
|
17
|
+
# CLX::API.new 'my_username', 'my_password'
|
18
|
+
def initialize(username, password, http_adapter = nil)
|
19
|
+
http_adapter = http_adapter.nil? ? HTTPAdapter.new : http_adapter
|
20
|
+
http_adapter.set_auth(username, password)
|
21
|
+
|
22
|
+
@http_client = HTTPClient.new(CLX::base_url, http_adapter)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Enables change of credentials after initialization
|
26
|
+
# @param [String] username
|
27
|
+
# @param [String] password
|
28
|
+
def set_auth(username, password)
|
29
|
+
@http_client.http_adapter.set_auth(username, password)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Enables change of base URL after initialization
|
33
|
+
# @param [String] url
|
34
|
+
def set_base_url(url)
|
35
|
+
@http_client.base_url = url
|
36
|
+
end
|
37
|
+
|
38
|
+
# Get all operators from the API
|
39
|
+
# @return [hash] operators
|
40
|
+
# list of operators as hash.
|
41
|
+
# @example
|
42
|
+
# clx_api = CLX::API.new 'my_username', 'my_password'
|
43
|
+
# operators = clx_api.get_operators
|
44
|
+
def get_operators
|
45
|
+
url = CLX.paths[:operator]
|
46
|
+
@http_client.get(url)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get one operator based on it's operator id
|
50
|
+
# @param [Integer] operator_id Operator ID
|
51
|
+
# @return [hash] operator
|
52
|
+
# One operator as hash.
|
53
|
+
# @example
|
54
|
+
# clx_api = CLX::API.new 'my_username', 'my_password'
|
55
|
+
# operator = clx_api.get_operator(1)
|
56
|
+
def get_operator_by_id(operator_id)
|
57
|
+
valid_id?(operator_id)
|
58
|
+
url = CLX.paths[:operator] + '/' + operator_id.to_s
|
59
|
+
@http_client.get(url)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Get all gateways
|
63
|
+
# @return [hash] gateways
|
64
|
+
# list of gateways as hash.
|
65
|
+
def get_gateways
|
66
|
+
url = CLX.paths[:gateway]
|
67
|
+
@http_client.get(url)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Get one gateway based on it's gateway id
|
71
|
+
# @param [Integer] gateway_id Gateway ID
|
72
|
+
# @return [hash] gateway
|
73
|
+
# One operators as hash.
|
74
|
+
def get_gateway_by_id(gateway_id)
|
75
|
+
valid_id?(gateway_id)
|
76
|
+
url = CLX.paths[:gateway] + '/' + gateway_id.to_s
|
77
|
+
@http_client.get(url)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get price entires based on gateway id
|
81
|
+
# @param [Integer] gateway_id Gateway ID
|
82
|
+
# @return [hash] price_entires
|
83
|
+
# list of price entries as hash.
|
84
|
+
def get_price_entires_by_gateway_id(gateway_id)
|
85
|
+
valid_id?(gateway_id)
|
86
|
+
url = CLX.paths[:gateway] + '/' + gateway_id.to_s + '/price'
|
87
|
+
@http_client.get(url)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get price entiry based on gateway id and operator id
|
91
|
+
# @param [Integer] gateway_id Gateway ID
|
92
|
+
# @param [Integer] operator_id Operator ID
|
93
|
+
# @return [hash] price_entry
|
94
|
+
# one price entry as hash.
|
95
|
+
def get_price_entries_by_gateway_id_and_operator_id(gateway_id, operator_id)
|
96
|
+
valid_id?(gateway_id)
|
97
|
+
valid_id?(operator_id)
|
98
|
+
url = CLX.paths[:gateway] + '/' + gateway_id.to_s + '/price/' + operator_id.to_s
|
99
|
+
@http_client.get(url)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Get price entiry based on gateway id, operator id and a date
|
103
|
+
# @param [Integer] gateway_id Gateway ID
|
104
|
+
# @param [Integer] operator_id Operator ID
|
105
|
+
# @param [DateTime] date DateTime
|
106
|
+
# @return [hash] price_entry
|
107
|
+
# one price entry as hash.
|
108
|
+
def get_price_entries_by_gateway_id_and_operator_id_and_date(gateway_id, operator_id, date)
|
109
|
+
valid_id?(gateway_id)
|
110
|
+
valid_id?(operator_id)
|
111
|
+
valid_date?(date)
|
112
|
+
date_query = "?date=#{date.year}-#{date.month}-#{date.day}"
|
113
|
+
url = CLX.paths[:gateway] + '/' + gateway_id.to_s + '/price/' + operator_id.to_s + '/' + date_query
|
114
|
+
@http_client.get(url)
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
# Validates that in is of type integer and is grater than zero
|
120
|
+
def valid_id?(id)
|
121
|
+
raise CLXException, 'Id must be integer' unless id.is_a? Integer
|
122
|
+
raise CLXException, 'Id must be greater than zero' unless id > 0
|
123
|
+
end
|
124
|
+
|
125
|
+
#Validates that date is of type DateTime
|
126
|
+
def valid_date?(date)
|
127
|
+
raise CLXException, 'Date must be of type DateTime' unless date.is_a? DateTime
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module CLX
|
2
|
+
|
3
|
+
# CLX Exception Class for API request errors
|
4
|
+
class CLXAPIException < Exception
|
5
|
+
|
6
|
+
# @!attribute [r]
|
7
|
+
attr_reader :clx_error_code
|
8
|
+
|
9
|
+
# @!attribute [r]
|
10
|
+
attr_reader :clx_error_message
|
11
|
+
|
12
|
+
# Initialize CLX Exception
|
13
|
+
# @param [String] clx_error_message
|
14
|
+
# @param [Integer] clx_error_code
|
15
|
+
# @example
|
16
|
+
# response = http_adapter.get('operator/99999999') #results in error from api
|
17
|
+
# raise CLXException(response.error.message, response.error.body), ""
|
18
|
+
def initialize(clx_error_message = nil, clx_error_code = nil)
|
19
|
+
@clx_error_message = clx_error_message
|
20
|
+
@clx_error_code = clx_error_code
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module CLX
|
4
|
+
|
5
|
+
#HTTP Adapter class for making RESTful HTTP-requests
|
6
|
+
class HTTPAdapter
|
7
|
+
|
8
|
+
# Contains the username used for Basic Auth requests
|
9
|
+
# @!attribute [r]
|
10
|
+
attr_reader :username
|
11
|
+
|
12
|
+
# Contains the password used for Basic Auth requests
|
13
|
+
# @!attribute [r]
|
14
|
+
attr_reader :password
|
15
|
+
|
16
|
+
# Set credentials for basic auth
|
17
|
+
# @param [String] username
|
18
|
+
# @param [String] password
|
19
|
+
def set_auth(username, password)
|
20
|
+
raise CLXException, 'Username must be a string' unless username.is_a? String
|
21
|
+
raise CLXException, 'Password must be a string' unless password.is_a? String
|
22
|
+
raise CLXException, 'Username can not be an empty string' unless username.length > 0
|
23
|
+
raise CLXException, 'Password can not be an empty string' unless password.length > 0
|
24
|
+
|
25
|
+
@username = username
|
26
|
+
@password = password
|
27
|
+
end
|
28
|
+
|
29
|
+
# GET-request
|
30
|
+
# @param [URI] uri
|
31
|
+
# Ruby URI object with full API URL
|
32
|
+
# @return [HTTP::Response]
|
33
|
+
def get(uri)
|
34
|
+
return execute('get', uri)
|
35
|
+
end
|
36
|
+
|
37
|
+
# POST-request
|
38
|
+
# (Not implemented)
|
39
|
+
# @param [URI] uri
|
40
|
+
# Ruby URI object with full API URL
|
41
|
+
# @param [Hash] data
|
42
|
+
# POST-data
|
43
|
+
# @return [HTTP::Response]
|
44
|
+
def post(uri, data)
|
45
|
+
return execute('post', uri, data)
|
46
|
+
end
|
47
|
+
|
48
|
+
# PUT-request
|
49
|
+
# (Not implemented)
|
50
|
+
# @param [URI] uri
|
51
|
+
# Ruby URI object with full API URL
|
52
|
+
# @param [Hash] data
|
53
|
+
# PUT-data
|
54
|
+
# @return [HTTP::Response]
|
55
|
+
def put(uri, data)
|
56
|
+
return execute('put', uri, data)
|
57
|
+
end
|
58
|
+
|
59
|
+
# DELETE-request
|
60
|
+
# (Not implemented)
|
61
|
+
# @param [URI] uri
|
62
|
+
# Ruby URI object with full API URL
|
63
|
+
# @return [HTTP::Response]
|
64
|
+
def delete(uri)
|
65
|
+
return execute('delete', uri)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# Execute request
|
71
|
+
# @param [String] method
|
72
|
+
# @param [String] uri
|
73
|
+
# Full API-path
|
74
|
+
# @param [Hash] data
|
75
|
+
# @return [HTTP::Response] result
|
76
|
+
# @raise [CLXException] if he request fails
|
77
|
+
def execute(method, uri, data = nil)
|
78
|
+
raise CLXException, 'uri must be instance of URI' unless uri.instance_of?(URI::HTTPS) || uri.instance_of?(URI::HTTP)
|
79
|
+
request = create_request(method, uri, data)
|
80
|
+
request.basic_auth(@username, @password)
|
81
|
+
http = create_http(uri);
|
82
|
+
|
83
|
+
return http.request(request)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Create Request object by method and uri
|
87
|
+
# @param [String] method
|
88
|
+
# HTTP
|
89
|
+
# @param [URI] uri
|
90
|
+
# @param [Hash] data
|
91
|
+
# @return [Mixed] request
|
92
|
+
# Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Put, Net::HTTP::Delete
|
93
|
+
# @example
|
94
|
+
# request = create_request("GET", 'http://some.url')
|
95
|
+
# @raise [CLXException] If an invalid HTTP-method was passed
|
96
|
+
def create_request(method, uri, data = nil)
|
97
|
+
method = method.upcase
|
98
|
+
if(method == 'GET')
|
99
|
+
return Net::HTTP::Get.new(uri)
|
100
|
+
elsif(method == 'POST')
|
101
|
+
request = Net::HTTP::Post.new(uri)
|
102
|
+
request.body = data.to_json
|
103
|
+
return request
|
104
|
+
elsif(method == 'PUT')
|
105
|
+
request = Net::HTTP::Put.new(uri)
|
106
|
+
request.body = data.to_json
|
107
|
+
return request
|
108
|
+
elsif(method == 'DELETE')
|
109
|
+
return Net::HTTP::Delete.new(uri)
|
110
|
+
else
|
111
|
+
raise CLXException, 'Unknown HTTP method'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Creates a Net:HTTP instance with ssl activated with URI-object
|
116
|
+
# @param [URI] uri
|
117
|
+
# @return [Net::HTTP] http
|
118
|
+
def create_http(uri)
|
119
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
120
|
+
if uri.instance_of? URI::HTTPS
|
121
|
+
http.use_ssl = true
|
122
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
123
|
+
end
|
124
|
+
return http
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module CLX
|
2
|
+
|
3
|
+
#HTTP Client class for making RESTful HTTP-requests
|
4
|
+
class HTTPClient
|
5
|
+
|
6
|
+
# Gives access to base_url so this can be modified
|
7
|
+
# @!attribute [rw]
|
8
|
+
attr_accessor :base_url
|
9
|
+
|
10
|
+
# Gives access to the adapter so Auth credentials can be monipulated
|
11
|
+
# @!attribute [rw]
|
12
|
+
attr_accessor :http_adapter
|
13
|
+
|
14
|
+
# Initializer
|
15
|
+
# @param [String] base_url
|
16
|
+
# @param [HTTPAdapter] http_adapter
|
17
|
+
def initialize(base_url, http_adapter)
|
18
|
+
@base_url = base_url
|
19
|
+
@http_adapter = http_adapter
|
20
|
+
end
|
21
|
+
|
22
|
+
# Make a GET-request to specified API-path
|
23
|
+
# @param [String] url
|
24
|
+
# API-path
|
25
|
+
# @return [hash] result
|
26
|
+
def get(url)
|
27
|
+
uri = get_full_url(url)
|
28
|
+
response = @http_adapter.get(uri)
|
29
|
+
return parseResponse(response)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Make a POST-request to specified API-path
|
33
|
+
# (Not implemented)
|
34
|
+
# @param [String] url
|
35
|
+
# API-path
|
36
|
+
# @param [Hash] data
|
37
|
+
# POST data
|
38
|
+
def post(url, data = nil)
|
39
|
+
uri = get_full_url(url)
|
40
|
+
response = @http_adapter.post(uri, data)
|
41
|
+
return parseResponse(response)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Make a PUT-request to specified API-path
|
45
|
+
# (Not implemented)
|
46
|
+
# @param [String] url
|
47
|
+
# API-path
|
48
|
+
# @param [Hash] data
|
49
|
+
# PUT-data
|
50
|
+
def put(url, data = nil)
|
51
|
+
uri = get_full_url(url)
|
52
|
+
response = @http_adapter.put(uri, data)
|
53
|
+
return parseResponse(response)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Make a DELETE-request to specified API-path
|
57
|
+
# (Not implemented)
|
58
|
+
# @param [String] url
|
59
|
+
# API-path
|
60
|
+
def delete(url)
|
61
|
+
uri = get_full_url(url)
|
62
|
+
response = @http_adapter.delete(uri)
|
63
|
+
return parseResponse(response)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# Build the full API request URL
|
69
|
+
# @param [string] url
|
70
|
+
# API-path
|
71
|
+
# @return [Mixed] uri
|
72
|
+
# URI::HTTP or URI::HTTPS
|
73
|
+
# @example
|
74
|
+
# uri = get_full_url('/gateway/1/operator/')
|
75
|
+
def get_full_url(url)
|
76
|
+
full_url = @base_url + url
|
77
|
+
return URI(URI.encode(full_url))
|
78
|
+
end
|
79
|
+
|
80
|
+
# Parse response from a request and return body content as JSON
|
81
|
+
# @param [NET::HTTP::response] response
|
82
|
+
# @return [JSON] json
|
83
|
+
def parseResponse(response)
|
84
|
+
|
85
|
+
begin
|
86
|
+
result = JSON.parse(response.body, object_class: OpenStruct)
|
87
|
+
rescue
|
88
|
+
raise CLXException, 'Unable to parse JSON response'
|
89
|
+
end
|
90
|
+
|
91
|
+
if(response.code.to_i > 399)
|
92
|
+
error_message = (result.error && result.error.message) ? result.error.message : 'No error message available'
|
93
|
+
code = (result.error && result.error.code) ? result.error.code : 'No error code available'
|
94
|
+
raise CLXAPIException.new(error_message, code), '400: Bad request' if response.code == 400
|
95
|
+
raise CLXAPIException.new(error_message, code), '401: Unauthorized' if response.code == 401
|
96
|
+
raise CLXAPIException.new(error_message, code), '403: Forbidden' if response.code == 403
|
97
|
+
raise CLXAPIException.new(error_message, code), '404: Not Found' if response.code == 404
|
98
|
+
raise CLXAPIException.new(error_message, code), 'Unknown error'
|
99
|
+
end
|
100
|
+
|
101
|
+
return result
|
102
|
+
end
|
103
|
+
|
104
|
+
#################################
|
105
|
+
# Currently unused helper methods
|
106
|
+
#################################
|
107
|
+
|
108
|
+
# # Method for validating URL's
|
109
|
+
# # @param [String] url
|
110
|
+
# # @return [Boolean]
|
111
|
+
# # @raise [CLXException]
|
112
|
+
# def valid_url?(url)
|
113
|
+
# raise CLXException, 'url can not be an empty string' if url.to_s.strip.length == 0
|
114
|
+
# # Seems to accept any string as a valid url, might need some work
|
115
|
+
# !!URI.parse(url)
|
116
|
+
# rescue URI::InvalidURIError
|
117
|
+
# raise CLXException, format('URL: "%s" is not a valid url', url)
|
118
|
+
# end
|
119
|
+
|
120
|
+
# # Encodes passed mixed variable to a URL-encoded query string
|
121
|
+
# # @param [Mixed] params
|
122
|
+
# # String, Hash or Array
|
123
|
+
# # @return [String] query_string
|
124
|
+
# # @example
|
125
|
+
# # date = 'date=2014-01-01'
|
126
|
+
# # encoded_date = url_encode(date)
|
127
|
+
# # @example
|
128
|
+
# # param_hash = {my_date: '2014-01-01', my_string: 'a string', my_int: 1}
|
129
|
+
# # encoded_params = url_encode(param_hash)
|
130
|
+
# def url_encode(params)
|
131
|
+
# return URI.encode(params) if params.instance_of? String
|
132
|
+
|
133
|
+
# if params.instance_of?(Hash) || params.instance_of?(Array)
|
134
|
+
# return '' if params.size == 0
|
135
|
+
|
136
|
+
# ret = ''
|
137
|
+
# params.each do | key, value |
|
138
|
+
# ret += format('&%s=%s', key, value)
|
139
|
+
# end
|
140
|
+
|
141
|
+
# return ret[1..-1]
|
142
|
+
# end
|
143
|
+
|
144
|
+
# return ''
|
145
|
+
# end
|
146
|
+
|
147
|
+
# # Tries to validate that parameter argument is in the correct format: String, Array or Hash
|
148
|
+
# # @param [Mixed] params
|
149
|
+
# # @return [Boolean]
|
150
|
+
# # @raise [CLXException]
|
151
|
+
# def valid_params?(params)
|
152
|
+
# if params != nil
|
153
|
+
# if params.is_a?(String) || params.is_a?(Hash) || params.is_a?(Array)
|
154
|
+
# return true
|
155
|
+
# else
|
156
|
+
# raise CLXException, 'params must be String, Hash or Array'
|
157
|
+
# end
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|