clx_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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