blix-rest 0.8.2 → 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 +486 -500
- data/lib/blix/rest/cache.rb +1 -29
- data/lib/blix/rest/controller.rb +92 -1
- data/lib/blix/rest/memory_cache.rb +30 -0
- data/lib/blix/rest/request_mapper.rb +39 -33
- 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 +13 -1
- 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
@@ -82,7 +82,7 @@ module Blix::Rest
|
|
82
82
|
|
83
83
|
# ovverride the path method to return the internal path.
|
84
84
|
def path
|
85
|
-
p = req.path
|
85
|
+
p = CGI.unescape(req.path)
|
86
86
|
p = '/' + p if p[0, 1] != '/' # ensure a leading slash on path
|
87
87
|
idx = RequestMapper.path_root_length
|
88
88
|
if idx > 0
|
@@ -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
|
@@ -671,6 +751,17 @@ module Blix::Rest
|
|
671
751
|
end
|
672
752
|
end
|
673
753
|
|
754
|
+
def allow_methods(*methods)
|
755
|
+
out = String.new
|
756
|
+
methods.each do |method|
|
757
|
+
method = method.to_s.upcase
|
758
|
+
next if (HTTP_VERBS + ['ALL']).include?(method)
|
759
|
+
out << "def #{method.downcase}(*a, &b);route '#{method}', *a, &b;end\n"
|
760
|
+
end
|
761
|
+
puts out if $DEBUG || $VERBOSE
|
762
|
+
eval out unless out.empty?
|
763
|
+
end
|
764
|
+
|
674
765
|
end
|
675
766
|
|
676
767
|
end
|
@@ -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
|
@@ -317,31 +321,33 @@ module Blix::Rest
|
|
317
321
|
list.sort! { |a, b| a[0] <=> b[0] }
|
318
322
|
str = String.new
|
319
323
|
list.each do |route|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
str << verb << "\t" << route[0] << route[1][verb] << "\n"
|
324
|
-
end
|
324
|
+
pairs = route[1].to_a.sort{|a,b| a[0]<=>b[0]}
|
325
|
+
pairs.each do |pair|
|
326
|
+
str << pair[0] << "\t" << route[0] << "\t" << pair[1] << "\n"
|
325
327
|
end
|
326
328
|
str << "\n"
|
327
329
|
end
|
328
330
|
str
|
329
331
|
end
|
330
|
-
|
331
332
|
end
|
332
333
|
|
333
334
|
end # RequestMapper
|
334
335
|
|
335
|
-
|
336
|
-
RequestMapper.set_path_root(*args)
|
337
|
-
end
|
336
|
+
class << self
|
338
337
|
|
339
|
-
def self.path_root
|
340
|
-
RequestMapper.path_root
|
341
|
-
end
|
342
338
|
|
343
|
-
|
344
|
-
|
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
|
+
|
345
351
|
end
|
346
352
|
|
347
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
|
@@ -96,9 +100,14 @@ module Blix
|
|
96
100
|
|
97
101
|
def initialize(message, status = nil, headers = nil)
|
98
102
|
super(message || "")
|
99
|
-
@status = status || 406
|
103
|
+
@status = (status || 406).to_i
|
100
104
|
@headers = headers
|
101
105
|
end
|
106
|
+
|
107
|
+
def to_i
|
108
|
+
@status
|
109
|
+
end
|
110
|
+
|
102
111
|
end
|
103
112
|
|
104
113
|
class RawResponse < StandardError
|
@@ -122,6 +131,8 @@ module Blix
|
|
122
131
|
@type = type || 'Basic'
|
123
132
|
end
|
124
133
|
end
|
134
|
+
|
135
|
+
class RateError < StandardError; end
|
125
136
|
end
|
126
137
|
end
|
127
138
|
|
@@ -149,6 +160,7 @@ require 'blix/rest/response'
|
|
149
160
|
require 'blix/rest/format_parser'
|
150
161
|
require 'blix/rest/request_mapper'
|
151
162
|
require 'blix/rest/cache'
|
163
|
+
require 'blix/rest/memory_cache'
|
152
164
|
require 'blix/rest/server'
|
153
165
|
require 'blix/rest/route'
|
154
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
|