amee 4.3.2 → 4.4.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 (63) hide show
  1. data/CHANGELOG.txt +6 -0
  2. data/Gemfile +7 -1
  3. data/Rakefile +2 -0
  4. data/VERSION +1 -1
  5. data/amee.gemspec +57 -6
  6. data/amee_test_credentials.example.yml +11 -0
  7. data/cassettes/AMEE_Connection/v2/raising_unhandled_errors.yml +36 -0
  8. data/cassettes/AMEE_Connection/v3/retries/502.yml +36 -0
  9. data/cassettes/AMEE_Connection/v3/retries/503.yml +36 -0
  10. data/cassettes/AMEE_Connection/v3/retries/504.yml +36 -0
  11. data/cassettes/AMEE_Connection/v3/retries/AMEE_TimeOut.yml +36 -0
  12. data/cassettes/AMEE_Connection/v3/should_be_able_to_get_from_meta_server.yml +30 -0
  13. data/cassettes/AMEE_Connection/v3/should_be_able_to_handle_failed_gets_from_meta_server.yml +30 -0
  14. data/cassettes/AMEE_Connection/v3/should_be_able_to_post_to_meta_server.yml +59 -0
  15. data/cassettes/AMEE_Connection/v3/should_have_a_connection_to_meta_server.yml +36 -0
  16. data/cassettes/AMEE_Connection/v3/should_login_and_know_the_path_to_the_server.yml +36 -0
  17. data/cassettes/AMEE_Connection_Caching_Off/authenticating.yml +36 -0
  18. data/cassettes/AMEE_Connection_Caching_Off/first_request.yml +40 -0
  19. data/cassettes/AMEE_Connection_Caching_Off/second_request.yml +40 -0
  20. data/cassettes/AMEE_Connection_Caching_On/authenticating.yml +36 -0
  21. data/cassettes/AMEE_Connection_Caching_On/first_request.yml +40 -0
  22. data/cassettes/AMEE_Connection_Caching_clear_all/second_request.yml +40 -0
  23. data/cassettes/AMEE_Connection_Caching_clear_manually/second_request.yml +40 -0
  24. data/cassettes/AMEE_Connection_Caching_further_down_tree/second_request.yml +79 -0
  25. data/cassettes/AMEE_Connection_with_authentication/handling_404s.yml +69 -0
  26. data/cassettes/AMEE_Connection_with_authentication/hitting_private_urls.yml +75 -0
  27. data/cassettes/AMEE_Connection_with_authentication/raising_errors_if_permission_denied.yml +69 -0
  28. data/cassettes/AMEE_Connection_with_authentication/should_re-authenticate_and_refresh_authtoken_when_authtoken_expires.yml +104 -0
  29. data/cassettes/AMEE_Connection_with_authentication/should_refresh_authtoken_when_authtoken_is_changed.yml +114 -0
  30. data/cassettes/AMEE_Connection_with_authentication/using_a_v1_key.yml +71 -0
  31. data/cassettes/AMEE_Connection_with_authentication/using_a_v2_key/detects_the_API_version_for_JSON.yml +36 -0
  32. data/cassettes/AMEE_Connection_with_authentication/using_a_v2_key/detects_the_API_version_for_XML.yml +36 -0
  33. data/cassettes/AMEE_Connection_with_authentication_doing_write-requests.yml +75 -0
  34. data/cassettes/AMEE_Connection_with_authentication_doing_write-requests/working_with_an_existing_profile/deleting_existing_items.yml +108 -0
  35. data/cassettes/AMEE_Connection_with_authentication_doing_write-requests/working_with_an_existing_profile/sending_updates_to_existing_items.yml +108 -0
  36. data/cassettes/AMEE_Connection_with_bad_authentication_information/hitting_a_private_url.yml +29 -0
  37. data/cassettes/AMEE_Connection_with_bad_authentication_information/hitting_a_public_url.yml +32 -0
  38. data/cassettes/AMEE_Connection_with_incorrect_server_name.yml +16 -0
  39. data/cassettes/AMEE_Connection_with_retry_enabled.yml +36 -0
  40. data/lib/amee/connection.rb +234 -110
  41. data/lib/amee/data_category.rb +2 -2
  42. data/lib/amee/data_item.rb +45 -2
  43. data/lib/amee/data_item_value.rb +1 -1
  44. data/lib/amee/exceptions.rb +5 -2
  45. data/lib/amee/parse_helper.rb +2 -0
  46. data/lib/amee/profile_item.rb +6 -2
  47. data/lib/amee/v3/connection.rb +77 -70
  48. data/lib/amee/v3/item_value_definition.rb +1 -1
  49. data/lib/amee/v3/return_value_definition.rb +1 -1
  50. data/spec/cache_spec.rb +107 -48
  51. data/spec/connection_spec.rb +224 -183
  52. data/spec/data_item_spec.rb +12 -0
  53. data/spec/data_item_value_history_spec.rb +4 -4
  54. data/spec/data_item_value_spec.rb +2 -2
  55. data/spec/fixtures/AD63A83B4D41.json +1 -1
  56. data/spec/fixtures/AD63A83B4D41.xml +1 -1
  57. data/spec/profile_item_spec.rb +14 -10
  58. data/spec/spec_helper.rb +29 -0
  59. data/spec/v3/connection_spec.rb +77 -65
  60. data/spec/v3/item_value_definition_spec.rb +1 -0
  61. data/spec/v3/return_value_definition_spec.rb +1 -1
  62. metadata +140 -24
  63. data/Gemfile.lock +0 -63
