blix-rest 0.1.30 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +2 -2
- data/README.md +154 -28
- data/lib/blix/rest/cache.rb +79 -0
- data/lib/blix/rest/controller.rb +162 -29
- data/lib/blix/rest/cucumber/world.rb +13 -12
- data/lib/blix/rest/format_parser.rb +18 -11
- data/lib/blix/rest/redis_cache.rb +127 -0
- data/lib/blix/rest/request_mapper.rb +22 -6
- data/lib/blix/rest/response.rb +2 -2
- data/lib/blix/rest/server.rb +60 -20
- data/lib/blix/rest/version.rb +1 -1
- data/lib/blix/rest.rb +30 -9
- data/lib/blix/utils/redis_store.rb +2 -2
- metadata +21 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf93b3d5836172b6cf1b4ac5df21dfe14e1e998e31e774f9b4fdb4bc5bdec323
|
4
|
+
data.tar.gz: 622db8bf8d0052fd25f3727656ac6b641bc63a2667e97eb3f93f7dc4884e03ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32516afd36a4a6c36c81650e50f84970cf2436b7cf682a51cae83d1300f736d4dbfe49d04d590ac8ffde841d2dac7f236d0979b3b5c1d5bec230112584eb6e0d
|
7
|
+
data.tar.gz: 7f106344ec03beb691d5870c5809f379285d578ba17cb9b8edd1ea86c5c64dfa31b0a9747a75adab7730ba514cecca3a508cb36f5560343f147cd64d866ca3d4
|
data/LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2017 Clive Andrews
|
3
|
+
Copyright (c) 2017-2020 Clive Andrews
|
4
4
|
|
5
5
|
|
6
6
|
Permission is hereby granted, free of charge, to any person
|
@@ -22,4 +22,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
22
22
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
23
23
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
24
24
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
25
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -71,7 +71,7 @@ if there is a more specific path then it will be used first :
|
|
71
71
|
### Path options
|
72
72
|
|
73
73
|
:accept : the format or formats to accept eg: :html or [:png, :jpeg]
|
74
|
-
:default : default format if not derived through
|
74
|
+
:default : default format if not derived through other means.
|
75
75
|
:force : force response into the given format
|
76
76
|
:query : derive format from request query (default: false)
|
77
77
|
:extension : derive format from path extension (default: true)
|
@@ -189,10 +189,19 @@ use the following to accept requests in a special format ..
|
|
189
189
|
|
190
190
|
get '/custom', :accept=>:xyz, :force=>:raw do
|
191
191
|
add_headers 'Content-Type'=>'text/xyz'
|
192
|
-
|
193
192
|
"xyz"
|
194
193
|
end
|
195
194
|
|
195
|
+
|
196
|
+
Alternatively it is possible to raise a RawResponse:
|
197
|
+
|
198
|
+
add_headers 'Content-Type'=>'text/xyz'
|
199
|
+
raise RawResponse, 'xyz'
|
200
|
+
|
201
|
+
or with status and headers:
|
202
|
+
|
203
|
+
raise RawResponse.new('xyz', 123, 'Content-Type'=>'text/xyz')
|
204
|
+
|
196
205
|
## FORMATS
|
197
206
|
|
198
207
|
the format of a request is derived from
|
@@ -218,32 +227,39 @@ base class for controllers. within your block handling a particular route you
|
|
218
227
|
have access to a number of methods
|
219
228
|
|
220
229
|
|
221
|
-
env
|
222
|
-
method
|
223
|
-
req
|
224
|
-
body
|
225
|
-
query_params
|
226
|
-
path_params
|
227
|
-
post_params
|
228
|
-
params
|
229
|
-
user
|
230
|
-
format
|
231
|
-
before
|
232
|
-
after
|
233
|
-
proxy
|
234
|
-
session
|
235
|
-
redirect
|
236
|
-
request_ip
|
237
|
-
render_erb
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
230
|
+
env : the request environment hash
|
231
|
+
method : the request method lowercase( 'get'/'post' ..)
|
232
|
+
req : the rack request
|
233
|
+
body : the request body as a string
|
234
|
+
query_params : a hash of parameters as passed in the url as parameters
|
235
|
+
path_params : a hash of parameters constructed from variable parts of the path
|
236
|
+
post_params : a hash of parameters passed in the body of the request
|
237
|
+
params : all the params combined
|
238
|
+
user : the user making this request ( or nil if
|
239
|
+
format : the format the response should be in :json or :html
|
240
|
+
before : before hook ( opts ) - remember to add 'super' as first line !!!
|
241
|
+
after : after hook (opts,response)- remember to add 'super' as first line !!!
|
242
|
+
proxy : forward the call to another service (service,path, opts={}) , :include_query=>true/false
|
243
|
+
session : req.session
|
244
|
+
redirect : (path, status=302) redirect to another url.
|
245
|
+
request_ip : the ip of the request
|
246
|
+
render_erb : (template_name [,:layout=>name])
|
247
|
+
server_cache : get the server cache object
|
248
|
+
server_cache_get : retrieve/store value in cache
|
249
|
+
path_for : (path) give the correct path for an internal path
|
250
|
+
url_for : (path) give the full url for an internal path
|
251
|
+
h : escape html string to avoid XSS
|
252
|
+
escape_javascript : escape a javascript string
|
253
|
+
server_options : options as passed to server at create time
|
254
|
+
logger : system logger
|
255
|
+
mode_test? : test mode ?
|
256
|
+
mode_production? : production mode ?
|
257
|
+
mode_development? : development mode?
|
258
|
+
send_data : send raw data (data, options )
|
259
|
+
[:type=>mimetype]
|
260
|
+
[:filename=>name]
|
261
|
+
[:disposition=>inline|attachment]
|
262
|
+
[:status=>234]
|
247
263
|
|
248
264
|
get_session_id(session_name, opts={}) :
|
249
265
|
refresh_session_id(session_name, opts={}) :
|
@@ -252,6 +268,45 @@ to accept requests other than json then set `:accept=>[:json,:html]` as options
|
|
252
268
|
|
253
269
|
eg `post '/myform' :accept=>[:html] # this will only accept html requests.`
|
254
270
|
|
271
|
+
### Hooks
|
272
|
+
|
273
|
+
a before or after hook can be defined on a controller. Only define the hook once
|
274
|
+
for a given controller per source file. A hook included from another source file
|
275
|
+
is ok though.
|
276
|
+
|
277
|
+
class MyController < Blix::Rest::Controller
|
278
|
+
|
279
|
+
before do
|
280
|
+
...
|
281
|
+
end
|
282
|
+
|
283
|
+
after do
|
284
|
+
...
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
#### manipulate the route path or options
|
291
|
+
|
292
|
+
the `before_route` hook can be used to modify the path or options of a route.
|
293
|
+
|
294
|
+
*NOTE* ! when manipulating the path you have to modify the string object in place.
|
295
|
+
|
296
|
+
the verb can not be modified
|
297
|
+
|
298
|
+
example:
|
299
|
+
|
300
|
+
class MyController < Blix::Rest::Controller
|
301
|
+
|
302
|
+
before_route do |verb, path, opts|
|
303
|
+
opts[:level] = :visitor unless opts[:level]
|
304
|
+
path.prepend('/') unless path[0] == '/'
|
305
|
+
path.prepend('/app') unless path[0, 4] == '/app'
|
306
|
+
end
|
307
|
+
...
|
308
|
+
end
|
309
|
+
|
255
310
|
### Sessions
|
256
311
|
|
257
312
|
the following methods are available in the controller for managing sessions.
|
@@ -272,7 +327,78 @@ options can include:
|
|
272
327
|
:samesite =>:lax # use lax x-site policy
|
273
328
|
|
274
329
|
|
330
|
+
## Cache
|
331
|
+
|
332
|
+
|
333
|
+
the server has a cache which can also be used for storing your own data.
|
334
|
+
|
335
|
+
within a controller access the controller with `server_cache` which returns the
|
336
|
+
cache object.
|
337
|
+
|
338
|
+
cache object methods:
|
339
|
+
|
340
|
+
get(key) # return value from the cache or nil
|
341
|
+
set(key,value) # set a value in the cache
|
342
|
+
key?(key) # is a key present in the cache
|
343
|
+
delete(key) # delete a key from the cache
|
344
|
+
clear # delete all keys from the cache.
|
345
|
+
|
346
|
+
there is also a `server_cache_get` method.
|
347
|
+
|
348
|
+
server_cache_get(key){ action }
|
349
|
+
|
350
|
+
get the value from the cache. If the key is missing in the cache then perform
|
351
|
+
the action in the provided block and store the result in the cache.
|
352
|
+
|
353
|
+
the default cache is just a ruby hash in memory. Pass a custom cache to
|
354
|
+
when creating a server with the `:cache` parameter.
|
355
|
+
|
356
|
+
class MyCache < Blix::Rest::Cache
|
357
|
+
def get(key)
|
358
|
+
..
|
359
|
+
end
|
360
|
+
|
361
|
+
def set(key,value)
|
362
|
+
..
|
363
|
+
end
|
364
|
+
|
365
|
+
def key?(key)
|
366
|
+
..
|
367
|
+
end
|
368
|
+
|
369
|
+
def delete(key)
|
370
|
+
..
|
371
|
+
end
|
372
|
+
|
373
|
+
def clear
|
374
|
+
..
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
cache = MyCache.new
|
379
|
+
|
380
|
+
app = Blix::Rest::Server.new(:cache=>cache)
|
381
|
+
|
382
|
+
there is a redis cache already defined:
|
383
|
+
|
384
|
+
require 'blix/rest/redis_cache'
|
385
|
+
|
386
|
+
cache = Blix::Rest::RedisCache.new(:expire_secs=>60*60*24) # expire after 1 day
|
387
|
+
run Blix::Rest::Server.new(:cache=>cache)
|
388
|
+
|
389
|
+
|
390
|
+
### automatically cache server responses
|
391
|
+
|
392
|
+
add `:cache=>true` to your route options in order to cache this route.
|
393
|
+
|
394
|
+
add `:cache_reset=>true` to your route options if the cache should be cleared when
|
395
|
+
calling this route.
|
396
|
+
|
397
|
+
the cache is not used in development/testmode , only in production mode.
|
398
|
+
|
399
|
+
### IMPORTANT - DO NOT CACHE SESSION KEYS AND OTHER SPECIFIC DATA IN CACHE
|
275
400
|
|
401
|
+
only cache pages with **HEADERS** and **CONTENT** that is not user specific.
|
276
402
|
|
277
403
|
## Views
|
278
404
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Blix::Rest
|
2
|
+
|
3
|
+
# cache server responses
|
4
|
+
class Cache
|
5
|
+
|
6
|
+
attr_reader :params
|
7
|
+
|
8
|
+
def initialize(params={})
|
9
|
+
@params = params
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
get(key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key,data)
|
17
|
+
set(key, data)
|
18
|
+
end
|
19
|
+
|
20
|
+
#--------------- redefine these methods ..
|
21
|
+
|
22
|
+
# clear all data from the cache
|
23
|
+
def clear
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# retrieve data from the cache
|
28
|
+
def get(key)
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
# set data in the cache
|
33
|
+
def set(key, data)
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
# is key present in the cache
|
38
|
+
def key?(key)
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete(key)
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
#---------------------------------------------------------------------------
|
47
|
+
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
# implement cache as a simple ruby hash
|
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
|
data/lib/blix/rest/controller.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'base64'
|
4
4
|
require 'erb'
|
5
5
|
require 'securerandom'
|
6
|
+
require 'digest'
|
6
7
|
|
7
8
|
module Blix::Rest
|
8
9
|
# base class for controllers. within your block handling a particular route you
|
@@ -21,8 +22,19 @@ module Blix::Rest
|
|
21
22
|
# to accept requests other thatn json then set :accept=>[:json,:html] as options in the route
|
22
23
|
# eg post '/myform' :accept=>[:html] # this will only accept html requests.
|
23
24
|
|
25
|
+
Context = Struct.new(
|
26
|
+
:path_params,
|
27
|
+
:params,
|
28
|
+
:req,
|
29
|
+
:format,
|
30
|
+
:response,
|
31
|
+
:method,
|
32
|
+
:server
|
33
|
+
)
|
34
|
+
|
24
35
|
class Controller
|
25
36
|
|
37
|
+
|
26
38
|
#--------------------------------------------------------------------------------------------------------
|
27
39
|
# convenience methods
|
28
40
|
#--------------------------------------------------------------------------------------------------------
|
@@ -35,6 +47,14 @@ module Blix::Rest
|
|
35
47
|
@_server_options
|
36
48
|
end
|
37
49
|
|
50
|
+
def server_cache
|
51
|
+
@_server_cache
|
52
|
+
end
|
53
|
+
|
54
|
+
def server_cache_get(key)
|
55
|
+
server_cache[key] ||= yield if block_given?
|
56
|
+
end
|
57
|
+
|
38
58
|
def logger
|
39
59
|
Blix::Rest.logger
|
40
60
|
end
|
@@ -60,8 +80,18 @@ module Blix::Rest
|
|
60
80
|
# env['rack.input'].rewindreq.POST #env["body"]
|
61
81
|
end
|
62
82
|
|
83
|
+
# ovverride the path method to return the internal path.
|
63
84
|
def path
|
64
|
-
req.path
|
85
|
+
p = req.path
|
86
|
+
p = '/' + p if p[0, 1] != '/' # ensure a leading slash on path
|
87
|
+
idx = RequestMapper.path_root_length
|
88
|
+
if idx > 0
|
89
|
+
p = p[idx..-1] || '/'
|
90
|
+
p = '/' + p if p[0, 1] != '/' # ensure a leading slash on path
|
91
|
+
p
|
92
|
+
else
|
93
|
+
p
|
94
|
+
end
|
65
95
|
end
|
66
96
|
|
67
97
|
def form_hash
|
@@ -113,7 +143,7 @@ module Blix::Rest
|
|
113
143
|
end
|
114
144
|
|
115
145
|
def path_for(path)
|
116
|
-
File.join(RequestMapper.path_root, path)
|
146
|
+
File.join(RequestMapper.path_root, path || '')
|
117
147
|
end
|
118
148
|
|
119
149
|
def url_for(path)
|
@@ -128,6 +158,18 @@ module Blix::Rest
|
|
128
158
|
@_verb
|
129
159
|
end
|
130
160
|
|
161
|
+
def method
|
162
|
+
@_method
|
163
|
+
end
|
164
|
+
|
165
|
+
def route_parameters
|
166
|
+
@_parameters
|
167
|
+
end
|
168
|
+
|
169
|
+
def response
|
170
|
+
@_response
|
171
|
+
end
|
172
|
+
|
131
173
|
def method
|
132
174
|
env['REQUEST_METHOD'].downcase
|
133
175
|
end
|
@@ -147,7 +189,7 @@ module Blix::Rest
|
|
147
189
|
end
|
148
190
|
|
149
191
|
def redirect(path, status = 302)
|
150
|
-
raise ServiceError.new(nil, status, '
|
192
|
+
raise ServiceError.new(nil, status, 'location' => RequestMapper.ensure_full_path(path))
|
151
193
|
end
|
152
194
|
|
153
195
|
alias redirect_to redirect
|
@@ -191,11 +233,11 @@ module Blix::Rest
|
|
191
233
|
end
|
192
234
|
|
193
235
|
def set_status(value)
|
194
|
-
@_response.status = value
|
236
|
+
@_response.status = value.to_i
|
195
237
|
end
|
196
238
|
|
197
239
|
def add_headers(headers)
|
198
|
-
@_response.headers.merge!(headers)
|
240
|
+
@_response.headers.merge!(headers.map{|k,v| [k.to_s.downcase,v]}.to_h)
|
199
241
|
end
|
200
242
|
|
201
243
|
# the following is copied from Rack::Utils
|
@@ -231,6 +273,19 @@ module Blix::Rest
|
|
231
273
|
raise ServiceError.new(message, status, headers)
|
232
274
|
end
|
233
275
|
|
276
|
+
# send data to browser as attachment
|
277
|
+
def send_data(data, opts = {})
|
278
|
+
add_headers 'content-type'=> opts[:type] || 'application/octet-stream'
|
279
|
+
if opts[:filename]
|
280
|
+
add_headers 'content-disposition'=>'attachment;filename='+ opts[:filename]
|
281
|
+
elsif opts[:disposition] == 'attachment'
|
282
|
+
add_headers 'content-disposition'=>'attachment'
|
283
|
+
elsif opts[:disposition] == 'inline'
|
284
|
+
add_headers 'content-disposition'=>'inline'
|
285
|
+
end
|
286
|
+
raise RawResponse.new(data, opts[:status] || 200)
|
287
|
+
end
|
288
|
+
|
234
289
|
def auth_error(*params)
|
235
290
|
if params[0].kind_of?(String)
|
236
291
|
message = params[0]
|
@@ -279,7 +334,7 @@ module Blix::Rest
|
|
279
334
|
# else
|
280
335
|
# cookie_header = cookie_text
|
281
336
|
# end
|
282
|
-
@_response.headers['
|
337
|
+
@_response.headers['set-cookie'] = @_cookies.values.join("\n")
|
283
338
|
value
|
284
339
|
end
|
285
340
|
|
@@ -315,6 +370,16 @@ module Blix::Rest
|
|
315
370
|
store_cookie(session_name, session_id, opts)
|
316
371
|
end
|
317
372
|
|
373
|
+
# perform the before hooks.
|
374
|
+
def __before(*a)
|
375
|
+
self.class._do_before(self, *a)
|
376
|
+
end
|
377
|
+
|
378
|
+
# perform the after hooks
|
379
|
+
def __after(*a)
|
380
|
+
self.class._do_after(self, *a)
|
381
|
+
end
|
382
|
+
|
318
383
|
#----------------------------------------------------------------------------------------------------------
|
319
384
|
# template methods that can be overwritten
|
320
385
|
|
@@ -329,15 +394,27 @@ module Blix::Rest
|
|
329
394
|
|
330
395
|
#----------------------------------------------------------------------------------------------------------
|
331
396
|
|
332
|
-
def
|
333
|
-
@
|
334
|
-
@
|
397
|
+
def _setup(context, _verb, _path, _parameters)
|
398
|
+
@_context = context
|
399
|
+
@_req = context.req
|
400
|
+
@_env = req.env
|
335
401
|
@_query_params = StringHash.new(req.GET)
|
336
|
-
@_path_params = StringHash.new(path_params)
|
337
|
-
@_format
|
338
|
-
@_verb
|
339
|
-
@_response
|
340
|
-
@_server_options =
|
402
|
+
@_path_params = StringHash.new(context.path_params)
|
403
|
+
@_format = context.format
|
404
|
+
@_verb = _verb
|
405
|
+
@_response = context.response
|
406
|
+
@_server_options = context.server._options
|
407
|
+
@_parameters = _parameters
|
408
|
+
@_server_cache = context.server._cache
|
409
|
+
@_method = context.method
|
410
|
+
end
|
411
|
+
|
412
|
+
def to_s
|
413
|
+
"<#{self.class.to_s}:#{object_id}>"
|
414
|
+
end
|
415
|
+
|
416
|
+
def inspect
|
417
|
+
to_s
|
341
418
|
end
|
342
419
|
|
343
420
|
# do not cache templates in development mode
|
@@ -376,9 +453,9 @@ module Blix::Rest
|
|
376
453
|
path = opts[:path] || __erb_path || Controller.erb_root
|
377
454
|
|
378
455
|
layout = layout_name && if no_template_cache
|
379
|
-
ERB.new(File.read(File.join(path, layout_name + '.html.erb'))
|
456
|
+
ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
|
380
457
|
else
|
381
|
-
erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb'))
|
458
|
+
erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
|
382
459
|
end
|
383
460
|
|
384
461
|
begin
|
@@ -388,8 +465,8 @@ module Blix::Rest
|
|
388
465
|
text
|
389
466
|
end
|
390
467
|
rescue Exception
|
391
|
-
|
392
|
-
|
468
|
+
::Blix::Rest.logger << $!
|
469
|
+
::Blix::Rest.logger << $@
|
393
470
|
'*** TEMPLATE ERROR ***'
|
394
471
|
end
|
395
472
|
end
|
@@ -401,15 +478,15 @@ module Blix::Rest
|
|
401
478
|
path = opts[:erb_dir] || __erb_path || Controller.erb_root
|
402
479
|
|
403
480
|
layout = layout_name && if no_template_cache
|
404
|
-
ERB.new(File.read(File.join(path, layout_name + '.html.erb'))
|
481
|
+
ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
|
405
482
|
else
|
406
|
-
erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb'))
|
483
|
+
erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
|
407
484
|
end
|
408
485
|
|
409
486
|
erb = if no_template_cache
|
410
|
-
ERB.new(File.read(File.join(path, name + '.html.erb'))
|
487
|
+
ERB.new(File.read(File.join(path, name + '.html.erb')),:trim_mode=>'-')
|
411
488
|
else
|
412
|
-
erb_templates[name] ||= ERB.new(File.read(File.join(path, name + '.html.erb'))
|
489
|
+
erb_templates[name] ||= ERB.new(File.read(File.join(path, name + '.html.erb')),:trim_mode=>'-')
|
413
490
|
end
|
414
491
|
|
415
492
|
begin
|
@@ -421,8 +498,8 @@ module Blix::Rest
|
|
421
498
|
erb.result(bind)
|
422
499
|
end
|
423
500
|
rescue Exception
|
424
|
-
|
425
|
-
|
501
|
+
::Blix::Rest.logger << $!
|
502
|
+
::Blix::Rest.logger << $@
|
426
503
|
'*** TEMPLATE ERROR ***'
|
427
504
|
end
|
428
505
|
end
|
@@ -447,19 +524,32 @@ module Blix::Rest
|
|
447
524
|
raise ServiceError, 'invalid format for this request' unless accept.index format
|
448
525
|
end
|
449
526
|
|
527
|
+
def _do_route_hook(verb, path, opts)
|
528
|
+
if @_route_hook
|
529
|
+
superclass._do_route_hook(verb, path, opts) if superclass.respond_to? :_do_route_hook
|
530
|
+
@_route_hook.call(verb, path, opts)
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
450
534
|
def route(verb, path, opts = {}, &blk)
|
451
|
-
|
535
|
+
path = String.new(path) # in case frozen.
|
536
|
+
_do_route_hook(verb.dup, path, opts)
|
537
|
+
proc = lambda do |context|
|
452
538
|
unless opts[:force] && (opts[:accept] == :*)
|
453
|
-
check_format(opts[:accept],
|
539
|
+
check_format(opts[:accept], context.format)
|
454
540
|
end
|
455
|
-
app = new
|
541
|
+
app = new
|
542
|
+
app._setup(context, verb, path, opts)
|
456
543
|
begin
|
457
544
|
app.before(opts)
|
458
|
-
|
545
|
+
app.__before
|
546
|
+
context.response = app.instance_eval( &blk )
|
459
547
|
rescue
|
460
548
|
raise
|
461
549
|
ensure
|
462
|
-
app.
|
550
|
+
app.__after
|
551
|
+
app.after(opts, context.response)
|
552
|
+
context.response
|
463
553
|
end
|
464
554
|
end
|
465
555
|
|
@@ -498,6 +588,49 @@ module Blix::Rest
|
|
498
588
|
route 'OPTIONS', *a, &b
|
499
589
|
end
|
500
590
|
|
591
|
+
def before_route(&b)
|
592
|
+
@_route_hook = b if b
|
593
|
+
end
|
594
|
+
|
595
|
+
|
596
|
+
def _before_hooks
|
597
|
+
@_before_hooks ||= {}
|
598
|
+
end
|
599
|
+
|
600
|
+
def _after_hooks
|
601
|
+
@_after_hooks ||= {}
|
602
|
+
end
|
603
|
+
|
604
|
+
def _do_before(ctx, *a)
|
605
|
+
superclass._do_before(ctx, *a) if superclass.respond_to? :_do_before
|
606
|
+
_before_hooks.each_value{ |h| ctx.instance_eval(&h) }
|
607
|
+
end
|
608
|
+
|
609
|
+
def _do_after(ctx, *a)
|
610
|
+
_after_hooks.each_value{ |h| ctx.instance_eval(&h) }
|
611
|
+
superclass._do_after(ctx, *a) if superclass.respond_to? :_do_after
|
612
|
+
end
|
613
|
+
|
614
|
+
# define a before hook for a controller. only one hook can be defined per
|
615
|
+
# controller in a single source file.
|
616
|
+
def before(&block)
|
617
|
+
if block
|
618
|
+
file = block.source_location[0]
|
619
|
+
warn("warning: before hook already defined in #{file}") if _before_hooks[file]
|
620
|
+
_before_hooks[file] = block
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
# define an after hook for a controller. only one hook can be defined per
|
625
|
+
# controller in a single source file.
|
626
|
+
def after(&block)
|
627
|
+
if block
|
628
|
+
file = block.source_location[0]
|
629
|
+
warn("warning: after hook already defined in #{file}") if _after_hooks[file]
|
630
|
+
_after_hooks[file] = block
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
501
634
|
end
|
502
635
|
|
503
636
|
end
|