thingfish 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.md +48 -0
- data/{README.rdoc → README.md} +40 -30
- data/Rakefile +4 -86
- data/bin/thingfish +1 -1
- data/lib/strelka/app/metadata.rb +1 -1
- data/lib/strelka/apps.rb +1 -1
- data/lib/strelka/httprequest/metadata.rb +1 -1
- data/lib/thingfish.rb +2 -2
- data/lib/thingfish/behaviors.rb +1 -1
- data/lib/thingfish/datastore.rb +1 -1
- data/lib/thingfish/datastore/memory.rb +1 -1
- data/lib/thingfish/handler.rb +1 -1
- data/lib/thingfish/metastore.rb +1 -1
- data/lib/thingfish/metastore/memory.rb +1 -1
- data/lib/thingfish/mixins.rb +1 -1
- data/lib/thingfish/processor.rb +1 -1
- data/lib/thingfish/processor/sha256.rb +2 -2
- data/lib/thingfish/spechelpers.rb +1 -1
- data/spec/helpers.rb +19 -12
- data/spec/thingfish/datastore/memory_spec.rb +1 -1
- data/spec/thingfish/datastore_spec.rb +1 -1
- data/spec/thingfish/handler_spec.rb +175 -184
- data/spec/thingfish/metastore/memory_spec.rb +1 -1
- data/spec/thingfish/metastore_spec.rb +1 -1
- data/spec/thingfish/mixins_spec.rb +1 -1
- data/spec/thingfish/processor/sha256_spec.rb +1 -1
- data/spec/thingfish/processor_spec.rb +1 -1
- data/spec/thingfish_spec.rb +1 -1
- metadata +52 -100
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -8826
- data/Gemfile +0 -2
- data/History.rdoc +0 -27
- data/Manifest.txt +0 -41
- data/Procfile +0 -4
- data/etc/mongrel2-config.rb +0 -57
- data/etc/thingfish.conf.example +0 -26
@@ -7,7 +7,7 @@ require 'thingfish/handler'
|
|
7
7
|
require 'thingfish/processor'
|
8
8
|
|
9
9
|
|
10
|
-
describe Thingfish::Handler do
|
10
|
+
RSpec.describe Thingfish::Handler do
|
11
11
|
|
12
12
|
EVENT_SOCKET_URI = 'tcp://127.0.0.1:*'
|
13
13
|
|
@@ -16,18 +16,9 @@ describe Thingfish::Handler do
|
|
16
16
|
Thingfish::Handler.install_plugins
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@handler = described_class.new( TEST_APPID, TEST_SEND_SPEC, TEST_RECV_SPEC )
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
after( :each ) do
|
27
|
-
@handler.shutdown
|
28
|
-
end
|
29
|
-
|
30
|
-
# let( :handler ) { described_class.new(TEST_APPID, TEST_SEND_SPEC, TEST_RECV_SPEC) }
|
19
|
+
let( :png_io ) { StringIO.new( TEST_PNG_DATA.dup ) }
|
20
|
+
let( :text_io ) { StringIO.new( TEST_TEXT_DATA.dup ) }
|
21
|
+
let( :handler ) { described_class.new(TEST_APPID, TEST_SEND_SPEC, TEST_RECV_SPEC) }
|
31
22
|
|
32
23
|
|
33
24
|
#
|
@@ -51,7 +42,7 @@ describe Thingfish::Handler do
|
|
51
42
|
|
52
43
|
it 'returns interesting configuration info' do
|
53
44
|
req = factory.get( '/serverinfo', content_type: 'text/plain' )
|
54
|
-
res =
|
45
|
+
res = handler.handle( req )
|
55
46
|
|
56
47
|
expect( res.status_line ).to match( /200 ok/i )
|
57
48
|
expect( res.headers ).to include( 'x-thingfish' )
|
@@ -73,7 +64,7 @@ describe Thingfish::Handler do
|
|
73
64
|
req = factory.post( '/', TEST_TEXT_DATA )
|
74
65
|
req.content_type = 'text/plain'
|
75
66
|
req.headers.content_length = TEST_TEXT_DATA.bytesize
|
76
|
-
res =
|
67
|
+
res = handler.handle( req )
|
77
68
|
|
78
69
|
expect( res.status_line ).to match( /201 created/i )
|
79
70
|
expect( res.headers.location.to_s ).to match( %r:/#{UUID_PATTERN}$: )
|
@@ -100,18 +91,18 @@ describe Thingfish::Handler do
|
|
100
91
|
with( spool_path, 'r', encoding: Encoding::ASCII_8BIT ).
|
101
92
|
and_return( fh )
|
102
93
|
|
103
|
-
start_req = factory.post( '/',
|
94
|
+
start_req = factory.post( '/', '',
|
104
95
|
x_mongrel2_upload_start: spool_path,
|
105
96
|
content_length: upload_size,
|
106
97
|
content_type: 'text/plain' )
|
107
|
-
upload_req = factory.post( '/',
|
98
|
+
upload_req = factory.post( '/', '',
|
108
99
|
x_mongrel2_upload_start: spool_path,
|
109
100
|
x_mongrel2_upload_done: spool_path,
|
110
101
|
content_length: upload_size,
|
111
102
|
content_type: 'text/plain' )
|
112
103
|
|
113
|
-
start_res =
|
114
|
-
upload_res =
|
104
|
+
start_res = handler.dispatch_request( start_req )
|
105
|
+
upload_res = handler.dispatch_request( upload_req )
|
115
106
|
|
116
107
|
expect( start_res ).to be_nil
|
117
108
|
|
@@ -151,7 +142,7 @@ describe Thingfish::Handler do
|
|
151
142
|
req = factory.post( '/', TEST_TEXT_DATA )
|
152
143
|
req.content_type = 'text/plain'
|
153
144
|
|
154
|
-
res =
|
145
|
+
res = handler.handle( req )
|
155
146
|
res.body.rewind
|
156
147
|
expect( res.status ).to be( HTTP::BAD_REQUEST )
|
157
148
|
expect( res.body.read ).to match( /missing operational attribute/i )
|
@@ -166,60 +157,60 @@ describe Thingfish::Handler do
|
|
166
157
|
}
|
167
158
|
req = factory.post( '/', TEST_TEXT_DATA, headers )
|
168
159
|
req.headers.content_length = TEST_TEXT_DATA.bytesize
|
169
|
-
res =
|
160
|
+
res = handler.handle( req )
|
170
161
|
|
171
162
|
expect( res.status_line ).to match( /201 created/i )
|
172
163
|
expect( res.headers.location.to_s ).to match( %r:/#{UUID_PATTERN}$: )
|
173
164
|
|
174
165
|
uuid = res.headers.x_thingfish_uuid
|
175
|
-
expect(
|
166
|
+
expect( handler.metastore.fetch_value(uuid, 'title') ).
|
176
167
|
to eq( 'Muffin the Panda Goes To School' )
|
177
|
-
expect(
|
168
|
+
expect( handler.metastore.fetch_value(uuid, 'tags') ).to eq( 'rapper,ukraine,potap' )
|
178
169
|
end
|
179
170
|
|
180
171
|
|
181
172
|
it 'replaces content via PUT' do
|
182
|
-
uuid =
|
183
|
-
|
173
|
+
uuid = handler.datastore.save( text_io )
|
174
|
+
handler.metastore.save( uuid, {'format' => 'text/plain'} )
|
184
175
|
|
185
|
-
req = factory.put( "/#{uuid}",
|
186
|
-
req.headers.content_length =
|
187
|
-
res =
|
176
|
+
req = factory.put( "/#{uuid}", png_io, content_type: 'image/png' )
|
177
|
+
req.headers.content_length = png_io.read.bytesize
|
178
|
+
res = handler.handle( req )
|
188
179
|
|
189
180
|
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
190
|
-
expect(
|
191
|
-
expect(
|
181
|
+
expect( handler.datastore.fetch(uuid).read ).to eq( TEST_PNG_DATA )
|
182
|
+
expect( handler.metastore.fetch(uuid) ).to include( 'format' => 'image/png' )
|
192
183
|
end
|
193
184
|
|
194
185
|
|
195
186
|
it "doesn't care about the case of the UUID when replacing content via PUT" do
|
196
|
-
uuid =
|
197
|
-
|
187
|
+
uuid = handler.datastore.save( text_io )
|
188
|
+
handler.metastore.save( uuid, {'format' => 'text/plain'} )
|
198
189
|
|
199
|
-
req = factory.put( "/#{uuid.upcase}",
|
200
|
-
req.headers.content_length =
|
201
|
-
res =
|
190
|
+
req = factory.put( "/#{uuid.upcase}", png_io, content_type: 'image/png' )
|
191
|
+
req.headers.content_length = png_io.read.bytesize
|
192
|
+
res = handler.handle( req )
|
202
193
|
|
203
194
|
expect( res.status ).to eq( HTTP::NO_CONTENT )
|
204
|
-
expect(
|
205
|
-
expect(
|
195
|
+
expect( handler.datastore.fetch(uuid).read ).to eq( TEST_PNG_DATA )
|
196
|
+
expect( handler.metastore.fetch(uuid) ).to include( 'format' => 'image/png' )
|
206
197
|
end
|
207
198
|
|
208
199
|
|
209
200
|
it 'can fetch all uploaded data' do
|
210
|
-
text_uuid =
|
211
|
-
|
201
|
+
text_uuid = handler.datastore.save( text_io )
|
202
|
+
handler.metastore.save( text_uuid, {
|
212
203
|
'format' => 'text/plain',
|
213
|
-
'extent' =>
|
204
|
+
'extent' => text_io.string.bytesize
|
214
205
|
})
|
215
|
-
png_uuid =
|
216
|
-
|
206
|
+
png_uuid = handler.datastore.save( png_io )
|
207
|
+
handler.metastore.save( png_uuid, {
|
217
208
|
'format' => 'image/png',
|
218
|
-
'extent' =>
|
209
|
+
'extent' => png_io.string.bytesize
|
219
210
|
})
|
220
211
|
|
221
212
|
req = factory.get( '/' )
|
222
|
-
res =
|
213
|
+
res = handler.handle( req )
|
223
214
|
content = Yajl::Parser.parse( res.body.read )
|
224
215
|
|
225
216
|
expect( res.status_line ).to match( /200 ok/i )
|
@@ -228,30 +219,30 @@ describe Thingfish::Handler do
|
|
228
219
|
expect( content[0] ).to be_a( Hash )
|
229
220
|
expect( content[0]['uri'] ).to eq( "#{req.base_uri}#{text_uuid}" )
|
230
221
|
expect( content[0]['format'] ).to eq( "text/plain" )
|
231
|
-
expect( content[0]['extent'] ).to eq(
|
222
|
+
expect( content[0]['extent'] ).to eq( text_io.string.bytesize )
|
232
223
|
expect( content[1] ).to be_a( Hash )
|
233
224
|
expect( content[1]['uri'] ).to eq( "#{req.base_uri}#{png_uuid}" )
|
234
225
|
expect( content[1]['format'] ).to eq( 'image/png' )
|
235
|
-
expect( content[1]['extent'] ).to eq(
|
226
|
+
expect( content[1]['extent'] ).to eq( png_io.string.bytesize )
|
236
227
|
end
|
237
228
|
|
238
229
|
|
239
230
|
it 'can fetch all related data for a single resource' do
|
240
|
-
main_uuid =
|
241
|
-
|
231
|
+
main_uuid = handler.datastore.save( png_io )
|
232
|
+
handler.metastore.save( main_uuid, {
|
242
233
|
'format' => 'image/png',
|
243
|
-
'extent' =>
|
234
|
+
'extent' => png_io.string.bytesize
|
244
235
|
})
|
245
|
-
related_uuid =
|
246
|
-
|
236
|
+
related_uuid = handler.datastore.save( png_io )
|
237
|
+
handler.metastore.save( related_uuid, {
|
247
238
|
'format' => 'image/png',
|
248
|
-
'extent' =>
|
239
|
+
'extent' => png_io.string.bytesize,
|
249
240
|
'relation' => main_uuid,
|
250
241
|
'relationship' => "twinsies"
|
251
242
|
})
|
252
243
|
|
253
244
|
req = factory.get( "/#{main_uuid}/related" )
|
254
|
-
res =
|
245
|
+
res = handler.handle( req )
|
255
246
|
content = Yajl::Parser.parse( res.body.read )
|
256
247
|
|
257
248
|
expect( res.status_line ).to match( /200 ok/i )
|
@@ -260,22 +251,22 @@ describe Thingfish::Handler do
|
|
260
251
|
expect( content[0] ).to be_a( Hash )
|
261
252
|
expect( content[0]['uri'] ).to eq( "#{req.base_uri}#{related_uuid}" )
|
262
253
|
expect( content[0]['format'] ).to eq( "image/png" )
|
263
|
-
expect( content[0]['extent'] ).to eq(
|
254
|
+
expect( content[0]['extent'] ).to eq( png_io.string.bytesize )
|
264
255
|
expect( content[0]['uuid'] ).to eq( related_uuid )
|
265
256
|
expect( content[0]['relation'] ).to eq( main_uuid )
|
266
257
|
end
|
267
258
|
|
268
259
|
|
269
260
|
it 'can fetch a related resource by name' do
|
270
|
-
main_uuid =
|
271
|
-
|
261
|
+
main_uuid = handler.datastore.save( png_io )
|
262
|
+
handler.metastore.save( main_uuid, {
|
272
263
|
'format' => 'image/png',
|
273
|
-
'extent' =>
|
264
|
+
'extent' => png_io.string.bytesize
|
274
265
|
})
|
275
|
-
related_uuid =
|
276
|
-
|
266
|
+
related_uuid = handler.datastore.save( png_io )
|
267
|
+
handler.metastore.save( related_uuid, {
|
277
268
|
'format' => 'image/png',
|
278
|
-
'extent' =>
|
269
|
+
'extent' => png_io.string.bytesize,
|
279
270
|
'relation' => main_uuid,
|
280
271
|
'relationship' => "twinsies",
|
281
272
|
'title' => 'Make America Smart Again.png',
|
@@ -283,7 +274,7 @@ describe Thingfish::Handler do
|
|
283
274
|
})
|
284
275
|
|
285
276
|
req = factory.get( "/#{main_uuid}/related/twinsies" )
|
286
|
-
res =
|
277
|
+
res = handler.handle( req )
|
287
278
|
|
288
279
|
expect( res.status_line ).to match( /200 ok/i )
|
289
280
|
expect( res.headers.content_type ).to eq( 'image/png' )
|
@@ -295,77 +286,77 @@ describe Thingfish::Handler do
|
|
295
286
|
|
296
287
|
it "404s when attempting to fetch a resource related to a non-existant resource" do
|
297
288
|
req = factory.get( "/#{TEST_UUID}/related/twinsies" )
|
298
|
-
res =
|
289
|
+
res = handler.handle( req )
|
299
290
|
|
300
291
|
expect( res.status_line ).to match( /404 not found/i )
|
301
292
|
end
|
302
293
|
|
303
294
|
|
304
295
|
it "404s when attempting to fetch a related resource that doesn't exist" do
|
305
|
-
uuid =
|
306
|
-
|
296
|
+
uuid = handler.datastore.save( png_io )
|
297
|
+
handler.metastore.save( uuid, {
|
307
298
|
'format' => 'image/png',
|
308
|
-
'extent' =>
|
299
|
+
'extent' => png_io.string.bytesize
|
309
300
|
})
|
310
301
|
|
311
302
|
req = factory.get( "/#{uuid}/related/twinsies" )
|
312
|
-
res =
|
303
|
+
res = handler.handle( req )
|
313
304
|
|
314
305
|
expect( res.status_line ).to match( /404 not found/i )
|
315
306
|
end
|
316
307
|
|
317
308
|
|
318
309
|
it "can fetch an uploaded chunk of data" do
|
319
|
-
uuid =
|
320
|
-
|
310
|
+
uuid = handler.datastore.save( png_io )
|
311
|
+
handler.metastore.save( uuid, {'format' => 'image/png'} )
|
321
312
|
|
322
313
|
req = factory.get( "/#{uuid}" )
|
323
|
-
result =
|
314
|
+
result = handler.handle( req )
|
324
315
|
|
325
316
|
expect( result.status_line ).to match( /200 ok/i )
|
326
|
-
expect( result.body.read ).to eq(
|
317
|
+
expect( result.body.read ).to eq( png_io.string )
|
327
318
|
expect( result.headers.content_type ).to eq( 'image/png' )
|
328
319
|
end
|
329
320
|
|
330
321
|
|
331
322
|
it "returns a 404 Not Found when asked to fetch an object that doesn't exist" do
|
332
323
|
req = factory.get( "/#{TEST_UUID}" )
|
333
|
-
result =
|
324
|
+
result = handler.handle( req )
|
334
325
|
|
335
326
|
expect( result.status_line ).to match( /404 not found/i )
|
336
327
|
end
|
337
328
|
|
338
329
|
|
339
330
|
it "returns a 404 Not Found when asked to fetch an object that doesn't exist in the metastore" do
|
340
|
-
uuid =
|
331
|
+
uuid = handler.datastore.save( png_io )
|
341
332
|
|
342
333
|
req = factory.get( "/#{uuid}" )
|
343
|
-
result =
|
334
|
+
result = handler.handle( req )
|
344
335
|
|
345
336
|
expect( result.status_line ).to match( /404 not found/i )
|
346
337
|
end
|
347
338
|
|
348
339
|
|
349
340
|
it "doesn't care about the case of the UUID when fetching uploaded data" do
|
350
|
-
uuid =
|
351
|
-
|
341
|
+
uuid = handler.datastore.save( png_io )
|
342
|
+
handler.metastore.save( uuid, {'format' => 'image/png'} )
|
352
343
|
|
353
344
|
req = factory.get( "/#{uuid.upcase}" )
|
354
|
-
result =
|
345
|
+
result = handler.handle( req )
|
355
346
|
|
356
347
|
expect( result.status_line ).to match( /200 ok/i )
|
357
|
-
expect( result.body.read ).to eq(
|
348
|
+
expect( result.body.read ).to eq( png_io.string )
|
358
349
|
expect( result.headers.content_type ).to eq( 'image/png' )
|
359
350
|
end
|
360
351
|
|
361
352
|
|
362
353
|
it "adds date cache headers to resources" do
|
363
354
|
created = Time.now
|
364
|
-
uuid =
|
365
|
-
|
355
|
+
uuid = handler.datastore.save( png_io )
|
356
|
+
handler.metastore.save( uuid, 'format' => 'image/png', 'created' => created )
|
366
357
|
|
367
358
|
req = factory.get( "/#{uuid}" )
|
368
|
-
result =
|
359
|
+
result = handler.handle( req )
|
369
360
|
|
370
361
|
expect( result.status_line ).to match( /200 ok/i )
|
371
362
|
expect( result.headers.last_modified ).to eq( created.httpdate )
|
@@ -373,11 +364,11 @@ describe Thingfish::Handler do
|
|
373
364
|
|
374
365
|
|
375
366
|
it "adds content cache headers to resources with a checksum attribute" do
|
376
|
-
uuid =
|
377
|
-
|
367
|
+
uuid = handler.datastore.save( png_io )
|
368
|
+
handler.metastore.save( uuid, 'format' => 'image/png', 'checksum' => '123456' )
|
378
369
|
|
379
370
|
req = factory.get( "/#{uuid}" )
|
380
|
-
result =
|
371
|
+
result = handler.handle( req )
|
381
372
|
|
382
373
|
expect( result.status_line ).to match( /200 ok/i )
|
383
374
|
expect( result.headers.etag ).to eq( '123456' )
|
@@ -385,14 +376,14 @@ describe Thingfish::Handler do
|
|
385
376
|
|
386
377
|
|
387
378
|
it "adds content disposition filename, if the resource has a title" do
|
388
|
-
uuid =
|
389
|
-
|
379
|
+
uuid = handler.datastore.save( png_io )
|
380
|
+
handler.metastore.save( uuid, {'format' => 'image/png', 'title' => 'spょler"py.txt'} )
|
390
381
|
|
391
382
|
req = factory.get( "/#{uuid}" )
|
392
|
-
result =
|
383
|
+
result = handler.handle( req )
|
393
384
|
|
394
385
|
expect( result.status_line ).to match( /200 ok/i )
|
395
|
-
expect( result.body.read ).to eq(
|
386
|
+
expect( result.body.read ).to eq( png_io.string )
|
396
387
|
expect( result.headers.content_type ).to eq( 'image/png' )
|
397
388
|
expect( result.headers.content_disposition ).to eq( 'filename="sp?ler\"py.txt"' )
|
398
389
|
end
|
@@ -400,12 +391,12 @@ describe Thingfish::Handler do
|
|
400
391
|
|
401
392
|
it "returns a 304 not modified for unchanged date cache requests" do
|
402
393
|
created = Time.now
|
403
|
-
uuid =
|
404
|
-
|
394
|
+
uuid = handler.datastore.save( png_io )
|
395
|
+
handler.metastore.save( uuid, 'format' => 'image/png', 'created' => created )
|
405
396
|
|
406
397
|
req = factory.get( "/#{uuid}" )
|
407
398
|
req.headers[ :if_modified_since ] = ( Time.now - 300 ).httpdate
|
408
|
-
result =
|
399
|
+
result = handler.handle( req )
|
409
400
|
|
410
401
|
expect( result.status_line ).to match( /304 not modified/i )
|
411
402
|
expect( result.body.read ).to be_empty
|
@@ -413,12 +404,12 @@ describe Thingfish::Handler do
|
|
413
404
|
|
414
405
|
|
415
406
|
it "returns a 304 not modified for unchanged content cache requests" do
|
416
|
-
uuid =
|
417
|
-
|
407
|
+
uuid = handler.datastore.save( png_io )
|
408
|
+
handler.metastore.save( uuid, 'format' => 'image/png', 'checksum' => '123456' )
|
418
409
|
|
419
410
|
req = factory.get( "/#{uuid}" )
|
420
411
|
req.headers[ :if_none_match ] = '123456'
|
421
|
-
result =
|
412
|
+
result = handler.handle( req )
|
422
413
|
|
423
414
|
expect( result.status_line ).to match( /304 not modified/i )
|
424
415
|
expect( result.body.read ).to be_empty
|
@@ -426,24 +417,24 @@ describe Thingfish::Handler do
|
|
426
417
|
|
427
418
|
|
428
419
|
it "can remove everything associated with an object id" do
|
429
|
-
uuid =
|
430
|
-
|
420
|
+
uuid = handler.datastore.save( png_io )
|
421
|
+
handler.metastore.save( uuid, {
|
431
422
|
'format' => 'image/png',
|
432
423
|
'extent' => 288,
|
433
424
|
})
|
434
425
|
|
435
426
|
req = factory.delete( "/#{uuid}" )
|
436
|
-
result =
|
427
|
+
result = handler.handle( req )
|
437
428
|
|
438
429
|
expect( result.status_line ).to match( /200 ok/i )
|
439
|
-
expect(
|
440
|
-
expect(
|
430
|
+
expect( handler.metastore.include?(uuid) ).to be_falsey
|
431
|
+
expect( handler.datastore.include?(uuid) ).to be_falsey
|
441
432
|
end
|
442
433
|
|
443
434
|
|
444
435
|
it "returns a 404 Not Found when asked to remove an object that doesn't exist" do
|
445
436
|
req = factory.delete( "/#{TEST_UUID}" )
|
446
|
-
result =
|
437
|
+
result = handler.handle( req )
|
447
438
|
|
448
439
|
expect( result.status_line ).to match( /404 not found/i )
|
449
440
|
end
|
@@ -461,15 +452,15 @@ describe Thingfish::Handler do
|
|
461
452
|
end
|
462
453
|
|
463
454
|
it "can fetch the metadata associated with uploaded data" do
|
464
|
-
uuid =
|
465
|
-
|
455
|
+
uuid = handler.datastore.save( png_io )
|
456
|
+
handler.metastore.save( uuid, {
|
466
457
|
'format' => 'image/png',
|
467
458
|
'extent' => 288,
|
468
459
|
'created' => Time.at(1378313840),
|
469
460
|
})
|
470
461
|
|
471
462
|
req = factory.get( "/#{uuid}/metadata" )
|
472
|
-
result =
|
463
|
+
result = handler.handle( req )
|
473
464
|
content = result.body.read
|
474
465
|
|
475
466
|
content_hash = Yajl::Parser.parse( content )
|
@@ -485,21 +476,21 @@ describe Thingfish::Handler do
|
|
485
476
|
|
486
477
|
it "returns a 404 Not Found when fetching metadata for an object that doesn't exist" do
|
487
478
|
req = factory.get( "/#{TEST_UUID}/metadata" )
|
488
|
-
result =
|
479
|
+
result = handler.handle( req )
|
489
480
|
|
490
481
|
expect( result.status_line ).to match( /404 not found/i )
|
491
482
|
end
|
492
483
|
|
493
484
|
|
494
485
|
it "can fetch a value for a single metadata key" do
|
495
|
-
uuid =
|
496
|
-
|
486
|
+
uuid = handler.datastore.save( png_io )
|
487
|
+
handler.metastore.save( uuid, {
|
497
488
|
'format' => 'image/png',
|
498
489
|
'extent' => 288,
|
499
490
|
})
|
500
491
|
|
501
492
|
req = factory.get( "/#{uuid}/metadata/extent" )
|
502
|
-
result =
|
493
|
+
result = handler.handle( req )
|
503
494
|
result.body.rewind
|
504
495
|
content = result.body.read
|
505
496
|
|
@@ -511,21 +502,21 @@ describe Thingfish::Handler do
|
|
511
502
|
|
512
503
|
it "returns a 404 Not Found when fetching a single metadata value for a uuid that doesn't exist" do
|
513
504
|
req = factory.get( "/#{TEST_UUID}/metadata/extent" )
|
514
|
-
result =
|
505
|
+
result = handler.handle( req )
|
515
506
|
|
516
507
|
expect( result.status_line ).to match( /404 not found/i )
|
517
508
|
end
|
518
509
|
|
519
510
|
|
520
511
|
it "doesn't error when fetching a non-existent metadata value" do
|
521
|
-
uuid =
|
522
|
-
|
512
|
+
uuid = handler.datastore.save( png_io )
|
513
|
+
handler.metastore.save( uuid, {
|
523
514
|
'format' => 'image/png',
|
524
515
|
'extent' => 288,
|
525
516
|
})
|
526
517
|
|
527
518
|
req = factory.get( "/#{uuid}/metadata/hururrgghh" )
|
528
|
-
result =
|
519
|
+
result = handler.handle( req )
|
529
520
|
|
530
521
|
content = Yajl::Parser.parse( result.body.read )
|
531
522
|
|
@@ -537,58 +528,58 @@ describe Thingfish::Handler do
|
|
537
528
|
|
538
529
|
|
539
530
|
it "can merge in new metadata for an existing resource with a POST" do
|
540
|
-
uuid =
|
541
|
-
|
531
|
+
uuid = handler.datastore.save( png_io )
|
532
|
+
handler.metastore.save( uuid, {
|
542
533
|
'format' => 'image/png',
|
543
534
|
'extent' => 288
|
544
535
|
})
|
545
536
|
|
546
537
|
body_json = Yajl.dump({ 'comment' => 'Ignore me!', 'uuid' => 123 })
|
547
538
|
req = factory.post( "/#{uuid}/metadata", body_json, 'Content-type' => 'application/json' )
|
548
|
-
result =
|
539
|
+
result = handler.handle( req )
|
549
540
|
|
550
541
|
expect( result.status ).to eq( HTTP::OK )
|
551
|
-
expect(
|
552
|
-
expect(
|
542
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to eq( 'Ignore me!' )
|
543
|
+
expect( handler.metastore.fetch_value(uuid, 'uuid') ).to be_nil
|
553
544
|
end
|
554
545
|
|
555
546
|
|
556
547
|
it "ignores attempts to alter operational metadata when merging" do
|
557
|
-
uuid =
|
558
|
-
|
548
|
+
uuid = handler.datastore.save( png_io )
|
549
|
+
handler.metastore.save( uuid, {
|
559
550
|
'format' => 'image/png',
|
560
551
|
'extent' => 288,
|
561
552
|
})
|
562
553
|
|
563
554
|
body_json = Yajl.dump({ 'format' => 'text/plain', 'comment' => 'Ignore me!' })
|
564
555
|
req = factory.post( "/#{uuid}/metadata", body_json, 'Content-type' => 'application/json' )
|
565
|
-
result =
|
556
|
+
result = handler.handle( req )
|
566
557
|
|
567
558
|
expect( result.status ).to eq( HTTP::OK )
|
568
|
-
expect(
|
569
|
-
expect(
|
559
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to eq( 'Ignore me!' )
|
560
|
+
expect( handler.metastore.fetch_value(uuid, 'format') ).to eq( 'image/png' )
|
570
561
|
end
|
571
562
|
|
572
563
|
|
573
564
|
it "can create single metadata values with a POST" do
|
574
|
-
uuid =
|
575
|
-
|
565
|
+
uuid = handler.datastore.save( png_io )
|
566
|
+
handler.metastore.save( uuid, {
|
576
567
|
'format' => 'image/png',
|
577
568
|
'extent' => 288,
|
578
569
|
})
|
579
570
|
|
580
571
|
req = factory.post( "/#{uuid}/metadata/comment", "urrrg", 'Content-type' => 'text/plain' )
|
581
|
-
result =
|
572
|
+
result = handler.handle( req )
|
582
573
|
|
583
574
|
expect( result.status ).to eq( HTTP::CREATED )
|
584
575
|
expect( result.headers.location ).to match( %r|#{uuid}/metadata/comment$| )
|
585
|
-
expect(
|
576
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to eq( 'urrrg' )
|
586
577
|
end
|
587
578
|
|
588
579
|
|
589
580
|
it "returns NOT_FOUND when attempting to create metadata for a non-existent object" do
|
590
581
|
req = factory.post( "/#{TEST_UUID}/metadata/comment", "urrrg", 'Content-type' => 'text/plain' )
|
591
|
-
result =
|
582
|
+
result = handler.handle( req )
|
592
583
|
|
593
584
|
expect( result.status ).to eq( HTTP::NOT_FOUND )
|
594
585
|
expect( result.body.string ).to match( /no such object/i )
|
@@ -596,73 +587,73 @@ describe Thingfish::Handler do
|
|
596
587
|
|
597
588
|
|
598
589
|
it "returns CONFLICT when attempting to create a single metadata value if it already exists" do
|
599
|
-
uuid =
|
600
|
-
|
590
|
+
uuid = handler.datastore.save( png_io )
|
591
|
+
handler.metastore.save( uuid, {
|
601
592
|
'format' => 'image/png',
|
602
593
|
'extent' => 288,
|
603
594
|
'comment' => 'nill bill'
|
604
595
|
})
|
605
596
|
|
606
597
|
req = factory.post( "/#{uuid}/metadata/comment", "urrrg", 'Content-type' => 'text/plain' )
|
607
|
-
result =
|
598
|
+
result = handler.handle( req )
|
608
599
|
|
609
600
|
expect( result.status ).to eq( HTTP::CONFLICT )
|
610
601
|
expect( result.body.string ).to match( /already exists/i )
|
611
|
-
expect(
|
602
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to eq( 'nill bill' )
|
612
603
|
end
|
613
604
|
|
614
605
|
|
615
606
|
it "can create single metadata values with a PUT" do
|
616
|
-
uuid =
|
617
|
-
|
607
|
+
uuid = handler.datastore.save( png_io )
|
608
|
+
handler.metastore.save( uuid, {
|
618
609
|
'format' => 'image/png',
|
619
610
|
'extent' => 288,
|
620
611
|
})
|
621
612
|
|
622
613
|
req = factory.put( "/#{uuid}/metadata/comment", "urrrg", 'Content-type' => 'text/plain' )
|
623
|
-
result =
|
614
|
+
result = handler.handle( req )
|
624
615
|
|
625
616
|
expect( result.status ).to eq( HTTP::NO_CONTENT )
|
626
|
-
expect(
|
617
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to eq( 'urrrg' )
|
627
618
|
end
|
628
619
|
|
629
620
|
|
630
621
|
it "can replace a single metadata value with a PUT" do
|
631
|
-
uuid =
|
632
|
-
|
622
|
+
uuid = handler.datastore.save( png_io )
|
623
|
+
handler.metastore.save( uuid, {
|
633
624
|
'format' => 'image/png',
|
634
625
|
'extent' => 288,
|
635
626
|
'comment' => 'nill bill'
|
636
627
|
})
|
637
628
|
|
638
629
|
req = factory.put( "/#{uuid}/metadata/comment", "urrrg", 'Content-type' => 'text/plain' )
|
639
|
-
result =
|
630
|
+
result = handler.handle( req )
|
640
631
|
|
641
632
|
expect( result.status ).to eq( HTTP::NO_CONTENT )
|
642
|
-
expect(
|
633
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to eq( 'urrrg' )
|
643
634
|
end
|
644
635
|
|
645
636
|
|
646
637
|
it "returns FORBIDDEN when attempting to replace a operational metadata value with a PUT" do
|
647
|
-
uuid =
|
648
|
-
|
638
|
+
uuid = handler.datastore.save( png_io )
|
639
|
+
handler.metastore.save( uuid, {
|
649
640
|
'format' => 'image/png',
|
650
641
|
'extent' => 288,
|
651
642
|
'comment' => 'nill bill'
|
652
643
|
})
|
653
644
|
|
654
645
|
req = factory.put( "/#{uuid}/metadata/format", "image/gif", 'Content-type' => 'text/plain' )
|
655
|
-
result =
|
646
|
+
result = handler.handle( req )
|
656
647
|
|
657
648
|
expect( result.status ).to eq( HTTP::FORBIDDEN )
|
658
649
|
expect( result.body.string ).to match( /protected metadata/i )
|
659
|
-
expect(
|
650
|
+
expect( handler.metastore.fetch_value(uuid, 'format') ).to eq( 'image/png' )
|
660
651
|
end
|
661
652
|
|
662
653
|
|
663
654
|
it "can replace all metadata with a PUT" do
|
664
|
-
uuid =
|
665
|
-
|
655
|
+
uuid = handler.datastore.save( png_io )
|
656
|
+
handler.metastore.save( uuid, {
|
666
657
|
'format' => 'image/png',
|
667
658
|
'extent' => 288,
|
668
659
|
'comment' => 'nill bill',
|
@@ -671,19 +662,19 @@ describe Thingfish::Handler do
|
|
671
662
|
|
672
663
|
req = factory.put( "/#{uuid}/metadata", %[{"comment":"Yeah."}],
|
673
664
|
'Content-type' => 'application/json' )
|
674
|
-
result =
|
665
|
+
result = handler.handle( req )
|
675
666
|
|
676
667
|
expect( result.status ).to eq( HTTP::OK )
|
677
|
-
expect(
|
678
|
-
expect(
|
679
|
-
expect(
|
668
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to eq( 'Yeah.' )
|
669
|
+
expect( handler.metastore.fetch_value(uuid, 'format') ).to eq( 'image/png' )
|
670
|
+
expect( handler.metastore ).to_not include( 'ephemeral' )
|
680
671
|
end
|
681
672
|
|
682
673
|
|
683
674
|
it "can remove all non-default metadata with a DELETE" do
|
684
675
|
timestamp = Time.now.getgm
|
685
|
-
uuid =
|
686
|
-
|
676
|
+
uuid = handler.datastore.save( png_io )
|
677
|
+
handler.metastore.save( uuid, {
|
687
678
|
'format' => 'image/png',
|
688
679
|
'extent' => 288,
|
689
680
|
'comment' => 'nill bill',
|
@@ -693,49 +684,49 @@ describe Thingfish::Handler do
|
|
693
684
|
})
|
694
685
|
|
695
686
|
req = factory.delete( "/#{uuid}/metadata" )
|
696
|
-
result =
|
687
|
+
result = handler.handle( req )
|
697
688
|
|
698
689
|
expect( result.status ).to eq( HTTP::OK )
|
699
690
|
expect( result.body.string ).to_not be_empty
|
700
|
-
expect(
|
701
|
-
expect(
|
702
|
-
expect(
|
703
|
-
expect(
|
691
|
+
expect( handler.metastore.fetch_value(uuid, 'format') ).to eq( 'image/png' )
|
692
|
+
expect( handler.metastore.fetch_value(uuid, 'extent') ).to eq( 288 )
|
693
|
+
expect( handler.metastore.fetch_value(uuid, 'uploadaddress') ).to eq( '127.0.0.1' )
|
694
|
+
expect( handler.metastore.fetch_value(uuid, 'created') ).to eq( timestamp )
|
704
695
|
|
705
|
-
expect(
|
706
|
-
expect(
|
696
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to be_nil
|
697
|
+
expect( handler.metastore.fetch_value(uuid, 'useragent') ).to be_nil
|
707
698
|
end
|
708
699
|
|
709
700
|
|
710
701
|
it "can remove a single metadata value with DELETE" do
|
711
|
-
uuid =
|
712
|
-
|
702
|
+
uuid = handler.datastore.save( png_io )
|
703
|
+
handler.metastore.save( uuid, {
|
713
704
|
'format' => 'image/png',
|
714
705
|
'comment' => 'nill bill'
|
715
706
|
})
|
716
707
|
|
717
708
|
req = factory.delete( "/#{uuid}/metadata/comment" )
|
718
|
-
result =
|
709
|
+
result = handler.handle( req )
|
719
710
|
|
720
711
|
expect( result.status ).to eq( HTTP::NO_CONTENT )
|
721
712
|
expect( result.body.string ).to be_empty
|
722
|
-
expect(
|
723
|
-
expect(
|
713
|
+
expect( handler.metastore.fetch_value(uuid, 'comment') ).to be_nil
|
714
|
+
expect( handler.metastore.fetch_value(uuid, 'format') ).to eq( 'image/png' )
|
724
715
|
end
|
725
716
|
|
726
717
|
|
727
718
|
it "returns FORBIDDEN when attempting to remove a operational metadata value with a DELETE" do
|
728
|
-
uuid =
|
729
|
-
|
719
|
+
uuid = handler.datastore.save( png_io )
|
720
|
+
handler.metastore.save( uuid, {
|
730
721
|
'format' => 'image/png'
|
731
722
|
})
|
732
723
|
|
733
724
|
req = factory.delete( "/#{uuid}/metadata/format" )
|
734
|
-
result =
|
725
|
+
result = handler.handle( req )
|
735
726
|
|
736
727
|
expect( result.status ).to eq( HTTP::FORBIDDEN )
|
737
728
|
expect( result.body.string ).to match( /protected metadata/i )
|
738
|
-
expect(
|
729
|
+
expect( handler.metastore.fetch_value(uuid, 'format') ).to eq( 'image/png' )
|
739
730
|
end
|
740
731
|
end
|
741
732
|
|
@@ -820,23 +811,23 @@ describe Thingfish::Handler do
|
|
820
811
|
|
821
812
|
req = factory.post( '/', TEST_TEXT_DATA, content_type: 'text/plain' )
|
822
813
|
req.headers.content_length = TEST_TEXT_DATA.bytesize
|
823
|
-
res =
|
814
|
+
res = handler.handle( req )
|
824
815
|
uuid = res.headers.x_thingfish_uuid
|
825
816
|
|
826
|
-
Thingfish.logger.debug "Metastore contains: %p" % [
|
817
|
+
Thingfish.logger.debug "Metastore contains: %p" % [ handler.metastore.storage ]
|
827
818
|
|
828
|
-
expect(
|
819
|
+
expect( handler.metastore.fetch(uuid) ).
|
829
820
|
to include( 'test:comment' => 'Yo, it totally worked.')
|
830
|
-
related_uuids =
|
821
|
+
related_uuids = handler.metastore.fetch_related_oids( uuid )
|
831
822
|
expect( related_uuids.size ).to eq( 1 )
|
832
823
|
|
833
824
|
r_uuid = related_uuids.first.downcase
|
834
|
-
expect(
|
835
|
-
expect(
|
836
|
-
expect(
|
837
|
-
expect(
|
825
|
+
expect( handler.metastore.fetch_value(r_uuid, 'relation') ).to eq( uuid )
|
826
|
+
expect( handler.metastore.fetch_value(r_uuid, 'format') ).to eq( 'text/plain' )
|
827
|
+
expect( handler.metastore.fetch_value(r_uuid, 'extent') ).to eq( 9 )
|
828
|
+
expect( handler.metastore.fetch_value(r_uuid, 'relationship') ).to eq( 'comment' )
|
838
829
|
|
839
|
-
expect(
|
830
|
+
expect( handler.datastore.fetch(r_uuid).read ).to eq( 'Chunkers!' )
|
840
831
|
end
|
841
832
|
|
842
833
|
|
@@ -845,7 +836,7 @@ describe Thingfish::Handler do
|
|
845
836
|
processor = described_class.processors.first
|
846
837
|
|
847
838
|
req = factory.post( "/#{TEST_UUID}/metadata", TEST_TEXT_DATA, content_type: 'text/plain' )
|
848
|
-
|
839
|
+
handler.handle( req )
|
849
840
|
|
850
841
|
expect( processor.was_called ).to be_falsey
|
851
842
|
end
|
@@ -854,11 +845,11 @@ describe Thingfish::Handler do
|
|
854
845
|
it "processes responses" do
|
855
846
|
described_class.configure( :processors => %w[test] )
|
856
847
|
|
857
|
-
uuid =
|
858
|
-
|
848
|
+
uuid = handler.datastore.save( text_io )
|
849
|
+
handler.metastore.save( uuid, {'format' => 'text/plain'} )
|
859
850
|
|
860
851
|
req = factory.get( "/#{uuid}" )
|
861
|
-
res =
|
852
|
+
res = handler.handle( req )
|
862
853
|
|
863
854
|
res.body.rewind
|
864
855
|
expect( res.body.read ).to eq( TEST_TEXT_DATA.reverse )
|
@@ -869,11 +860,11 @@ describe Thingfish::Handler do
|
|
869
860
|
described_class.configure( :processors => %w[test] )
|
870
861
|
processor = described_class.processors.first
|
871
862
|
|
872
|
-
uuid =
|
873
|
-
|
863
|
+
uuid = handler.datastore.save( text_io )
|
864
|
+
handler.metastore.save( uuid, {'format' => 'text/plain'} )
|
874
865
|
|
875
866
|
req = factory.get( "/#{uuid}/metadata" )
|
876
|
-
|
867
|
+
handler.handle( req )
|
877
868
|
|
878
869
|
expect( processor.was_called ).to be_falsey
|
879
870
|
end
|
@@ -889,12 +880,12 @@ describe Thingfish::Handler do
|
|
889
880
|
end
|
890
881
|
|
891
882
|
before( :each ) do
|
892
|
-
|
883
|
+
handler.setup_event_socket
|
893
884
|
|
894
885
|
@subsock = CZTop::Socket::SUB.new
|
895
886
|
@subsock.options.linger = 0
|
896
887
|
@subsock.subscribe( '' )
|
897
|
-
@subsock.connect(
|
888
|
+
@subsock.connect( handler.event_socket.last_endpoint )
|
898
889
|
end
|
899
890
|
|
900
891
|
after( :each ) do
|
@@ -908,7 +899,7 @@ describe Thingfish::Handler do
|
|
908
899
|
poller = CZTop::Poller.new
|
909
900
|
poller.add_reader( @subsock )
|
910
901
|
|
911
|
-
|
902
|
+
handler.handle( req )
|
912
903
|
event = poller.wait( 500 )
|
913
904
|
|
914
905
|
expect( event ).to_not be_nil
|