@@ -1,8 +1,16 @@
1
1
  # Copyright (C) 2008-2011 AMEE UK Ltd. - http://www.amee.com
2
2
  # Released as Open Source Software under the BSD 3-Clause license. See LICENSE.txt for details.
3
3
 
4
- require 'net/http'
5
- require 'net/https'
4
+ require 'typhoeus'
5
+ require 'json'
6
+ require 'log_buddy'
7
+
8
+
9
+
10
+ # LogBuddy.init :log_to_stdout => false
11
+ LogBuddy.init :disabled => true
12
+ # Set this to true to output curl debug messages in development
13
+ DEBUG = false
6
14
 
7
15
  module AMEE
8
16
  class Connection
@@ -13,6 +21,7 @@ module AMEE
13
21
  unless options.is_a?(Hash)
14
22
  raise AMEE::ArgumentError.new("Fourth argument must be a hash of options!")
15
23
  end
24
+
16
25
  @server = server
17
26
  @username = username
18
27
  @password = password
@@ -25,6 +34,9 @@ module AMEE
25
34
  if !valid?
26
35
  raise "You must supply connection details - server, username and password are all required!"
27
36
  end
37
+
38
+ # Working with caching
39
+
28
40
  # Handle old option
29
41
  if options[:enable_caching]
30
42
  Kernel.warn '[DEPRECATED] :enable_caching => true is deprecated. Use :cache => :memory_store instead'
@@ -33,7 +45,7 @@ module AMEE
33
45
  # Create cache store
34
46
  if options[:cache] &&
35
47
  (options[:cache_store].class.name == "ActiveSupport::Cache::MemCacheStore" ||
36
- options[:cache].to_sym == :mem_cache_store)
48
+ options[:cache].to_sym == :mem_cache_store)
37
49
  raise 'ActiveSupport::Cache::MemCacheStore is not supported, as it doesn\'t allow regexp expiry'
38
50
  end
39
51
  if options[:cache_store].is_a?(ActiveSupport::Cache::Store)
@@ -46,18 +58,22 @@ module AMEE
46
58
  @cache = ActiveSupport::Cache.lookup_store(options[:cache].to_sym)
47
59
  end
48
60
  end
49
- # Make connection to server
50
- @http = Net::HTTP.new(@server, @port)
61
+
62
+ # set up hash to pass to builder block
63
+ @params = {
64
+ :ssl => @ssl,
65
+ :params => {},
66
+ :headers => {}
67
+ }
68
+
51
69
  if @ssl == true
52
- @http.use_ssl = true
70
+ @params[:ssl] = true
53
71
  if File.exists? RootCA
54
- @http.ca_file = RootCA
55
- @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
56
- @http.verify_depth = 5
72
+ @params[:ca_file] = RootCA
57
73
  end
58
74
  end
75
+
59
76
  self.timeout = options[:timeout] || 60
60
- @http.set_debug_output($stdout) if options[:enable_debug]
61
77
  @debug = options[:enable_debug]
62
78
  end
63
79
 
