strelka 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ChangeLog +156 -9
- data/History.rdoc +15 -0
- data/IDEAS.rdoc +17 -1
- data/MILESTONES.rdoc +1 -1
- data/Manifest.txt +10 -2
- data/Plugins.rdoc +4 -4
- data/README.rdoc +3 -3
- data/Rakefile +5 -4
- data/bin/strelka +19 -10
- data/contrib/hoetemplate/data/project/apps/file_name_app +1 -0
- data/contrib/hoetemplate/lib/file_name.rb.erb +3 -2
- data/examples/apps/hello-world +1 -0
- data/examples/apps/ws-chat +69 -0
- data/examples/apps/ws-echo +61 -0
- data/examples/gen-config.rb +6 -5
- data/lib/strelka/app/auth.rb +2 -2
- data/lib/strelka/app/errors.rb +1 -1
- data/lib/strelka/app/filters.rb +3 -2
- data/lib/strelka/app/negotiation.rb +2 -2
- data/lib/strelka/app/parameters.rb +1 -2
- data/lib/strelka/app/restresources.rb +3 -2
- data/lib/strelka/app/routing.rb +1 -1
- data/lib/strelka/app/sessions.rb +2 -2
- data/lib/strelka/app/templating.rb +7 -3
- data/lib/strelka/app.rb +5 -145
- data/lib/strelka/behavior/plugin.rb +4 -4
- data/lib/strelka/discovery.rb +211 -0
- data/lib/strelka/httprequest.rb +1 -0
- data/lib/strelka/httpresponse/negotiation.rb +7 -1
- data/lib/strelka/mixins.rb +4 -1
- data/lib/strelka/paramvalidator.rb +1 -1
- data/lib/strelka/plugins.rb +8 -6
- data/lib/strelka/websocketserver/routing.rb +116 -0
- data/lib/strelka/websocketserver.rb +147 -0
- data/lib/strelka.rb +5 -4
- data/spec/{lib/constants.rb → constants.rb} +3 -2
- data/spec/{lib/helpers.rb → helpers.rb} +15 -14
- data/spec/strelka/app/auth_spec.rb +145 -142
- data/spec/strelka/app/errors_spec.rb +20 -26
- data/spec/strelka/app/filters_spec.rb +67 -54
- data/spec/strelka/app/negotiation_spec.rb +8 -14
- data/spec/strelka/app/parameters_spec.rb +23 -29
- data/spec/strelka/app/restresources_spec.rb +98 -100
- data/spec/strelka/app/routing_spec.rb +57 -57
- data/spec/strelka/app/sessions_spec.rb +11 -17
- data/spec/strelka/app/templating_spec.rb +36 -40
- data/spec/strelka/app_spec.rb +48 -147
- data/spec/strelka/authprovider/basic_spec.rb +5 -11
- data/spec/strelka/authprovider/hostaccess_spec.rb +9 -15
- data/spec/strelka/authprovider_spec.rb +3 -9
- data/spec/strelka/cookie_spec.rb +32 -38
- data/spec/strelka/cookieset_spec.rb +31 -37
- data/spec/strelka/discovery_spec.rb +144 -0
- data/spec/strelka/exceptions_spec.rb +2 -8
- data/spec/strelka/httprequest/acceptparams_spec.rb +74 -83
- data/spec/strelka/httprequest/auth_spec.rb +5 -15
- data/spec/strelka/httprequest/negotiation_spec.rb +93 -103
- data/spec/strelka/httprequest/session_spec.rb +12 -22
- data/spec/strelka/httprequest_spec.rb +1 -7
- data/spec/strelka/httpresponse/negotiation_spec.rb +84 -76
- data/spec/strelka/httpresponse/session_spec.rb +25 -35
- data/spec/strelka/httpresponse_spec.rb +20 -26
- data/spec/strelka/mixins_spec.rb +66 -61
- data/spec/strelka/multipartparser_spec.rb +31 -37
- data/spec/strelka/paramvalidator_spec.rb +389 -373
- data/spec/strelka/plugins_spec.rb +17 -23
- data/spec/strelka/router/default_spec.rb +32 -38
- data/spec/strelka/router/exclusive_spec.rb +28 -34
- data/spec/strelka/router_spec.rb +2 -8
- data/spec/strelka/session/db_spec.rb +17 -15
- data/spec/strelka/session/default_spec.rb +22 -28
- data/spec/strelka/session_spec.rb +3 -9
- data/spec/strelka/websocketserver/routing_spec.rb +119 -0
- data/spec/strelka/websocketserver_spec.rb +149 -0
- data/spec/strelka_spec.rb +11 -13
- data.tar.gz.sig +3 -3
- metadata +22 -14
- metadata.gz.sig +0 -0
@@ -2,16 +2,10 @@
|
|
2
2
|
# vim: set nosta noet ts=4 sw=4:
|
3
3
|
# encoding: utf-8
|
4
4
|
|
5
|
-
|
6
|
-
require 'pathname'
|
7
|
-
basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
|
8
|
-
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
9
|
-
}
|
5
|
+
require_relative '../../helpers'
|
10
6
|
|
11
7
|
require 'rspec'
|
12
8
|
|
13
|
-
require 'spec/lib/helpers'
|
14
|
-
|
15
9
|
require 'strelka'
|
16
10
|
require 'strelka/plugins'
|
17
11
|
require 'strelka/app/restresources'
|
@@ -48,7 +42,7 @@ describe Strelka::App::RestResources do
|
|
48
42
|
end
|
49
43
|
|
50
44
|
|
51
|
-
it_should_behave_like( "A Strelka
|
45
|
+
it_should_behave_like( "A Strelka Plugin" )
|
52
46
|
|
53
47
|
|
54
48
|
describe "included in an App" do
|
@@ -64,8 +58,8 @@ describe Strelka::App::RestResources do
|
|
64
58
|
|
65
59
|
|
66
60
|
it "keeps track of what resources are mounted where" do
|
67
|
-
@app.resource_verbs.
|
68
|
-
@app.resource_verbs.
|
61
|
+
expect( @app.resource_verbs ).to be_a( Hash )
|
62
|
+
expect( @app.resource_verbs ).to be_empty()
|
69
63
|
end
|
70
64
|
|
71
65
|
|
@@ -80,8 +74,8 @@ describe Strelka::App::RestResources do
|
|
80
74
|
end
|
81
75
|
|
82
76
|
it "keeps track of what resources are mounted where" do
|
83
|
-
@app.resource_verbs.
|
84
|
-
@app.resource_verbs.
|
77
|
+
expect( @app.resource_verbs ).to have( 1 ).member
|
78
|
+
expect( @app.resource_verbs ).to include( 'servers' )
|
85
79
|
@app.resource_verbs[ 'servers' ].
|
86
80
|
should include( :OPTIONS, :GET, :HEAD, :POST, :PUT, :DELETE )
|
87
81
|
end
|
@@ -117,8 +111,8 @@ describe Strelka::App::RestResources do
|
|
117
111
|
end
|
118
112
|
|
119
113
|
it "keeps track of what resources are mounted where" do
|
120
|
-
@app.resource_verbs.
|
121
|
-
@app.resource_verbs.
|
114
|
+
expect( @app.resource_verbs ).to have( 1 ).member
|
115
|
+
expect( @app.resource_verbs ).to include( 'servers' )
|
122
116
|
@app.resource_verbs[ 'servers' ].
|
123
117
|
should include( :OPTIONS, :GET, :HEAD )
|
124
118
|
@app.resource_verbs[ 'servers' ].
|
@@ -182,8 +176,8 @@ describe Strelka::App::RestResources do
|
|
182
176
|
req = @request_factory.options( '/api/v1/servers' )
|
183
177
|
res = @app.new.handle( req )
|
184
178
|
|
185
|
-
res.status.
|
186
|
-
res.headers.allowed.split( /\s*,\s*/ ).
|
179
|
+
expect( res.status ).to eq( HTTP::OK )
|
180
|
+
expect( res.headers.allowed.split( /\s*,\s*/ ) ).to include(*%w[GET HEAD POST PUT DELETE])
|
187
181
|
end
|
188
182
|
|
189
183
|
end # OPTIONS routes
|
@@ -194,11 +188,11 @@ describe Strelka::App::RestResources do
|
|
194
188
|
req = @request_factory.get( '/api/v1/servers', 'Accept' => 'application/json' )
|
195
189
|
res = @app.new.handle( req )
|
196
190
|
|
197
|
-
res.content_type.
|
191
|
+
expect( res.content_type ).to eq( 'application/json' )
|
198
192
|
body = Yajl.load( res.body )
|
199
193
|
|
200
|
-
body.
|
201
|
-
body.map {|record| record['uuid'] }.
|
194
|
+
expect( body ).to have( 2 ).members
|
195
|
+
expect( body.map {|record| record['uuid'] } ).to include( 'test-server', 'step-server' )
|
202
196
|
end
|
203
197
|
|
204
198
|
it "supports limiting the result set when fetching the resource collection" do
|
@@ -206,12 +200,12 @@ describe Strelka::App::RestResources do
|
|
206
200
|
'Accept' => 'application/json' )
|
207
201
|
res = @app.new.handle( req )
|
208
202
|
|
209
|
-
res.status.
|
210
|
-
res.content_type.
|
203
|
+
expect( res.status ).to eq( HTTP::OK )
|
204
|
+
expect( res.content_type ).to eq( 'application/json' )
|
211
205
|
body = Yajl.load( res.body )
|
212
206
|
|
213
|
-
body.
|
214
|
-
body[0]['uuid'].
|
207
|
+
expect( body ).to have( 1 ).member
|
208
|
+
expect( body[0]['uuid'] ).to eq( 'test-server' )
|
215
209
|
end
|
216
210
|
|
217
211
|
it "supports paging the result set when fetching the resource collection" do
|
@@ -219,12 +213,12 @@ describe Strelka::App::RestResources do
|
|
219
213
|
'Accept' => 'application/json' )
|
220
214
|
res = @app.new.handle( req )
|
221
215
|
|
222
|
-
res.status.
|
223
|
-
res.content_type.
|
216
|
+
expect( res.status ).to eq( HTTP::OK )
|
217
|
+
expect( res.content_type ).to eq( 'application/json' )
|
224
218
|
body = Yajl.load( res.body )
|
225
219
|
|
226
|
-
body.
|
227
|
-
body[0]['uuid'].
|
220
|
+
expect( body ).to have( 1 ).member
|
221
|
+
expect( body[0]['uuid'] ).to eq( 'step-server' )
|
228
222
|
end
|
229
223
|
|
230
224
|
it "supports ordering the result by a single column" do
|
@@ -232,12 +226,12 @@ describe Strelka::App::RestResources do
|
|
232
226
|
'Accept' => 'application/json' )
|
233
227
|
res = @app.new.handle( req )
|
234
228
|
|
235
|
-
res.status.
|
236
|
-
res.content_type.
|
229
|
+
expect( res.status ).to eq( HTTP::OK )
|
230
|
+
expect( res.content_type ).to eq( 'application/json' )
|
237
231
|
body = Yajl.load( res.body )
|
238
232
|
|
239
|
-
body.
|
240
|
-
body[0]['name'].
|
233
|
+
expect( body ).to have( 2 ).members
|
234
|
+
expect( body[0]['name'] ).to eq( 'Step' )
|
241
235
|
end
|
242
236
|
|
243
237
|
it "supports ordering the result by multiple columns" do
|
@@ -245,41 +239,41 @@ describe Strelka::App::RestResources do
|
|
245
239
|
'Accept' => 'application/json' )
|
246
240
|
res = @app.new.handle( req )
|
247
241
|
|
248
|
-
res.status.
|
249
|
-
res.content_type.
|
242
|
+
expect( res.status ).to eq( HTTP::OK )
|
243
|
+
expect( res.content_type ).to eq( 'application/json' )
|
250
244
|
body = Yajl.load( res.body )
|
251
245
|
|
252
|
-
body.
|
253
|
-
body[0]['name'].
|
246
|
+
expect( body ).to have( 2 ).members
|
247
|
+
expect( body[0]['name'] ).to eq( 'Test' )
|
254
248
|
end
|
255
249
|
|
256
250
|
it "has a GET route to fetch a single resource by its ID" do
|
257
251
|
req = @request_factory.get( '/api/v1/servers/1', 'Accept' => 'application/json' )
|
258
252
|
res = @app.new.handle( req )
|
259
253
|
|
260
|
-
res.content_type.
|
254
|
+
expect( res.content_type ).to eq( 'application/json' )
|
261
255
|
body = Yajl.load( res.body )
|
262
256
|
|
263
|
-
body.
|
264
|
-
body['uuid'].
|
257
|
+
expect( body ).to be_a( Hash )
|
258
|
+
expect( body['uuid'] ).to eq( 'test-server' )
|
265
259
|
end
|
266
260
|
|
267
261
|
it "returns a NOT FOUND response when fetching a non-existant resource" do
|
268
262
|
req = @request_factory.get( '/api/v1/servers/411', 'Accept' => 'application/json' )
|
269
263
|
res = @app.new.handle( req )
|
270
264
|
|
271
|
-
res.status.
|
265
|
+
expect( res.status ).to eq( HTTP::NOT_FOUND )
|
272
266
|
res.body.rewind
|
273
|
-
res.body.read.
|
267
|
+
expect( res.body.read ).to match( /no such server/i )
|
274
268
|
end
|
275
269
|
|
276
270
|
it "returns a NOT FOUND response when fetching a resource with an invalid ID" do
|
277
271
|
req = @request_factory.get( '/api/v1/servers/ape-tastic' )
|
278
272
|
res = @app.new.handle( req )
|
279
273
|
|
280
|
-
res.status.
|
274
|
+
expect( res.status ).to eq( HTTP::NOT_FOUND )
|
281
275
|
res.body.rewind
|
282
|
-
res.body.read.
|
276
|
+
expect( res.body.read ).to match( /requested resource was not found/i )
|
283
277
|
end
|
284
278
|
|
285
279
|
it "has a GET route for fetching the resource via one of its dataset methods" do
|
@@ -287,13 +281,13 @@ describe Strelka::App::RestResources do
|
|
287
281
|
:accept => 'application/json' )
|
288
282
|
res = @app.new.handle( req )
|
289
283
|
|
290
|
-
res.status.
|
284
|
+
expect( res.status ).to eq( HTTP::OK )
|
291
285
|
body = Yajl.load( res.body )
|
292
286
|
|
293
|
-
body.
|
294
|
-
body.
|
295
|
-
body.first.
|
296
|
-
body.first['uuid'].
|
287
|
+
expect( body ).to be_an( Array )
|
288
|
+
expect( body ).to have( 1 ).member
|
289
|
+
expect( body.first ).to be_a( Hash )
|
290
|
+
expect( body.first['uuid'] ).to eq( 'test-server' )
|
297
291
|
end
|
298
292
|
|
299
293
|
it "has a GET route for fetching the resource via a subset" do
|
@@ -301,13 +295,13 @@ describe Strelka::App::RestResources do
|
|
301
295
|
:accept => 'application/json' )
|
302
296
|
res = @app.new.handle( req )
|
303
297
|
|
304
|
-
res.status.
|
298
|
+
expect( res.status ).to eq( HTTP::OK )
|
305
299
|
body = Yajl.load( res.body )
|
306
300
|
|
307
|
-
body.
|
308
|
-
body.
|
309
|
-
body.first.
|
310
|
-
body.first['port'].
|
301
|
+
expect( body ).to be_an( Array )
|
302
|
+
expect( body ).to have( 1 ).member
|
303
|
+
expect( body.first ).to be_a( Hash )
|
304
|
+
expect( body.first['port'] ).to be > 1024
|
311
305
|
end
|
312
306
|
|
313
307
|
it "has a GET route for methods declared in a named dataset module" do
|
@@ -315,13 +309,13 @@ describe Strelka::App::RestResources do
|
|
315
309
|
:accept => 'application/json' )
|
316
310
|
res = @app.new.handle( req )
|
317
311
|
|
318
|
-
res.status.
|
312
|
+
expect( res.status ).to eq( HTTP::OK )
|
319
313
|
body = Yajl.load( res.body )
|
320
314
|
|
321
|
-
body.
|
322
|
-
body.
|
323
|
-
body.first.
|
324
|
-
body.first['name'].
|
315
|
+
expect( body ).to be_an( Array )
|
316
|
+
expect( body ).to have( 1 ).member
|
317
|
+
expect( body.first ).to be_a( Hash )
|
318
|
+
expect( body.first['name'] ).to eq( 'Step' )
|
325
319
|
end
|
326
320
|
|
327
321
|
|
@@ -329,28 +323,28 @@ describe Strelka::App::RestResources do
|
|
329
323
|
req = @request_factory.get( '/api/v1/servers/1/hosts' )
|
330
324
|
res = @app.new.handle( req )
|
331
325
|
|
332
|
-
res.status.
|
326
|
+
expect( res.status ).to eq( HTTP::OK )
|
333
327
|
body = Yajl.load( res.body )
|
334
328
|
|
335
|
-
body.
|
336
|
-
body.
|
337
|
-
body.first.
|
338
|
-
body.first['server_id'].
|
339
|
-
body.first['id'].
|
329
|
+
expect( body ).to be_an( Array )
|
330
|
+
expect( body ).to have( 4 ).members
|
331
|
+
expect( body.first ).to be_a( Hash )
|
332
|
+
expect( body.first['server_id'] ).to eq( 1 )
|
333
|
+
expect( body.first['id'] ).to eq( 1 )
|
340
334
|
end
|
341
335
|
|
342
336
|
it "supports offset and limits for composite GET routes" do
|
343
337
|
req = @request_factory.get( '/api/v1/servers/1/hosts?offset=2;limit=2' )
|
344
338
|
res = @app.new.handle( req )
|
345
339
|
|
346
|
-
res.status.
|
340
|
+
expect( res.status ).to eq( HTTP::OK )
|
347
341
|
body = Yajl.load( res.body )
|
348
342
|
|
349
|
-
body.
|
350
|
-
body.
|
351
|
-
body.first.
|
352
|
-
body.first['server_id'].
|
353
|
-
body.first['id'].
|
343
|
+
expect( body ).to be_an( Array )
|
344
|
+
expect( body ).to have( 2 ).members
|
345
|
+
expect( body.first ).to be_a( Hash )
|
346
|
+
expect( body.first['server_id'] ).to eq( 1 )
|
347
|
+
expect( body.first['id'] ).to eq( 3 )
|
354
348
|
end
|
355
349
|
|
356
350
|
end # GET routes
|
@@ -384,23 +378,25 @@ describe Strelka::App::RestResources do
|
|
384
378
|
|
385
379
|
res = @app.new.handle( req )
|
386
380
|
|
387
|
-
res.status.
|
388
|
-
res.headers.location.
|
381
|
+
expect( res.status ).to eq( HTTP::CREATED )
|
382
|
+
expect( res.headers.location ).to eq( 'http://localhost:8080/api/v1/servers/3' )
|
389
383
|
|
390
384
|
new_server = Mongrel2::Config::Server[ 3 ]
|
391
385
|
|
392
|
-
new_server.uuid.
|
393
|
-
new_server.access_log.
|
394
|
-
new_server.error_log.
|
395
|
-
new_server.chroot.
|
396
|
-
new_server.pid_file.
|
397
|
-
new_server.default_host.
|
398
|
-
new_server.name.
|
399
|
-
new_server.bind_addr.
|
400
|
-
new_server.port.
|
401
|
-
new_server.use_ssl.
|
386
|
+
expect( new_server.uuid ).to eq( "test-server" )
|
387
|
+
expect( new_server.access_log ).to eq( "/logs/admin-access.log" )
|
388
|
+
expect( new_server.error_log ).to eq( "/logs/admin-error.log" )
|
389
|
+
expect( new_server.chroot ).to eq( "/var/www" )
|
390
|
+
expect( new_server.pid_file ).to eq( "/var/run/test.pid" )
|
391
|
+
expect( new_server.default_host ).to eq( "localhost" )
|
392
|
+
expect( new_server.name ).to eq( "Testing Server" )
|
393
|
+
expect( new_server.bind_addr ).to eq( "127.0.0.1" )
|
394
|
+
expect( new_server.port ).to eq( 7337 )
|
395
|
+
expect( new_server.use_ssl ).to eq( 0 )
|
402
396
|
end
|
403
397
|
|
398
|
+
it "has a POST route to update instances"
|
399
|
+
|
404
400
|
end # POST routes
|
405
401
|
|
406
402
|
|
@@ -413,7 +409,7 @@ describe Strelka::App::RestResources do
|
|
413
409
|
}
|
414
410
|
end
|
415
411
|
|
416
|
-
it "has a PUT route to
|
412
|
+
it "has a PUT route to replace instances in the resource collection" do
|
417
413
|
req = @request_factory.put( '/api/v1/servers/1' )
|
418
414
|
req.content_type = 'application/json'
|
419
415
|
req.headers.accept = 'application/json'
|
@@ -421,22 +417,24 @@ describe Strelka::App::RestResources do
|
|
421
417
|
|
422
418
|
res = @app.new.handle( req )
|
423
419
|
|
424
|
-
res.status.
|
420
|
+
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
425
421
|
|
426
|
-
Mongrel2::Config::Server[ 1 ].name.
|
427
|
-
Mongrel2::Config::Server[ 1 ].bind_addr.
|
422
|
+
expect( Mongrel2::Config::Server[ 1 ].name ).to eq( 'Not A Testing Server' )
|
423
|
+
expect( Mongrel2::Config::Server[ 1 ].bind_addr ).to eq( '0.0.0.0' )
|
428
424
|
end
|
429
425
|
|
430
|
-
it "has a PUT route to
|
431
|
-
|
432
|
-
|
433
|
-
|
426
|
+
it "has a PUT route to replace all resources in a collection" do
|
427
|
+
pending "fix the semantics of PUT and POST" do
|
428
|
+
req = @request_factory.put( '/api/v1/servers' )
|
429
|
+
req.content_type = 'application/json'
|
430
|
+
req.body = Yajl.dump({ 'bind_addr' => '0.0.0.0' })
|
434
431
|
|
435
|
-
|
432
|
+
res = @app.new.handle( req )
|
436
433
|
|
437
|
-
|
434
|
+
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
438
435
|
|
439
|
-
|
436
|
+
expect( Mongrel2::Config::Server.map( :bind_addr ) ).to eq( ['0.0.0.0'] )
|
437
|
+
end
|
440
438
|
end
|
441
439
|
|
442
440
|
end # PUT routes
|
@@ -449,9 +447,9 @@ describe Strelka::App::RestResources do
|
|
449
447
|
|
450
448
|
res = @app.new.handle( req )
|
451
449
|
|
452
|
-
res.status.
|
450
|
+
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
453
451
|
|
454
|
-
Mongrel2::Config::Server.count.
|
452
|
+
expect( Mongrel2::Config::Server.count ).to eq( 1 )
|
455
453
|
end
|
456
454
|
|
457
455
|
it "has a DELETE route to mass-delete all resources in a collection" do
|
@@ -459,9 +457,9 @@ describe Strelka::App::RestResources do
|
|
459
457
|
|
460
458
|
res = @app.new.handle( req )
|
461
459
|
|
462
|
-
res.status.
|
460
|
+
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
463
461
|
|
464
|
-
Mongrel2::Config::Server.count.
|
462
|
+
expect( Mongrel2::Config::Server.count ).to eq( 0 )
|
465
463
|
end
|
466
464
|
|
467
465
|
end # DELETE routes
|
@@ -478,13 +476,13 @@ describe Strelka::App::RestResources do
|
|
478
476
|
|
479
477
|
|
480
478
|
it "has its config inherited by subclass" do
|
481
|
-
subject.service_options.
|
482
|
-
subject.service_options.
|
479
|
+
expect( subject.service_options ).to eq( @app.service_options )
|
480
|
+
expect( subject.service_options ).to_not be( @app.service_options )
|
483
481
|
end
|
484
482
|
|
485
483
|
it "has its metadata inherited by subclasses" do
|
486
|
-
subject.resource_verbs.
|
487
|
-
subject.resource_verbs.
|
484
|
+
expect( subject.resource_verbs ).to have( 1 ).member
|
485
|
+
expect( subject.resource_verbs ).to include( 'servers' )
|
488
486
|
subject.resource_verbs[ 'servers' ].
|
489
487
|
should include( :OPTIONS, :GET, :HEAD, :POST, :PUT, :DELETE )
|
490
488
|
end
|