thingfish 0.7.0 → 0.8.0
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 +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
|