@@ -66,13 +82,14 @@ module AMEE
66
82
  attr_reader :username
67
83
  attr_reader :password
68
84
  attr_reader :retries
85
+ attr_accessor :auth_token #Only used in tests really
69
86
 
70
87
  def timeout
71
- @http.read_timeout
88
+ @params[:timeout]
72
89
  end
73
90
 
74
91
  def timeout=(t)
75
- @http.open_timeout = @http.read_timeout = t
92
+ @params[:open_timeout] = @params[:timeout] = t
76
93
  end
77
94
 
78
95
  def version
@@ -84,99 +101,142 @@ module AMEE
84
101
  @username && @password && @server
85
102
  end
86
103
 
104
+ # check if we have a valid authentication token
87
105
  def authenticated?
88
- !@auth_token.nil?
106
+ @auth_token =~ /^.*$/
89
107
  end
90
108
 
109
+ # GET data from the API, passing in a hash of parameters
91
110
  def get(path, data = {})
92
111
  # Allow format override
93
112
  format = data.delete(:format) || @format
94
- # Create URL parameters
95
- params = []
96
- data.each_pair do |key, value|
97
- params << "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}"
98
- end
99
- if params.size > 0
100
- path += "?#{params.join('&')}"
101
- end
102
- # Send request
103
- cache(path) { do_request(Net::HTTP::Get.new(path), format) }
113
+ # Add parameters to URL query string
114
+ get_params = {
115
+ :method => "get",
116
+ :verbose => DEBUG
117
+ }
118
+ get_params[:params] = data unless data.empty?
119
+ # Create GET request
120
+ get = Typhoeus::Request.new("#{protocol}#{@server}#{path}", get_params)
121
+ # Send request
122
+ do_request(get, format, :cache => true)
104
123
  end
105
124
 
125
+ # POST to the AMEE API, passing in a hash of values
106
126
  def post(path, data = {})
107
127
  # Allow format override
108
128
  format = data.delete(:format) || @format
109
129
  # Clear cache
110
130
  expire_matching "#{raw_path(path)}.*"
131
+ # Extract return unit params
132
+ query_params = {}
133
+ query_params[:returnUnit] = data.delete(:returnUnit) if data[:returnUnit]
134
+ query_params[:returnPerUnit] = data.delete(:returnPerUnit) if data[:returnPerUnit]
111
135
  # Create POST request
112
- post = Net::HTTP::Post.new(path)
113
- body = []
114
- data.each_pair do |key, value|
115
- body << "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}"
116
- end
117
- post.body = body.join '&'
136
+ post_params = {
137
+ :verbose => DEBUG,
138
+ :method => "post",
139
+ :body => form_encode(data)
140
+ }
141
+ post_params[:params] = query_params unless query_params.empty?
142
+ post = Typhoeus::Request.new("#{protocol}#{@server}#{path}", post_params)
118
143
  # Send request
119
- do_request(post, format)
144
+ do_request(post, format)
120
145
  end
121
146
 
147
+ # POST to the AMEE API, passing in a string of data
122
148
  def raw_post(path, body, options = {})
123
149
  # Allow format override
124
150
  format = options.delete(:format) || @format
125
151
  # Clear cache
126
152
  expire_matching "#{raw_path(path)}.*"
127
153
  # Create POST request
128
- post = Net::HTTP::Post.new(path)
129
- post['Content-type'] = options[:content_type] || content_type(format)
130
- post.body = body
154
+ post = Typhoeus::Request.new("#{protocol}#{@server}#{path}",
155
+ :verbose => DEBUG,
156
+ :method => "post",
157
+ :body => body,
158
+ :headers => { :'Content-type' => options[:content_type] || content_type(format) }
159
+ )
160
+
131
161
  # Send request
132
162
  do_request(post, format)
133
163
  end
134
164
 
165
+ # PUT to the AMEE API, passing in a hash of data
135
166
  def put(path, data = {})
136
167
  # Allow format override
137
168
  format = data.delete(:format) || @format
138
169
  # Clear cache
139
170
  expire_matching "#{parent_path(path)}.*"
171
+ # Extract return unit params
172
+ query_params = {}
173
+ query_params[:returnUnit] = data.delete(:returnUnit) if data[:returnUnit]
174
+ query_params[:returnPerUnit] = data.delete(:returnPerUnit) if data[:returnPerUnit]
140
175
  # Create PUT request
