thingfish 0.5.0.pre20161103181816 → 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 -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+
|