blix-rest 0.9.3 → 0.11.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.
- checksums.yaml +4 -4
- data/README.md +484 -503
- data/lib/blix/rest/cache.rb +1 -29
- data/lib/blix/rest/controller.rb +80 -0
- data/lib/blix/rest/memory_cache.rb +30 -0
- data/lib/blix/rest/request_mapper.rb +36 -28
- data/lib/blix/rest/response.rb +10 -0
- data/lib/blix/rest/server.rb +57 -51
- data/lib/blix/rest/session.rb +8 -3
- data/lib/blix/rest/version.rb +1 -1
- data/lib/blix/rest.rb +7 -0
- data/lib/blix/utils/misc.rb +39 -0
- metadata +5 -9
- data/lib/blix/rest/cucumber/hooks.rb +0 -5
- data/lib/blix/rest/cucumber/request_steps.rb +0 -207
- data/lib/blix/rest/cucumber/resource_steps.rb +0 -28
- data/lib/blix/rest/cucumber/world.rb +0 -274
- data/lib/blix/rest/cucumber.rb +0 -8
data/lib/blix/rest/cache.rb
CHANGED
@@ -48,32 +48,4 @@ module Blix::Rest
|
|
48
48
|
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
class MemoryCache < Cache
|
53
|
-
|
54
|
-
def cache
|
55
|
-
@cache ||= {}
|
56
|
-
end
|
57
|
-
|
58
|
-
def get(key)
|
59
|
-
cache[key]
|
60
|
-
end
|
61
|
-
|
62
|
-
def set(key, data)
|
63
|
-
cache[key] = data
|
64
|
-
end
|
65
|
-
|
66
|
-
def clear
|
67
|
-
cache.clear
|
68
|
-
end
|
69
|
-
|
70
|
-
def key?(key)
|
71
|
-
cache.key?(key)
|
72
|
-
end
|
73
|
-
|
74
|
-
def delete(key)
|
75
|
-
cache.delete(key)
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|
51
|
+
end
|
data/lib/blix/rest/controller.rb
CHANGED
@@ -241,6 +241,35 @@ module Blix::Rest
|
|
241
241
|
[login, password]
|
242
242
|
end
|
243
243
|
|
244
|
+
def throttle_basic_auth(realm=nil, options={})
|
245
|
+
login, password = get_basic_auth(realm)
|
246
|
+
# check that the waiting time has expired
|
247
|
+
info = self.class.basic_store.get_hash(login) || {}
|
248
|
+
fail_count = info['fail_count'].to_i
|
249
|
+
if fail_count > 3
|
250
|
+
now = Time.now
|
251
|
+
fail_time = info['fail_time']
|
252
|
+
delta = 60 # one minute
|
253
|
+
delta = 60*10 if fail_count > 10 # 10 minutes
|
254
|
+
delta = 60*60*24 if fail_count > 100 # one day
|
255
|
+
if (fail_time + delta) > now
|
256
|
+
raise Blix::Rest::AuthorizationError.new("try again after #{(fail_time + delta)}", realm)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
if yield(login,password)
|
260
|
+
# auth success - set error count to 0
|
261
|
+
info['fail_count'] = 0
|
262
|
+
self.class.basic_store.store_hash(login, info)
|
263
|
+
true
|
264
|
+
else
|
265
|
+
# auth failure - increment error count / set error time
|
266
|
+
info['fail_count'] = fail_count + 1
|
267
|
+
info['fail_time'] = Time.now
|
268
|
+
self.class.basic_store.store_hash(login, info)
|
269
|
+
raise Blix::Rest::AuthorizationError.new("invalid login or password", realm)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
244
273
|
# set the cors headers
|
245
274
|
def set_accept_cors(opts={})
|
246
275
|
origin = opts[:origin] || env['HTTP_ORIGIN'] || '*'
|
@@ -371,6 +400,57 @@ module Blix::Rest
|
|
371
400
|
value
|
372
401
|
end
|
373
402
|
|
403
|
+
# only allow so many exceptions in a given time.
|
404
|
+
# the delay applies to
|
405
|
+
# - 3x failure
|
406
|
+
# - 10x failure
|
407
|
+
# - 100x failure
|
408
|
+
|
409
|
+
# options:
|
410
|
+
# :prefix # the prefix to use in the cache
|
411
|
+
# :cache # a cache object ( server_cache )
|
412
|
+
# :times # array of delays in seconds to apply default: [60, 600, 86400]
|
413
|
+
#
|
414
|
+
def rate_limit(name, options = {})
|
415
|
+
# check that the waiting time has expired
|
416
|
+
cache = options[:cache] || server_cache()
|
417
|
+
prefix = options[:prefix] || 'rlimit'
|
418
|
+
key = "#{prefix}|#{name}"
|
419
|
+
info = cache.get(key) || {}
|
420
|
+
fail_count = info['fc'].to_i
|
421
|
+
times = options[:times] || []
|
422
|
+
if fail_count > 2
|
423
|
+
now = Time.now
|
424
|
+
fail_time = info['ft']
|
425
|
+
delta = times[0] || 60 # one minute
|
426
|
+
delta = times[1] || 60 * 10 if fail_count > 10 # 10 minutes
|
427
|
+
delta = times[2] || 60 * 60 * 24 if fail_count > 100 # one day
|
428
|
+
ltime = fail_time + delta
|
429
|
+
if ltime > now
|
430
|
+
raise RateError, ltime.to_s
|
431
|
+
end
|
432
|
+
end
|
433
|
+
exception = nil
|
434
|
+
result = begin
|
435
|
+
yield(key)
|
436
|
+
rescue Exception => e
|
437
|
+
exception = e
|
438
|
+
nil
|
439
|
+
end
|
440
|
+
if exception
|
441
|
+
# auth failure - increment error count / set error time
|
442
|
+
info['fc'] = fail_count + 1
|
443
|
+
info['ft'] = Time.now
|
444
|
+
cache.set(key, info)
|
445
|
+
raise exception
|
446
|
+
else
|
447
|
+
# auth success - set error count to 0
|
448
|
+
info['fc'] = 0
|
449
|
+
cache.set(key, info)
|
450
|
+
result
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
374
454
|
# manage session handling --------------------------------------------------
|
375
455
|
# setup the session and retrieve the session_id
|
376
456
|
# this id can be used to retrieve and data associated
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Blix::Rest
|
2
|
+
# implement cache as a simple ruby hash
|
3
|
+
class MemoryCache < Cache
|
4
|
+
|
5
|
+
def cache
|
6
|
+
@cache ||= {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def get(key)
|
10
|
+
cache[key]
|
11
|
+
end
|
12
|
+
|
13
|
+
def set(key, data)
|
14
|
+
cache[key] = data
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear
|
18
|
+
cache.clear
|
19
|
+
end
|
20
|
+
|
21
|
+
def key?(key)
|
22
|
+
cache.key?(key)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete(key)
|
26
|
+
cache.delete(key)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -14,8 +14,9 @@ module Blix::Rest
|
|
14
14
|
PATH_SEP = '/'
|
15
15
|
STAR_PLACEHOLDER = '*'
|
16
16
|
|
17
|
-
# the
|
18
|
-
|
17
|
+
# the TableNode class is used to build a tree structure to
|
18
|
+
# represent the routes.
|
19
|
+
#
|
19
20
|
class TableNode
|
20
21
|
|
21
22
|
attr_accessor :blk
|
@@ -27,19 +28,7 @@ module Blix::Rest
|
|
27
28
|
|
28
29
|
def initialize(name)
|
29
30
|
@children = {}
|
30
|
-
|
31
|
-
@parameter = name[1..-1].to_sym
|
32
|
-
@value = WILD_PLACEHOLDER
|
33
|
-
elsif name[0, 1] == '*'
|
34
|
-
@parameter = if name[1..-1].empty?
|
35
|
-
:wildpath
|
36
|
-
else
|
37
|
-
name[1..-1].to_sym
|
38
|
-
end
|
39
|
-
@value = STAR_PLACEHOLDER
|
40
|
-
else
|
41
|
-
@value = name
|
42
|
-
end
|
31
|
+
@value, @parameter = parse_name(name)
|
43
32
|
@extract_format = true
|
44
33
|
end
|
45
34
|
|
@@ -51,6 +40,19 @@ module Blix::Rest
|
|
51
40
|
@children[k] = v
|
52
41
|
end
|
53
42
|
|
43
|
+
private
|
44
|
+
|
45
|
+
def parse_name(name)
|
46
|
+
case name[0]
|
47
|
+
when ':'
|
48
|
+
[WILD_PLACEHOLDER, name[1..].to_sym]
|
49
|
+
when '*'
|
50
|
+
[STAR_PLACEHOLDER, name[1..].empty? ? :wildpath : name[1..].to_sym]
|
51
|
+
else
|
52
|
+
[name, nil]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
54
56
|
end
|
55
57
|
|
56
58
|
class << self
|
@@ -58,18 +60,20 @@ module Blix::Rest
|
|
58
60
|
# the root always starts with '/' and finishes with '/'
|
59
61
|
def set_path_root(root)
|
60
62
|
root = root.to_s
|
61
|
-
root = '/' + root
|
62
|
-
root += '/'
|
63
|
+
root = '/' + root unless root.start_with?('/')
|
64
|
+
root += '/' unless root.end_with?('/')
|
63
65
|
@path_root = root
|
64
66
|
@path_root_length = @path_root.length - 1
|
65
67
|
end
|
66
68
|
|
69
|
+
# if the path_root has not been set then return '/'
|
67
70
|
def path_root
|
68
71
|
@path_root || '/'
|
69
72
|
end
|
70
73
|
|
74
|
+
# return 0 if the path_root has not been set
|
71
75
|
def path_root_length
|
72
|
-
@path_root_length
|
76
|
+
@path_root_length || 0
|
73
77
|
end
|
74
78
|
|
75
79
|
def full_path(path)
|
@@ -91,7 +95,7 @@ module Blix::Rest
|
|
91
95
|
|
92
96
|
def table
|
93
97
|
# compile the table in one thread only.
|
94
|
-
@table
|
98
|
+
@table || @@mutex.synchronize{@table ||= compile}
|
95
99
|
end
|
96
100
|
|
97
101
|
def dump
|
@@ -325,21 +329,25 @@ module Blix::Rest
|
|
325
329
|
end
|
326
330
|
str
|
327
331
|
end
|
328
|
-
|
329
332
|
end
|
330
333
|
|
331
334
|
end # RequestMapper
|
332
335
|
|
333
|
-
|
334
|
-
RequestMapper.set_path_root(*args)
|
335
|
-
end
|
336
|
+
class << self
|
336
337
|
|
337
|
-
def self.path_root
|
338
|
-
RequestMapper.path_root
|
339
|
-
end
|
340
338
|
|
341
|
-
|
342
|
-
|
339
|
+
def set_path_root(*args)
|
340
|
+
RequestMapper.set_path_root(*args)
|
341
|
+
end
|
342
|
+
|
343
|
+
def path_root
|
344
|
+
RequestMapper.path_root
|
345
|
+
end
|
346
|
+
|
347
|
+
def full_path(path)
|
348
|
+
RequestMapper.full_path(path)
|
349
|
+
end
|
350
|
+
|
343
351
|
end
|
344
352
|
|
345
353
|
RequestMapper.set_path_root(ENV['BLIX_REST_ROOT']) if ENV['BLIX_REST_ROOT']
|
data/lib/blix/rest/response.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# pass a response object to the controller to set
|
2
2
|
# header status and content.
|
3
3
|
|
4
|
+
unless defined?(Rack::Headers)
|
5
|
+
class Rack::Headers < Hash; end
|
6
|
+
end
|
7
|
+
|
4
8
|
module Blix::Rest
|
5
9
|
|
6
10
|
|
@@ -22,5 +26,11 @@ module Blix::Rest
|
|
22
26
|
@headers.merge!(headers) if headers
|
23
27
|
end
|
24
28
|
|
29
|
+
def set_options(options={})
|
30
|
+
@status = options[:status].to_i if options[:status]
|
31
|
+
@headers.merge!(options[:headers]) if options[:headers]
|
32
|
+
@headers['content-type'] = options[:content_type] if options[:content_type]
|
33
|
+
end
|
34
|
+
|
25
35
|
end
|
26
36
|
end
|
data/lib/blix/rest/server.rb
CHANGED
@@ -3,18 +3,11 @@
|
|
3
3
|
module Blix::Rest
|
4
4
|
class Server
|
5
5
|
|
6
|
-
def initialize(
|
6
|
+
def initialize(options = {})
|
7
7
|
@_parsers = {}
|
8
8
|
@_mime_types = {}
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
register_parser('html', HtmlFormatParser.new)
|
13
|
-
register_parser('json', JsonFormatParser.new)
|
14
|
-
register_parser('xml', XmlFormatParser.new)
|
15
|
-
register_parser('raw', RawFormatParser.new)
|
16
|
-
extract_parsers_from_options(opts)
|
17
|
-
@_options = opts
|
9
|
+
@_options = options
|
10
|
+
setup_parsers(options)
|
18
11
|
end
|
19
12
|
|
20
13
|
# options passed to the server
|
@@ -22,7 +15,6 @@ module Blix::Rest
|
|
22
15
|
@_options
|
23
16
|
end
|
24
17
|
|
25
|
-
|
26
18
|
# the object serving as a cache
|
27
19
|
def _cache
|
28
20
|
@_cache ||= begin
|
@@ -36,16 +28,15 @@ module Blix::Rest
|
|
36
28
|
end
|
37
29
|
end
|
38
30
|
|
39
|
-
def extract_parsers_from_options(
|
40
|
-
|
41
|
-
next unless k =~ /^(\w*)_parser
|
31
|
+
def extract_parsers_from_options(options)
|
32
|
+
options.each do |k, v|
|
33
|
+
next unless k =~ /^(\w*)_parser$/
|
42
34
|
|
43
35
|
format = Regexp.last_match(1)
|
44
36
|
parser = v
|
45
37
|
register_parser(format, parser)
|
46
38
|
end
|
47
39
|
end
|
48
|
-
|
49
40
|
def set_custom_headers(format, headers)
|
50
41
|
parser = get_parser(format)
|
51
42
|
raise "parser not found for custom headers format=>#{format}" unless parser
|
@@ -61,7 +52,7 @@ module Blix::Rest
|
|
61
52
|
end
|
62
53
|
|
63
54
|
def register_parser(format, parser)
|
64
|
-
raise "#{
|
55
|
+
raise "#{format} must be an object with parent class Blix::Rest::FormatParser" unless parser.is_a?(FormatParser)
|
65
56
|
|
66
57
|
parser._format = format
|
67
58
|
@_parsers[format.to_s.downcase] = parser
|
@@ -71,7 +62,7 @@ module Blix::Rest
|
|
71
62
|
# retrieve parameters from the http request
|
72
63
|
def retrieve_params(env)
|
73
64
|
post_params = {}
|
74
|
-
body
|
65
|
+
body = ''
|
75
66
|
params = env['params'] || {}
|
76
67
|
params.merge!(::Rack::Utils.parse_nested_query(env['QUERY_STRING']))
|
77
68
|
|
@@ -85,19 +76,15 @@ module Blix::Rest
|
|
85
76
|
post_params = {}
|
86
77
|
else
|
87
78
|
begin
|
88
|
-
post_params = case
|
79
|
+
post_params = case env['CONTENT_TYPE']
|
89
80
|
when URL_ENCODED
|
90
81
|
::Rack::Utils.parse_nested_query(body)
|
91
|
-
when JSON_ENCODED
|
82
|
+
when JSON_ENCODED
|
92
83
|
json = MultiJson.load(body)
|
93
|
-
|
94
|
-
json
|
95
|
-
else
|
96
|
-
{ '_json' => json }
|
97
|
-
end
|
84
|
+
json.is_a?(Hash) ? json : { '_json' => json }
|
98
85
|
else
|
99
86
|
{}
|
100
|
-
|
87
|
+
end
|
101
88
|
rescue StandardError => e
|
102
89
|
raise BadRequestError, "Invalid parameters: #{e.class}"
|
103
90
|
end
|
@@ -124,13 +111,22 @@ module Blix::Rest
|
|
124
111
|
case mime
|
125
112
|
when 'application/json' then :json
|
126
113
|
when 'text/html' then :html
|
127
|
-
when 'application/xml'
|
114
|
+
when 'application/xml' then :xml
|
128
115
|
when 'application/xhtml+xml' then :xhtml
|
129
116
|
when '*/*' then :*
|
130
117
|
end
|
131
118
|
end
|
132
119
|
|
133
|
-
|
120
|
+
def setup_parsers(options)
|
121
|
+
# Register default parsers
|
122
|
+
register_parser('html', HtmlFormatParser.new)
|
123
|
+
register_parser('json', JsonFormatParser.new)
|
124
|
+
register_parser('xml', XmlFormatParser.new)
|
125
|
+
register_parser('raw', RawFormatParser.new)
|
126
|
+
extract_parsers_from_options(options)
|
127
|
+
end
|
128
|
+
|
129
|
+
# attempt to handle multiple accept formats here..
|
134
130
|
# mime can include '.../*' and '*/*'
|
135
131
|
# FIXME
|
136
132
|
def get_format_new(env, options)
|
@@ -156,22 +152,22 @@ module Blix::Rest
|
|
156
152
|
|
157
153
|
# the call function is the interface with the rack framework
|
158
154
|
def call(env)
|
155
|
+
t1 = Time.now
|
159
156
|
req = Rack::Request.new(env)
|
160
157
|
|
161
|
-
verb
|
162
|
-
path
|
163
|
-
path
|
158
|
+
verb = env['REQUEST_METHOD']
|
159
|
+
path = req.path
|
160
|
+
path = CGI.unescape(path) unless _options[:unescape] == false
|
164
161
|
|
165
162
|
blk, path_params, options, is_wild = RequestMapper.match(verb, path)
|
166
163
|
|
167
164
|
match_all = RequestMapper.match('ALL', path) unless blk && !is_wild
|
168
|
-
blk, path_params, options = match_all if match_all && match_all[0]
|
169
|
-
|
165
|
+
blk, path_params, options = match_all if match_all && match_all[0]
|
170
166
|
|
171
167
|
default_format = options && options[:default] && options[:default].to_sym
|
172
168
|
force_format = options && options[:force] && options[:force].to_sym
|
173
|
-
do_cache
|
174
|
-
clear_cache
|
169
|
+
do_cache = options && options[:cache] && !Blix::Rest.cache_disabled
|
170
|
+
clear_cache = options && options[:cache_reset]
|
175
171
|
|
176
172
|
query_format = options && options[:query] && req.GET['format'] && req.GET['format'].to_sym
|
177
173
|
|
@@ -189,54 +185,59 @@ module Blix::Rest
|
|
189
185
|
|
190
186
|
parser._options = options
|
191
187
|
|
192
|
-
# check for cached response
|
193
|
-
#
|
194
|
-
if do_cache && ( response = _cache["#{verb}|#{format}|#{path}"] )
|
188
|
+
# check for cached response and return with cached response if found.
|
189
|
+
if do_cache && (response = _cache["#{verb}|#{format}|#{path}"])
|
195
190
|
return [response.status, response.headers.merge('x-blix-cache' => 'cached'), response.content]
|
196
191
|
end
|
197
192
|
|
198
193
|
response = Response.new
|
199
194
|
|
200
195
|
if blk
|
201
|
-
|
202
196
|
begin
|
203
197
|
params = env['params']
|
204
198
|
context = Context.new(path_params, params, req, format, response, verb, self)
|
205
|
-
value
|
199
|
+
value, response_options = blk.call(context)
|
206
200
|
rescue ServiceError => e
|
207
|
-
set_default_headers(parser,response)
|
201
|
+
set_default_headers(parser, response)
|
208
202
|
response.set(e.status, parser.format_error(e.message), e.headers)
|
203
|
+
logger << e.message if $VERBOSE
|
209
204
|
rescue RawResponse => e
|
210
205
|
value = e.content
|
211
|
-
value = [value.to_s] unless value.respond_to?(:each) ||
|
212
|
-
response.status
|
206
|
+
value = [value.to_s] unless value.respond_to?(:each) || value.respond_to?(:call)
|
207
|
+
response.status = e.status if e.status
|
213
208
|
response.content = value
|
214
209
|
response.headers.merge!(e.headers) if e.headers
|
215
210
|
rescue AuthorizationError => e
|
216
|
-
set_default_headers(parser,response)
|
211
|
+
set_default_headers(parser, response)
|
217
212
|
response.set(401, parser.format_error(e.message), AUTH_HEADER => "#{e.type} realm=\"#{e.realm}\", charset=\"UTF-8\"")
|
218
213
|
rescue Exception => e
|
219
|
-
set_default_headers(parser,response)
|
214
|
+
set_default_headers(parser, response)
|
220
215
|
response.set(500, parser.format_error('internal error'))
|
221
|
-
|
222
|
-
|
216
|
+
logger << e.message
|
217
|
+
logger << e.backtrace.join("\n")
|
223
218
|
else # no error
|
224
|
-
|
225
|
-
|
219
|
+
response_options ||= {}
|
220
|
+
response.set_options(response_options)
|
221
|
+
if response_options[:raw]
|
222
|
+
response.content = value
|
223
|
+
else
|
224
|
+
set_default_headers(parser, response)
|
225
|
+
parser.format_response(value, response)
|
226
|
+
end
|
226
227
|
# cache response if requested
|
227
228
|
_cache.clear if clear_cache
|
228
229
|
_cache["#{verb}|#{format}|#{path}"] = response if do_cache
|
229
230
|
end
|
230
|
-
|
231
231
|
else
|
232
|
-
set_default_headers(parser,response)
|
232
|
+
set_default_headers(parser, response)
|
233
233
|
response.set(404, parser.format_error('Invalid Url'))
|
234
234
|
end
|
235
235
|
|
236
|
+
logger << "#{verb} #{path} total time=#{((Time.now - t1) * 1000).round(2)}ms"
|
236
237
|
[response.status.to_i, response.headers, response.content]
|
237
238
|
end
|
238
239
|
|
239
|
-
def set_default_headers(parser,response)
|
240
|
+
def set_default_headers(parser, response)
|
240
241
|
if parser.__custom_headers
|
241
242
|
response.headers.merge! parser.__custom_headers
|
242
243
|
else
|
@@ -244,5 +245,10 @@ module Blix::Rest
|
|
244
245
|
end
|
245
246
|
end
|
246
247
|
|
248
|
+
private
|
249
|
+
|
250
|
+
def logger
|
251
|
+
Blix::Rest.logger
|
252
|
+
end
|
247
253
|
end
|
248
254
|
end
|
data/lib/blix/rest/session.rb
CHANGED
@@ -26,6 +26,11 @@ module Blix::Rest
|
|
26
26
|
self.class.get_session_manager
|
27
27
|
end
|
28
28
|
|
29
|
+
def session_skip_update
|
30
|
+
@__session_id = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
|
29
34
|
def session_name
|
30
35
|
self.class.get_session_name
|
31
36
|
end
|
@@ -67,9 +72,9 @@ module Blix::Rest
|
|
67
72
|
end
|
68
73
|
end
|
69
74
|
|
70
|
-
if opts[:csrf]
|
71
|
-
if env["HTTP_X_CSRF_TOKEN"] != csrf_token
|
72
|
-
send_error("
|
75
|
+
if opts[:csrf] && (ENV['RACK_ENV']!='test')
|
76
|
+
if env["HTTP_X_CSRF_TOKEN"] != csrf_token
|
77
|
+
send_error("error [0100]")
|
73
78
|
end
|
74
79
|
end
|
75
80
|
|
data/lib/blix/rest/version.rb
CHANGED
data/lib/blix/rest.rb
CHANGED
@@ -33,6 +33,10 @@ module Blix
|
|
33
33
|
@_environment ||= ENV['RACK_ENV'] || 'development'
|
34
34
|
end
|
35
35
|
|
36
|
+
def self.init
|
37
|
+
RequestMapper.table # compile the table
|
38
|
+
end
|
39
|
+
|
36
40
|
def self.environment?(val)
|
37
41
|
environment == val.to_s
|
38
42
|
end
|
@@ -127,6 +131,8 @@ module Blix
|
|
127
131
|
@type = type || 'Basic'
|
128
132
|
end
|
129
133
|
end
|
134
|
+
|
135
|
+
class RateError < StandardError; end
|
130
136
|
end
|
131
137
|
end
|
132
138
|
|
@@ -154,6 +160,7 @@ require 'blix/rest/response'
|
|
154
160
|
require 'blix/rest/format_parser'
|
155
161
|
require 'blix/rest/request_mapper'
|
156
162
|
require 'blix/rest/cache'
|
163
|
+
require 'blix/rest/memory_cache'
|
157
164
|
require 'blix/rest/server'
|
158
165
|
require 'blix/rest/route'
|
159
166
|
require 'blix/rest/controller'
|
data/lib/blix/utils/misc.rb
CHANGED
@@ -7,6 +7,45 @@ module Blix
|
|
7
7
|
Dir.glob("#{path}/*.rb").each {|file| require File.expand_path(file)[0..-4] }
|
8
8
|
end
|
9
9
|
|
10
|
+
def self.klass_to_name(klass)
|
11
|
+
return unless klass
|
12
|
+
klass = klass.to_s.split('::')[-1]
|
13
|
+
klass.gsub(/([a-z]+)([A-Z]+)/){"#{$1}_#{$2}"}.downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.name_to_klass(name)
|
17
|
+
construct_klass(name)
|
18
|
+
end
|
19
|
+
|
20
|
+
# construct a klass from a name
|
21
|
+
def self.construct_klass(name)
|
22
|
+
name && name.to_s.downcase.split('_').map(&:capitalize).join
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.construct_singular(name)
|
26
|
+
name && name.to_s.sub(/s$/,'')
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.construct_plural(name)
|
30
|
+
name && name.plural
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.camelcase(str)
|
34
|
+
downcase_front(construct_klass(str))
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.downcase_front(str)
|
38
|
+
str[0, 1].downcase + str[1..-1]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.underscore(str)
|
42
|
+
str.gsub(/::/, '/')
|
43
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
44
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
45
|
+
.tr('-', '_')
|
46
|
+
.downcase
|
47
|
+
end
|
48
|
+
|
10
49
|
|
11
50
|
|
12
51
|
# filter the hash using the supplied filter
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blix-rest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clive Andrews
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 2.0.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 2.0.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,14 +97,10 @@ files:
|
|
97
97
|
- lib/blix/rest.rb
|
98
98
|
- lib/blix/rest/cache.rb
|
99
99
|
- lib/blix/rest/controller.rb
|
100
|
-
- lib/blix/rest/cucumber.rb
|
101
|
-
- lib/blix/rest/cucumber/hooks.rb
|
102
|
-
- lib/blix/rest/cucumber/request_steps.rb
|
103
|
-
- lib/blix/rest/cucumber/resource_steps.rb
|
104
|
-
- lib/blix/rest/cucumber/world.rb
|
105
100
|
- lib/blix/rest/format.rb
|
106
101
|
- lib/blix/rest/format_parser.rb
|
107
102
|
- lib/blix/rest/handlebars_assets_fix.rb
|
103
|
+
- lib/blix/rest/memory_cache.rb
|
108
104
|
- lib/blix/rest/redis_cache.rb
|
109
105
|
- lib/blix/rest/request_mapper.rb
|
110
106
|
- lib/blix/rest/resource_cache.rb
|