141
- put = Net::HTTP::Put.new(path)
142
- body = []
143
- data.each_pair do |key, value|
144
- body << "#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}"
145
- end
146
- put.body = body.join '&'
147
- # Send request
176
+ put_params = {
177
+ :verbose => DEBUG,
178
+ :method => "put",
179
+ :body => form_encode(data)
180
+ }
181
+ put_params[:params] = query_params unless query_params.empty?
182
+ put = Typhoeus::Request.new("#{protocol}#{@server}#{path}", put_params)
183
+ # Send request
148
184
  do_request(put, format)
149
185
  end
150
186
 
187
+ # PUT to the AMEE API, passing in a string of data
151
188
  def raw_put(path, body, options = {})
152
189
  # Allow format override
153
190
  format = options.delete(:format) || @format
154
191
  # Clear cache
155
192
  expire_matching "#{parent_path(path)}.*"
156
193
  # Create PUT request
157
- put = Net::HTTP::Put.new(path)
158
- put['Content-type'] = options[:content_type] || content_type(format)
159
- put.body = body
194
+ put = Typhoeus::Request.new("#{protocol}#{@server}#{path}",
195
+ :verbose => DEBUG,
196
+ :method => "put",
197
+ :body => body,
198
+ :headers => { :'Content-type' => options[:content_type] || content_type(format) }
199
+ )
160
200
  # Send request
161
201
  do_request(put, format)
162
202
  end
163
203
 
164
204
  def delete(path)
205
+ # Clear cache
165
206
  expire_matching "#{parent_path(path)}.*"
166
207
  # Create DELETE request
167
- delete = Net::HTTP::Delete.new(path)
168
- # Send request
208
+ delete = Typhoeus::Request.new("#{protocol}#{@server}#{path}",
209
+ :verbose => DEBUG,
210
+ :method => "delete"
211
+ )
212
+ # Send request
169
213
  do_request(delete)
170
214
  end
171
215
 
216
+ # Post to the sign in resource on the API, so that all future
217
+ # requests are signed
172
218
  def authenticate
173
- response = nil
174
- post = Net::HTTP::Post.new("/auth/signIn")
175
- post.body = "username=#{@username}&password=#{@password}"
176
- post['Accept'] = content_type(:xml)
177
- post['X-AMEE-Source'] = @amee_source if @amee_source
178
- response = @http.request(post)
179
- @auth_token = response['authToken']
219
+ # :x_amee_source = "X-AMEE-Source".to_sym
220
+ request = Typhoeus::Request.new("#{protocol}#{@server}/auth/signIn",
221
+ :method => "post",
222
+ :verbose => DEBUG,
223
+ :headers => {
224
+ :Accept => content_type(:xml),
225
+ },
226
+ :body => form_encode(:username=>@username, :password=>@password)
227
+ )
228
+
229
+ hydra.queue(request)
230
+ hydra.run
231
+ response = request.response
232
+
233
+ @auth_token = response.headers_hash['AuthToken']
234
+ d {request.url}
235
+ d {response.code}
236
+ d {@auth_token}
237
+
238
+ connection_failed if response.code == 0
239
+
180
240
  unless authenticated?
181
241
  raise AMEE::AuthFailed.new("Authentication failed. Please check your username and password. (tried #{@username},#{@password})")
182
242
  end
@@ -192,6 +252,22 @@ module AMEE
192
252
 
193
253
  protected
194
254
 
255
+ def protocol
256
+ @ssl == true ? 'https://' : 'http://'
257
+ end
258
+
259
+ # Encode a hash into a application/x-www-form-urlencoded format
260
+ def form_encode(data)
261
+ data.map { |datum|
262
+ "#{CGI::escape(datum[0].to_s)}=#{CGI::escape(datum[1].to_s)}"
263
+ }.join('&')
264
+ end
265
+
266
+ ## set up the hydra for running http requests. Increase concurrency as needed
267
+ def hydra
268
+ @hydra ||= Typhoeus::Hydra.new(:max_concurrency => 1)
269
+ end
270
+
195
271
  def content_type(format = @format)
196
272
  case format
197
273
  when :xml
@@ -204,66 +280,104 @@ module AMEE
204
280
  end
205
281
 
206
282
  def redirect?(response)
