blix-rest 0.1.30 → 0.7.2
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/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
|