clx_api 0.1.0

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.yardopts +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +55 -0
  7. data/Rakefile +7 -0
  8. data/clx_api.gemspec +26 -0
  9. data/doc/CLX.html +305 -0
  10. data/doc/CLX/API.html +1491 -0
  11. data/doc/CLX/CLXAPIException.html +411 -0
  12. data/doc/CLX/CLXException.html +134 -0
  13. data/doc/CLX/HTTPAdapter.html +1294 -0
  14. data/doc/CLX/HTTPClient.html +1058 -0
  15. data/doc/ClxApi.html +141 -0
  16. data/doc/_index.html +161 -0
  17. data/doc/class_list.html +58 -0
  18. data/doc/css/common.css +1 -0
  19. data/doc/css/full_list.css +57 -0
  20. data/doc/css/style.css +339 -0
  21. data/doc/file.README.html +112 -0
  22. data/doc/file_list.html +60 -0
  23. data/doc/frames.html +26 -0
  24. data/doc/index.html +112 -0
  25. data/doc/js/app.js +219 -0
  26. data/doc/js/full_list.js +181 -0
  27. data/doc/js/jquery.js +4 -0
  28. data/doc/method_list.html +279 -0
  29. data/doc/top-level-namespace.html +112 -0
  30. data/examples/get_gateway_by_id.rb +16 -0
  31. data/examples/get_gateways.rb +18 -0
  32. data/examples/get_operator_by_id.rb +21 -0
  33. data/examples/get_operators.rb +23 -0
  34. data/examples/get_price_entries_by_gateway_id.rb +19 -0
  35. data/examples/get_price_entries_by_gateway_id_and_operator_id.rb +17 -0
  36. data/examples/get_price_entries_by_gateway_id_and_operator_id_and_date.rb +18 -0
  37. data/examples/readme.md +167 -0
  38. data/lib/clx_api.rb +35 -0
  39. data/lib/clx_api/api.rb +132 -0
  40. data/lib/clx_api/exceptions/clx_api_exception.rb +25 -0
  41. data/lib/clx_api/exceptions/clx_exception.rb +8 -0
  42. data/lib/clx_api/http_adapter.rb +129 -0
  43. data/lib/clx_api/http_client.rb +163 -0
  44. data/lib/clx_api/version.rb +4 -0
  45. data/test/adapter/test_adapter.rb +67 -0
  46. data/test/api_test.rb +306 -0
  47. data/test/http_adapter_test.rb +211 -0
  48. data/test/http_client_test.rb +173 -0
  49. data/test/test_helper.rb +7 -0
  50. metadata +168 -0
@@ -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,8 @@
1
+ module CLX
2
+
3
+ # CLX Generic Exception Class
4
+ class CLXException < Exception
5
+
6
+ end
7
+
8
+ 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