207
- response.code == '301' || response.code == '302'
283
+ response.code == 301 || response.code == 302
208
284
  end
209
-
285
+
286
+ def connection_failed
287
+ raise AMEE::ConnectionFailed.new("Connection failed. Check server name or network connection.")
288
+ end
289
+
290
+ # run each request through some basic error checking, and
291
+ # if needed log requests
210
292
  def response_ok?(response, request)
211
- case response.code
212
- when '200', '201'
213
- return true
214
- when '404'
215
- raise AMEE::NotFound.new("The URL was not found on the server.\nRequest: #{request.method} #{request.path}")
216
- when '403'
217
- raise AMEE::PermissionDenied.new("You do not have permission to perform the requested operation.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}")
218
- when '401'
219
- authenticate
220
- return false
221
- when '400'
222
- if response.body.include? "would have resulted in a duplicate resource being created"
223
- raise AMEE::DuplicateResource.new("The specified resource already exists. This is most often caused by creating an item that overlaps another in time.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}")
224
- else
225
- raise AMEE::BadRequest.new("Bad request. This is probably due to malformed input data.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}")
226
- end
293
+
294
+ # first allow for debugging
295
+ d {request.object_id}
296
+ d {request}
297
+ d {response.object_id}
298
+ d {response.code}
299
+ d {response.headers_hash}
300
+ d {response.body}
301
+
302
+ case response.code.to_i
303
+
304
+ when 502, 503, 504
305
+ raise AMEE::ConnectionFailed.new("A connection error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method.upcase} #{request.url.gsub(request.host, '')}")
306
+ when 408
307
+ raise AMEE::TimeOut.new("Request timed out.")
308
+ when 404
309
+ raise AMEE::NotFound.new("The URL was not found on the server.\nRequest: #{request.method.upcase} #{request.url.gsub(request.host, '')}")
310
+ when 403
311
+ raise AMEE::PermissionDenied.new("You do not have permission to perform the requested operation.\nRequest: #{request.method.upcase} #{request.url.gsub(request.host, '')}\n#{request.body}\Response: #{response.body}")
312
+ when 401
313
+ authenticate
314
+ return false
315
+ when 400
316
+ if response.body.include? "would have resulted in a duplicate resource being created"
317
+ raise AMEE::DuplicateResource.new("The specified resource already exists. This is most often caused by creating an item that overlaps another in time.\nRequest: #{request.method.upcase} #{request.url.gsub(request.host, '')}\n#{request.body}\Response: #{response.body}")
318
+ else
319
+ raise AMEE::BadRequest.new("Bad request. This is probably due to malformed input data.\nRequest: #{request.method.upcase} #{request.url.gsub(request.host, '')}\n#{request.body}\Response: #{response.body}")
320
+ end
321
+ when 200, 201, 204
322
+ return response
323
+ when 0
324
+ connection_failed
227
325
  end
228
- raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method} #{request.path}\n#{request.body}\Response: #{response.body}")
326
+ # If we get here, something unhandled has happened, so raise an unknown error.
327
+ raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method.upcase} #{request.url}\n#{request.body}\Response: #{response.body}")
229
328
  end
230
329
 
231
- def do_request(request, format = @format)
232
- # Open HTTP connection
233
- @http.start
234
- begin
235
- # Set auth token in cookie (and header just in case someone's stripping cookies)
236
- request['Cookie'] = "authToken=#{@auth_token}"
237
- request['authToken'] = @auth_token
238
- # Do request
239
- timethen=Time.now
240
- response = send_request(@http, request, format)
241
- Logger.log.debug("Requesting #{request.class} at #{request.path} with #{request.body} in format #{format}, taking #{(Time.now-timethen)*1000} miliseconds")
242
- end while !response_ok?(response, request)
243
- # Return response
244
- return response
245
- rescue SocketError
246
- raise AMEE::ConnectionFailed.new("Connection failed. Check server name or network connection.")
247
- ensure
248
- # Close HTTP connection
249
- @http.finish if @http.started?
250
- end
330
+ # Wrapper for sending requests through to the API.
331
+ # Takes care of making sure requests authenticated, and
332
+ # if set, attempts to retry a number of times set when
333
+ # initialising the class
334
+ def do_request(request, format = @format, options = {})
335
+
336
+ # Is this a v3 request?
337
+ v3_request = request.url.include?("/#{v3_hostname}/")
251
338
 
