thingfish 0.5.0.pre20161103181816 → 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 -26
- data/Rakefile +4 -88
- data/bin/thingfish +1 -1
- data/lib/strelka/app/metadata.rb +1 -1
- data/lib/strelka/apps.rb +9 -0
- data/lib/strelka/httprequest/metadata.rb +1 -1
- data/lib/thingfish.rb +2 -13
- 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 +94 -53
- 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 +51 -0
- 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 +235 -201
- 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/{mp3_spec.rb → sha256_spec.rb} +10 -11
- data/spec/thingfish/processor_spec.rb +1 -1
- data/spec/thingfish_spec.rb +1 -1
- metadata +61 -141
- metadata.gz.sig +0 -0
- data/History.rdoc +0 -5
- data/Manifest.txt +0 -44
- data/Procfile +0 -4
- data/bin/tfprocessord +0 -6
- data/etc/thingfish.conf.example +0 -26
- data/lib/thingfish/processor/mp3.rb +0 -167
- data/lib/thingfish/processordaemon.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 767d737d3f8a3ca3cae2d7f5b01fa7e7b1967127585efe3201b55fce50a46500
|
4
|
+
data.tar.gz: 769440ac44975755940720e4cd95a610c072874e3c5a1f709bcf3e7cf6cabf39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a83f80a9b4efa7c7e651f2fd1791e4424fa2bd63d6b304b4cc622cfcfc1fd2840ffd1fee370722cc4399453ac662efffc2591e51e054acb33e8e72e776d7a30c
|
7
|
+
data.tar.gz: d6244bb6e4b2c340f977f12ed0f19631bbdd6a10815973c44880c0ebbc8c841b6296744f7cb331ed71a776e26c2d7f24cac136b510afe1eceebe0eb110ff822c
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/History.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Release History for thingfish
|
2
|
+
|
3
|
+
---
|
4
|
+
|
5
|
+
## v0.8.0 [2021-01-02] Michael Granger <ged@FaerieMUD.org>
|
6
|
+
|
7
|
+
Improvements:
|
8
|
+
|
9
|
+
- Several bugfixes
|
10
|
+
- Support for newer Rubies
|
11
|
+
|
12
|
+
|
13
|
+
## v0.7.0 [2017-09-13] Michael Granger <ged@FaerieMUD.org>
|
14
|
+
|
15
|
+
Improvements:
|
16
|
+
|
17
|
+
- Explicitly set the HTTP status when returning resources.
|
18
|
+
- Add Last-Modified/If-None-Match support.
|
19
|
+
- Move the configure() method to help support deferred configuration.
|
20
|
+
|
21
|
+
|
22
|
+
## v0.6.0 [2017-01-16] Mahlon E. Smith <mahlon@martini.nu>
|
23
|
+
|
24
|
+
Housekeeping:
|
25
|
+
|
26
|
+
- Bump Configurability dependency.
|
27
|
+
- Migrate away from .rvmrc.
|
28
|
+
|
29
|
+
|
30
|
+
## v0.5.1 [2016-11-14] Michael Granger <ged@FaerieMUD.org>
|
31
|
+
|
32
|
+
Enhancements:
|
33
|
+
|
34
|
+
- Add support for Strelka app discovery.
|
35
|
+
|
36
|
+
Bugfixes:
|
37
|
+
|
38
|
+
- Remove the processor daemon for now
|
39
|
+
- Documentation fixes
|
40
|
+
|
41
|
+
|
42
|
+
## v0.5.0 [2016-11-14] Michael Granger <ged@FaerieMUD.org>
|
43
|
+
|
44
|
+
First public release.
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,8 +1,16 @@
|
|
1
|
-
|
1
|
+
# Thingfish
|
2
2
|
|
3
|
-
|
3
|
+
home
|
4
|
+
: https://thing.fish
|
4
5
|
|
5
|
-
|
6
|
+
code
|
7
|
+
: https://hg.sr.ht/~ged/thingfish
|
8
|
+
|
9
|
+
docs
|
10
|
+
: https://thing.fish/docs/
|
11
|
+
|
12
|
+
|
13
|
+
## Description
|
6
14
|
|
7
15
|
Thingfish is a extensible, web-based digital asset manager. It can be used to
|
8
16
|
store chunks of data on the network in an application-independent way, link the
|
@@ -10,38 +18,31 @@ chunks together with metadata, and then search for the chunk you need later and
|
|
10
18
|
fetch it, all through a REST API.
|
11
19
|
|
12
20
|
|
13
|
-
|
14
|
-
|
15
|
-
* Michael Granger <ged@FaerieMUD.org>
|
16
|
-
* Mahlon E. Smith <mahlon@martini.nu>
|
17
|
-
|
18
|
-
== Contributors
|
19
|
-
|
20
|
-
* Jeremiah Jordan <phaedrus@perlreason.com>
|
21
|
-
* Ben Bleything <ben@bleything.net>
|
22
|
-
* Jeff Davis <jeff-thingfish@j-davis.com>
|
23
|
-
|
21
|
+
## Requirements
|
24
22
|
|
25
|
-
|
23
|
+
Thingfish is written in ruby, and is tested using [version 2.7](http://www.ruby-lang.org/en/downloads/). Other versions may work,
|
24
|
+
but are not tested.
|
26
25
|
|
27
|
-
=== Requirements
|
28
26
|
|
29
|
-
|
27
|
+
## Installation
|
30
28
|
|
31
|
-
|
29
|
+
You can install Thingfish via Rubygems:
|
32
30
|
|
33
|
-
|
31
|
+
$ gem install thingfish
|
34
32
|
|
35
|
-
|
33
|
+
This will install the basic server and its dependencies. Additional functionality is available via separate gems in the following namespaces:
|
36
34
|
|
37
|
-
|
35
|
+
`thingfish-metastore-*`
|
36
|
+
: Storage backends for resource metadata
|
38
37
|
|
39
|
-
|
38
|
+
`thingfish-filestore-*`
|
39
|
+
: Storage backends for resources themselves
|
40
40
|
|
41
|
-
|
41
|
+
`thingfish-processor-*`
|
42
|
+
: Filters and extractors for resources
|
42
43
|
|
43
44
|
|
44
|
-
|
45
|
+
## Contributing
|
45
46
|
|
46
47
|
You can check out the current development source
|
47
48
|
{with Mercurial}[http://bitbucket.org/ged/thingfish], or
|
@@ -59,9 +60,22 @@ You can submit bug reports, suggestions, and read more about future plans at
|
|
59
60
|
{the project page}[http://bitbucket.org/ged/thingfish].
|
60
61
|
|
61
62
|
|
62
|
-
|
63
|
+
## Authors
|
64
|
+
|
65
|
+
* Michael Granger <ged@FaerieMUD.org>
|
66
|
+
* Mahlon E. Smith <mahlon@martini.nu>
|
67
|
+
|
68
|
+
|
69
|
+
## Contributors
|
70
|
+
|
71
|
+
* Jeremiah Jordan <phaedrus@perlreason.com>
|
72
|
+
* Ben Bleything <ben@bleything.net>
|
73
|
+
* Jeff Davis <jeff-thingfish@j-davis.com>
|
74
|
+
|
75
|
+
|
76
|
+
## License
|
63
77
|
|
64
|
-
Copyright (c) 2007-
|
78
|
+
Copyright (c) 2007-2020, Michael Granger and Mahlon E. Smith
|
65
79
|
All rights reserved.
|
66
80
|
|
67
81
|
Redistribution and use in source and binary forms, with or without
|
data/Rakefile
CHANGED
@@ -1,92 +1,8 @@
|
|
1
|
-
#!/usr/bin/env rake
|
2
|
-
#encoding: utf-8
|
1
|
+
#!/usr/bin/env ruby -S rake
|
3
2
|
|
4
|
-
|
5
|
-
require 'hoe'
|
6
|
-
rescue LoadError
|
7
|
-
abort "This Rakefile requires hoe (gem install hoe)"
|
8
|
-
end
|
9
|
-
|
10
|
-
GEMSPEC = 'thingfish.gemspec'
|
11
|
-
|
12
|
-
|
13
|
-
Hoe.plugin :mercurial
|
14
|
-
Hoe.plugin :signing
|
15
|
-
Hoe.plugin :deveiate
|
16
|
-
|
17
|
-
Hoe.plugins.delete :rubyforge
|
18
|
-
|
19
|
-
hoespec = Hoe.spec 'thingfish' do
|
20
|
-
self.readme_file = 'README.rdoc'
|
21
|
-
self.history_file = 'History.rdoc'
|
22
|
-
self.extra_rdoc_files = Rake::FileList[ '*.rdoc' ]
|
23
|
-
self.license 'BSD'
|
24
|
-
|
25
|
-
self.developer 'Michael Granger', 'ged@FaerieMUD.org'
|
26
|
-
self.developer 'Mahlon E. Smith', 'mahlon@martini.nu'
|
27
|
-
self.license "BSD"
|
28
|
-
|
29
|
-
self.dependency 'strelka', '~> 0.9'
|
30
|
-
self.dependency 'mongrel2', '~> 0.43'
|
31
|
-
|
32
|
-
self.dependency 'hoe-deveiate', '~> 0.3', :development
|
33
|
-
self.dependency 'simplecov', '~> 0.7', :development
|
34
|
-
self.dependency 'ruby-mp3info', '~> 0.8', :development
|
35
|
-
|
36
|
-
self.require_ruby_version( '>=2.0.0' )
|
37
|
-
|
38
|
-
self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
|
39
|
-
spec.check_history_on_release = true if spec.respond_to?( :check_history_on_release= )
|
40
|
-
|
41
|
-
self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
|
42
|
-
end
|
43
|
-
|
44
|
-
ENV['VERSION'] ||= hoespec.spec.version.to_s
|
45
|
-
|
46
|
-
# Run the tests before checking in
|
47
|
-
task 'hg:precheckin' => [ :check_history, :check_manifest, :gemspec, :spec ]
|
48
|
-
|
49
|
-
task :test => :spec
|
50
|
-
|
51
|
-
# Rebuild the ChangeLog immediately before release
|
52
|
-
task :prerelease => 'ChangeLog'
|
53
|
-
CLOBBER.include( 'ChangeLog' )
|
54
|
-
|
55
|
-
desc "Build a coverage report"
|
56
|
-
task :coverage do
|
57
|
-
ENV["COVERAGE"] = 'yes'
|
58
|
-
Rake::Task[:spec].invoke
|
59
|
-
end
|
60
|
-
CLOBBER.include( 'coverage' )
|
61
|
-
|
62
|
-
|
63
|
-
# Use the fivefish formatter for docs generated from development checkout
|
64
|
-
if File.directory?( '.hg' )
|
65
|
-
require 'rdoc/task'
|
3
|
+
require 'rake/deveiate'
|
66
4
|
|
67
|
-
|
68
|
-
|
69
|
-
rdoc.main = "README.rdoc"
|
70
|
-
rdoc.markup = 'markdown'
|
71
|
-
rdoc.rdoc_files.include( "*.rdoc", "ChangeLog", "lib/**/*.rb" )
|
72
|
-
rdoc.generator = :fivefish
|
73
|
-
rdoc.title = 'Thingfish'
|
74
|
-
rdoc.rdoc_dir = 'doc'
|
75
|
-
end
|
5
|
+
Rake::DevEiate.setup( 'thingfish' ) do |project|
|
6
|
+
project.publish_to = 'deveiate:/usr/local/www/public/code'
|
76
7
|
end
|
77
8
|
|
78
|
-
task :gemspec => GEMSPEC
|
79
|
-
file GEMSPEC => __FILE__
|
80
|
-
task GEMSPEC do |task|
|
81
|
-
spec = $hoespec.spec
|
82
|
-
spec.files.delete( '.gemtest' )
|
83
|
-
spec.signing_key = nil
|
84
|
-
spec.cert_chain = ['certs/ged.pem']
|
85
|
-
spec.version = "#{spec.version}.pre#{Time.now.strftime("%Y%m%d%H%M%S")}"
|
86
|
-
File.open( task.name, 'w' ) do |fh|
|
87
|
-
fh.write( spec.to_ruby )
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
CLOBBER.include( GEMSPEC.to_s )
|
92
|
-
|
data/bin/thingfish
CHANGED
data/lib/strelka/app/metadata.rb
CHANGED
data/lib/strelka/apps.rb
ADDED
data/lib/thingfish.rb
CHANGED
@@ -2,18 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'loggability'
|
4
4
|
|
5
|
-
#
|
6
5
|
# Network-accessable datastore service
|
7
|
-
#
|
8
|
-
# == Version
|
9
|
-
#
|
10
|
-
# $Id: thingfish.rb,v ce172208b523 2013/11/20 02:21:12 ged $
|
11
|
-
#
|
12
|
-
# == Authors
|
13
|
-
#
|
14
|
-
# * Michael Granger <ged@FaerieMUD.org>
|
15
|
-
# * Mahlon E. Smith <mahlon@martini.nu>
|
16
|
-
#
|
17
6
|
module Thingfish
|
18
7
|
extend Loggability
|
19
8
|
|
@@ -23,10 +12,10 @@ module Thingfish
|
|
23
12
|
|
24
13
|
|
25
14
|
# Package version
|
26
|
-
VERSION = '0.
|
15
|
+
VERSION = '0.8.0'
|
27
16
|
|
28
17
|
# Version control revision
|
29
|
-
REVISION = %q$Revision
|
18
|
+
REVISION = %q$Revision$
|
30
19
|
|
31
20
|
|
32
21
|
### Get the library version. If +include_buildnum+ is true, the version string will
|
data/lib/thingfish/behaviors.rb
CHANGED
data/lib/thingfish/datastore.rb
CHANGED
data/lib/thingfish/handler.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'strelka'
|
5
5
|
require 'strelka/app'
|
@@ -74,22 +74,6 @@ class Thingfish::Handler < Strelka::App
|
|
74
74
|
singleton_attr_accessor :processors
|
75
75
|
|
76
76
|
|
77
|
-
### Configurability API -- install the configuration
|
78
|
-
def self::configure( config=nil )
|
79
|
-
config = self.defaults.merge( config || {} )
|
80
|
-
|
81
|
-
self.datastore = config[:datastore]
|
82
|
-
self.metastore = config[:metastore]
|
83
|
-
self.event_socket_uri = config[:event_socket_uri]
|
84
|
-
|
85
|
-
self.processors = self.load_processors( config[:processors] )
|
86
|
-
self.processors.each do |processor|
|
87
|
-
self.filter( :request, &processor.method(:process_request) )
|
88
|
-
self.filter( :response, &processor.method(:process_response) )
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
77
|
### Load the Thingfish::Processors in the given +processor_list+ and return an instance
|
94
78
|
### of each one.
|
95
79
|
def self::load_processors( processor_list )
|
@@ -110,6 +94,24 @@ class Thingfish::Handler < Strelka::App
|
|
110
94
|
end
|
111
95
|
|
112
96
|
|
97
|
+
### Configurability API -- install the configuration
|
98
|
+
def self::configure( config=nil )
|
99
|
+
config = self.defaults.merge( config || {} )
|
100
|
+
|
101
|
+
self.datastore = config[:datastore]
|
102
|
+
self.metastore = config[:metastore]
|
103
|
+
self.event_socket_uri = config[:event_socket_uri]
|
104
|
+
|
105
|
+
self.plugin( :filters ) # pre-load the filters plugin for deferred config
|
106
|
+
|
107
|
+
self.processors = self.load_processors( config[:processors] )
|
108
|
+
self.processors.each do |processor|
|
109
|
+
self.filter( :request, &processor.method(:process_request) )
|
110
|
+
self.filter( :response, &processor.method(:process_response) )
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
113
115
|
### Set up the metastore, datastore, and event socket when the handler is
|
114
116
|
### created.
|
115
117
|
def initialize( * ) # :notnew:
|
@@ -145,8 +147,8 @@ class Thingfish::Handler < Strelka::App
|
|
145
147
|
### Set up the event socket.
|
146
148
|
def setup_event_socket
|
147
149
|
if self.class.event_socket_uri && ! @event_socket
|
148
|
-
@event_socket =
|
149
|
-
@event_socket.linger = 0
|
150
|
+
@event_socket = CZTop::Socket::PUB.new
|
151
|
+
@event_socket.options.linger = 0
|
150
152
|
@event_socket.bind( self.class.event_socket_uri )
|
151
153
|
end
|
152
154
|
end
|
@@ -193,7 +195,7 @@ class Thingfish::Handler < Strelka::App
|
|
193
195
|
"The name(s) of the fields to order results by."
|
194
196
|
param :direction, /^(asc|desc)$/i, "The order direction (ascending or descending)"
|
195
197
|
param :casefold, :boolean, "Whether or not to convert to lowercase before matching"
|
196
|
-
param :relationship,
|
198
|
+
param :relationship, /^[\w\-]+$/, "The name of the relationship between two resources"
|
197
199
|
|
198
200
|
|
199
201
|
#
|
@@ -316,6 +318,9 @@ class Thingfish::Handler < Strelka::App
|
|
316
318
|
|
317
319
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
318
320
|
|
321
|
+
primary_metadata = self.metastore.fetch( uuid )
|
322
|
+
self.check_resource_permissions( req, uuid, primary_metadata )
|
323
|
+
|
319
324
|
criteria = {
|
320
325
|
'relation' => uuid,
|
321
326
|
'relationship' => rel,
|
@@ -328,8 +333,12 @@ class Thingfish::Handler < Strelka::App
|
|
328
333
|
metadata = self.metastore.fetch( uuid )
|
329
334
|
|
330
335
|
res = req.response
|
336
|
+
self.add_cache_headers( req, metadata )
|
337
|
+
self.add_content_disposition( res, metadata )
|
338
|
+
|
331
339
|
res.body = object
|
332
340
|
res.content_type = metadata['format']
|
341
|
+
res.status = HTTP::OK
|
333
342
|
|
334
343
|
return res
|
335
344
|
end
|
@@ -348,7 +357,8 @@ class Thingfish::Handler < Strelka::App
|
|
348
357
|
res = req.response
|
349
358
|
res.content_type = metadata['format']
|
350
359
|
|
351
|
-
self.
|
360
|
+
self.add_cache_headers( req, metadata )
|
361
|
+
self.add_content_disposition( res, metadata )
|
352
362
|
|
353
363
|
if object.respond_to?( :path )
|
354
364
|
path = Pathname( object.path )
|
@@ -360,6 +370,7 @@ class Thingfish::Handler < Strelka::App
|
|
360
370
|
res.body = object
|
361
371
|
end
|
362
372
|
|
373
|
+
res.status = HTTP::OK
|
363
374
|
return res
|
364
375
|
end
|
365
376
|
|
@@ -411,9 +422,9 @@ class Thingfish::Handler < Strelka::App
|
|
411
422
|
|
412
423
|
self.check_resource_permissions( req, uuid )
|
413
424
|
|
414
|
-
self.datastore.remove( uuid ) or finish_with( HTTP::NOT_FOUND, "No such object." )
|
415
|
-
metadata = self.metastore.remove( uuid )
|
416
425
|
self.remove_related_resources( uuid )
|
426
|
+
metadata = self.metastore.remove( uuid )
|
427
|
+
self.datastore.remove( uuid ) or finish_with( HTTP::NOT_FOUND, "No such object." )
|
417
428
|
self.send_event( :deleted, :uuid => uuid )
|
418
429
|
|
419
430
|
res = req.response
|
@@ -441,8 +452,7 @@ class Thingfish::Handler < Strelka::App
|
|
441
452
|
|
442
453
|
finish_with( HTTP::NOT_FOUND, "No such object." ) unless self.metastore.include?( uuid )
|
443
454
|
|
444
|
-
metadata = self.
|
445
|
-
metadata[ 'oid' ] = uuid
|
455
|
+
metadata = self.normalized_metadata_for( uuid )
|
446
456
|
self.check_resource_permissions( req, uuid, metadata )
|
447
457
|
|
448
458
|
res = req.response
|
@@ -538,13 +548,17 @@ class Thingfish::Handler < Strelka::App
|
|
538
548
|
metadata = self.metastore.fetch( uuid )
|
539
549
|
self.check_resource_permissions( req, uuid, metadata )
|
540
550
|
|
541
|
-
op_metadata
|
551
|
+
op_metadata = self.metastore.fetch( uuid, *OPERATIONAL_METADATA_KEYS )
|
542
552
|
new_metadata = self.extract_metadata( req )
|
543
|
-
self.metastore.
|
553
|
+
self.metastore.transaction do
|
554
|
+
self.metastore.remove_except( uuid, *OPERATIONAL_METADATA_KEYS )
|
555
|
+
self.metastore.merge( uuid, new_metadata.merge(op_metadata) )
|
556
|
+
end
|
544
557
|
self.send_event( :metadata_replaced, :uuid => uuid )
|
545
558
|
|
546
559
|
res = req.response
|
547
|
-
res.status = HTTP::
|
560
|
+
res.status = HTTP::OK
|
561
|
+
res.for( :json, :yaml ) { self.normalized_metadata_for(uuid) }
|
548
562
|
|
549
563
|
return res
|
550
564
|
end
|
@@ -565,7 +579,8 @@ class Thingfish::Handler < Strelka::App
|
|
565
579
|
self.send_event( :metadata_updated, :uuid => uuid )
|
566
580
|
|
567
581
|
res = req.response
|
568
|
-
res.status = HTTP::
|
582
|
+
res.status = HTTP::OK
|
583
|
+
res.for( :json, :yaml ) { self.normalized_metadata_for(uuid) }
|
569
584
|
|
570
585
|
return res
|
571
586
|
end
|
@@ -585,7 +600,8 @@ class Thingfish::Handler < Strelka::App
|
|
585
600
|
self.send_event( :metadata_deleted, :uuid => uuid )
|
586
601
|
|
587
602
|
res = req.response
|
588
|
-
res.status = HTTP::
|
603
|
+
res.status = HTTP::OK
|
604
|
+
res.for( :json, :yaml ) { self.normalized_metadata_for(uuid) }
|
589
605
|
|
590
606
|
return res
|
591
607
|
end
|
@@ -626,8 +642,8 @@ class Thingfish::Handler < Strelka::App
|
|
626
642
|
metadata.merge!( self.extract_header_metadata(request) )
|
627
643
|
metadata.merge!( self.extract_default_metadata(request) )
|
628
644
|
|
629
|
-
self.verify_operational_metadata( metadata )
|
630
645
|
self.check_resource_permissions( request, uuid, metadata )
|
646
|
+
self.verify_operational_metadata( metadata )
|
631
647
|
|
632
648
|
if uuid
|
633
649
|
self.log.info "Replacing resource %s (encoding: %p)" %
|
@@ -702,9 +718,9 @@ class Thingfish::Handler < Strelka::App
|
|
702
718
|
### Return a Hash of default metadata extracted from the given +request+.
|
703
719
|
def extract_default_metadata( request )
|
704
720
|
return self.extract_connection_metadata( request ).merge(
|
705
|
-
'extent'
|
706
|
-
'format'
|
707
|
-
'created'
|
721
|
+
'extent' => request.headers.content_length,
|
722
|
+
'format' => request.content_type,
|
723
|
+
'created' => Time.now.getgm
|
708
724
|
)
|
709
725
|
end
|
710
726
|
|
@@ -722,15 +738,7 @@ class Thingfish::Handler < Strelka::App
|
|
722
738
|
### Extract and validate supplied metadata from the +request+.
|
723
739
|
def extract_metadata( req )
|
724
740
|
new_metadata = req.params.fields.dup
|
725
|
-
new_metadata.
|
726
|
-
|
727
|
-
protected_keys = OPERATIONAL_METADATA_KEYS & new_metadata.keys
|
728
|
-
|
729
|
-
unless protected_keys.empty?
|
730
|
-
finish_with HTTP::FORBIDDEN,
|
731
|
-
"Unable to alter protected metadata. (%s)" % [ protected_keys.join(', ') ]
|
732
|
-
end
|
733
|
-
|
741
|
+
new_metadata = self.remove_operational_metadata( new_metadata )
|
734
742
|
return new_metadata
|
735
743
|
end
|
736
744
|
|
@@ -750,6 +758,13 @@ class Thingfish::Handler < Strelka::App
|
|
750
758
|
end
|
751
759
|
|
752
760
|
|
761
|
+
### Fetch the current metadata for +uuid+, altering it for easier
|
762
|
+
### round trips with REST.
|
763
|
+
def normalized_metadata_for( uuid )
|
764
|
+
return self.metastore.fetch(uuid).merge( 'uuid' => uuid )
|
765
|
+
end
|
766
|
+
|
767
|
+
|
753
768
|
### Check that the metadata provided contains valid values for
|
754
769
|
### the operational keys, before saving a resource to disk.
|
755
770
|
def verify_operational_metadata( metadata )
|
@@ -759,32 +774,58 @@ class Thingfish::Handler < Strelka::App
|
|
759
774
|
end
|
760
775
|
|
761
776
|
|
777
|
+
### Prune operational +metadata+ from the provided hash.
|
778
|
+
def remove_operational_metadata( metadata )
|
779
|
+
operationals = OPERATIONAL_METADATA_KEYS + [ 'uuid' ]
|
780
|
+
return metadata.reject{|key, _| operationals.include?(key) }
|
781
|
+
end
|
782
|
+
|
783
|
+
|
762
784
|
### Send an event of +type+ with the given +msg+ over the zmq event socket.
|
763
785
|
def send_event( type, msg )
|
764
786
|
esock = self.event_socket or return
|
765
787
|
self.log.debug "Publishing %p event: %p" % [ type, msg ]
|
766
|
-
esock.
|
767
|
-
esock.send( Yajl.dump(msg) )
|
788
|
+
esock << CZTop::Message.new([ type.to_s, Yajl.dump(msg) ])
|
768
789
|
end
|
769
790
|
|
770
791
|
|
771
|
-
### Add browser cache headers for resources.
|
792
|
+
### Add browser cache headers for resources.
|
793
|
+
### Last-Modified is always added. ETag support requires the sha256
|
772
794
|
### processor plugin to be enabled for stored resources.
|
773
|
-
|
795
|
+
###
|
796
|
+
def add_cache_headers( request, metadata )
|
774
797
|
response = request.response
|
775
|
-
checksum = metadata[ 'checksum' ]
|
776
|
-
return unless checksum
|
777
798
|
|
778
|
-
|
779
|
-
|
780
|
-
|
799
|
+
# ETag takes precedence if available.
|
800
|
+
#
|
801
|
+
if (( checksum = metadata['checksum'] ))
|
802
|
+
if (( match = request.headers[ :if_none_match ] ))
|
803
|
+
match = match.gsub( '"', '' ).split( /,\s*/ )
|
804
|
+
finish_with( HTTP::NOT_MODIFIED ) if match.include?( checksum )
|
805
|
+
end
|
806
|
+
response.headers[ :etag ] = checksum
|
807
|
+
end
|
808
|
+
|
809
|
+
return unless metadata[ 'created' ]
|
810
|
+
|
811
|
+
if (( modified = request.headers[ :if_modified_since ] ))
|
812
|
+
finish_with( HTTP::NOT_MODIFIED ) if Time.parse( modified ) <= metadata['created'].round
|
781
813
|
end
|
814
|
+
response.headers[ :last_modified ] = metadata[ 'created' ].httpdate
|
782
815
|
|
783
|
-
response.headers[ :etag ] = checksum
|
784
816
|
return
|
785
817
|
end
|
786
818
|
|
787
819
|
|
820
|
+
### Add a filename "hint" for browsers, if the resource being fetched
|
821
|
+
### has a 'title' attribute.
|
822
|
+
def add_content_disposition( res, metadata )
|
823
|
+
return unless metadata[ 'title' ]
|
824
|
+
title = metadata[ 'title' ].encode( 'us-ascii', :undef => :replace )
|
825
|
+
res.headers[ :content_disposition ] = "filename=%p" % [ title ]
|
826
|
+
end
|
827
|
+
|
828
|
+
|
788
829
|
### Supply a method that child handlers can override. The regular auth
|
789
830
|
### plugin runs too early (but can also be used), this hook allows
|
790
831
|
### child handlers to make access decisions based on the +request+
|