252
- def send_request(connection, request, format = @format)
253
- # Set accept header
254
- request['Accept'] = content_type(format)
339
+ # make sure we have our auth token before we start
340
+ # any v1 or v2 requests
341
+ if !@auth_token && !v3_request
342
+ d "Authenticating first before we hit #{request.url}"
343
+ authenticate
344
+ end
345
+
346
+ request.headers['Accept'] = content_type(format)
255
347
  # Set AMEE source header if set
256
- request['X-AMEE-Source'] = @amee_source if @amee_source
257
- # Do the business
348
+ request.headers['X-AMEE-Source'] = @amee_source if @amee_source
349
+
350
+ # path+query string only (split with an int limits the number of splits)
351
+ path_and_query = '/' + request.url.split('/', 4)[3]
352
+
353
+ if options[:cache]
354
+ # Get response with caching
355
+ response = cache(path_and_query) { run_request(request, :xml) }
356
+ else
357
+ response = run_request(request, :xml)
358
+ end
359
+ response
360
+ end
361
+
362
+ # run request. Extracted from do_request to make
363
+ # cache code simpler
364
+ def run_request(request, format)
365
+ # Is this a v3 request?
366
+ v3_request = request.url.include?("/#{v3_hostname}/")
367
+ # Execute with retries
258
368
  retries = [1] * @retries
259
- begin
260
- response = connection.request(request)
261
- # 500-series errors fail early
262
- if ['502', '503', '504'].include? response.code
263
- raise AMEE::ConnectionFailed.new("A connection error occurred while talking to AMEE: HTTP response code #{response.code}.\nRequest: #{request.method} #{request.path}")
264
- end
265
- rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
266
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, AMEE::ConnectionFailed => e
369
+ begin
370
+ begin
371
+ d "Queuing the request for #{request.url}"
372
+ add_authentication_to(request) if @auth_token && !v3_request
373
+ hydra.queue request
374
+ hydra.run
375
+ # Return response if OK
376
+ end while !response_ok?(request.response, request)
377
+ # Store updated authToken
378
+ @auth_token = request.response.headers_hash['AuthToken']
379
+ return request.response
380
+ rescue AMEE::ConnectionFailed, AMEE::TimeOut => e
267
381
  if delay = retries.shift
268
382
  sleep delay
269
383
  retry
@@ -271,17 +385,27 @@ module AMEE
271
385
  raise
272
386
  end
273
387
  end
274
- # Done
275
- response
388
+ end
389
+
390
+ # Take an existing request, and add authentication
391
+ # may no longer be needed now that we authenticate before
392
+ # making a request anyway
393
+ def add_authentication_to(request=nil)
394
+ if @auth_token
395
+ request.headers['Cookie'] = "AuthToken=#{@auth_token}"
396
+ request.headers['AuthToken'] = @auth_token
397
+ else
398
+ raise "The connection can't authenticate. Check if the auth_token is being set by the server"
399
+ end
276
400
  end
277
401
 
278
402
  def cache(path, &block)
279
403
  key = cache_key(path)
280
404
  if @cache && @cache.exist?(key)
281
- puts "CACHE HIT on #{key}" if @debug
405
+ d "CACHE HIT on #{key}" if @debug
282
406
  return @cache.read(key)
283
407
  end
284
- puts "CACHE MISS on #{key}" if @debug
408
+ d "CACHE MISS on #{key}" if @debug
285
409
  data = block.call
286
410
  @cache.write(key, data) if @cache
287
411
  return data
@@ -298,8 +422,8 @@ module AMEE
298
422
  def cache_key(path)
299
423
  # We have to make sure cache keys don't get too long for the filesystem,
300
424
  # so we cut them off if they're too long and add a digest for uniqueness.
301
- newpath = @server + path.gsub(/[^0-9a-z\/]/i, '').gsub(/\//i, '_')
302
- newpath = (newpath.length < 250) ? newpath : newpath.first(218)+Digest::MD5.hexdigest(newpath)
425
+ key = @server + path.gsub(/[^0-9a-z\/]/i, '').gsub(/\//i, '_')
426
+ key = (key.length < 250) ? key : key.first(218)+Digest::MD5.hexdigest(key)
303
427
  end
304
428
 
305
429
  public