rack-gridfs 0.2.0 → 0.3.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.
- data/README.rdoc +14 -14
- data/Rakefile +2 -3
- data/VERSION +1 -1
- data/lib/rack/gridfs.rb +13 -22
- data/rack-gridfs.gemspec +8 -11
- data/test/gridfs_test.rb +34 -42
- data/test/test_helper.rb +8 -3
- metadata +5 -15
data/README.rdoc
CHANGED
@@ -2,19 +2,23 @@
|
|
2
2
|
|
3
3
|
Rack:GridFS is a Rack middleware for creating HTTP endpoints for files
|
4
4
|
stored in MongoDB's GridFS. You can configure a prefix string which
|
5
|
-
will be used to match the path of a request and
|
5
|
+
will be used to match the path of a request and supply an id for looking
|
6
6
|
up the file in the GridFS store.
|
7
7
|
|
8
8
|
For example,
|
9
9
|
|
10
|
-
GET '/gridfs/
|
10
|
+
GET '/gridfs/someobjectid'
|
11
11
|
|
12
|
-
If the prefix is "gridfs", then the
|
12
|
+
If the prefix is "gridfs", then the id will be be "someobjectid".
|
13
13
|
|
14
|
-
==
|
14
|
+
== Mongo Driver Compatibility Notes
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
This version is currently based off of mongo-0.20.1.
|
17
|
+
|
18
|
+
As of mongo-0.19.1, there have been significant changes to GridFS. I do
|
19
|
+
not plan to support versions of the mongo driver prior to 0.19. There are
|
20
|
+
some compatibility issues with mongo-0.19 vs. mongo-0.20 (Mongo::ObjectID
|
21
|
+
vs. BSON::ObjectID). For now, I am choosing to support mongo-0.20.
|
18
22
|
|
19
23
|
== Installation
|
20
24
|
|
@@ -31,14 +35,10 @@ You must specify MongoDB database details:
|
|
31
35
|
- database: the MongoDB database to connect to.
|
32
36
|
- prefix: a string used to match against incoming paths and route to through the middleware. Default 'gridfs'.
|
33
37
|
|
34
|
-
== Caveats
|
35
|
-
|
36
|
-
This is an experimental project. The Ruby GridFS adaptor is still pretty new and the performance
|
37
|
-
is known to be slow. I wouldn't recommend using this middleware for anything high-volume in
|
38
|
-
production.
|
39
|
-
|
40
38
|
== Sinatra Example
|
41
39
|
|
40
|
+
# TODO: THIS COULD USE A LOT MORE EXPLANATION!
|
41
|
+
|
42
42
|
require 'rubygems'
|
43
43
|
require 'sinatra'
|
44
44
|
|
@@ -46,9 +46,9 @@ production.
|
|
46
46
|
use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
|
47
47
|
|
48
48
|
get /.*/ do
|
49
|
-
"
|
49
|
+
"The URL did not match a file in GridFS."
|
50
50
|
end
|
51
51
|
|
52
52
|
== Copyright
|
53
53
|
|
54
|
-
Copyright (c)
|
54
|
+
Copyright (c) 2010 Blake Carlson. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -12,12 +12,11 @@ begin
|
|
12
12
|
gem.rubyforge_project = "rack-gridfs"
|
13
13
|
|
14
14
|
gem.add_dependency('rack')
|
15
|
-
gem.add_dependency('
|
16
|
-
gem.add_dependency('mongo', '0.15.1')
|
15
|
+
gem.add_dependency('mongo', '>=0.20.1')
|
17
16
|
|
18
17
|
gem.add_development_dependency('mocha', '0.9.4')
|
19
18
|
gem.add_development_dependency('rack-test')
|
20
|
-
gem.add_development_dependency('
|
19
|
+
gem.add_development_dependency('shoulda')
|
21
20
|
end
|
22
21
|
Jeweler::GemcutterTasks.new
|
23
22
|
Jeweler::RubyforgeTasks.new do |rubyforge|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/rack/gridfs.rb
CHANGED
@@ -1,29 +1,27 @@
|
|
1
1
|
require 'timeout'
|
2
2
|
require 'mongo'
|
3
|
-
require 'mongo/gridfs'
|
4
|
-
require 'active_support/core_ext'
|
5
3
|
|
6
4
|
module Rack
|
7
5
|
|
8
|
-
class
|
6
|
+
class GridFSConnectionError < StandardError ; end
|
9
7
|
|
10
8
|
class GridFS
|
11
9
|
|
12
|
-
attr_reader :hostname, :port, :database, :prefix, :
|
10
|
+
attr_reader :hostname, :port, :database, :prefix, :db
|
13
11
|
|
14
12
|
def initialize(app, options = {})
|
15
|
-
options
|
13
|
+
options = {
|
16
14
|
:hostname => 'localhost',
|
17
|
-
:
|
18
|
-
:
|
19
|
-
)
|
15
|
+
:prefix => 'gridfs',
|
16
|
+
:port => Mongo::Connection::DEFAULT_PORT
|
17
|
+
}.merge(options)
|
20
18
|
|
21
19
|
@app = app
|
22
20
|
@hostname = options[:hostname]
|
23
21
|
@port = options[:port]
|
24
22
|
@database = options[:database]
|
25
23
|
@prefix = options[:prefix]
|
26
|
-
@
|
24
|
+
@db = nil
|
27
25
|
|
28
26
|
connect!
|
29
27
|
end
|
@@ -37,28 +35,21 @@ module Rack
|
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
40
|
-
def
|
38
|
+
def gridfs_request(id)
|
39
|
+
file = Mongo::Grid.new(db).get(BSON::ObjectID.from_string(id))
|
40
|
+
[200, {'Content-Type' => file.content_type}, [file.read]]
|
41
|
+
rescue Mongo::GridError, BSON::InvalidObjectID
|
41
42
|
[404, {'Content-Type' => 'text/plain'}, ['File not found.']]
|
42
43
|
end
|
43
|
-
|
44
|
-
def gridfs_request(key)
|
45
|
-
if ::GridFS::GridStore.exist?(connection, key)
|
46
|
-
::GridFS::GridStore.open(connection, key, 'r') do |file|
|
47
|
-
[200, {'Content-Type' => file.content_type}, [file.read]]
|
48
|
-
end
|
49
|
-
else
|
50
|
-
not_found
|
51
|
-
end
|
52
|
-
end
|
53
44
|
|
54
45
|
private
|
55
46
|
|
56
47
|
def connect!
|
57
48
|
Timeout::timeout(5) do
|
58
|
-
@
|
49
|
+
@db = Mongo::Connection.new(hostname).db(database)
|
59
50
|
end
|
60
51
|
rescue Exception => e
|
61
|
-
raise Rack::
|
52
|
+
raise Rack::GridFSConnectionError, "Unable to connect to the MongoDB server (#{e.to_s})"
|
62
53
|
end
|
63
54
|
|
64
55
|
end
|
data/rack-gridfs.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rack-gridfs}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Blake Carlson"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-05-11}
|
13
13
|
s.email = %q{blake@coin-operated.net}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
@@ -47,26 +47,23 @@ Gem::Specification.new do |s|
|
|
47
47
|
|
48
48
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
49
49
|
s.add_runtime_dependency(%q<rack>, [">= 0"])
|
50
|
-
s.add_runtime_dependency(%q<
|
51
|
-
s.add_runtime_dependency(%q<mongo>, ["= 0.15.1"])
|
50
|
+
s.add_runtime_dependency(%q<mongo>, [">= 0.20.1"])
|
52
51
|
s.add_development_dependency(%q<mocha>, ["= 0.9.4"])
|
53
52
|
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
54
|
-
s.add_development_dependency(%q<
|
53
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
55
54
|
else
|
56
55
|
s.add_dependency(%q<rack>, [">= 0"])
|
57
|
-
s.add_dependency(%q<
|
58
|
-
s.add_dependency(%q<mongo>, ["= 0.15.1"])
|
56
|
+
s.add_dependency(%q<mongo>, [">= 0.20.1"])
|
59
57
|
s.add_dependency(%q<mocha>, ["= 0.9.4"])
|
60
58
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
61
|
-
s.add_dependency(%q<
|
59
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
62
60
|
end
|
63
61
|
else
|
64
62
|
s.add_dependency(%q<rack>, [">= 0"])
|
65
|
-
s.add_dependency(%q<
|
66
|
-
s.add_dependency(%q<mongo>, ["= 0.15.1"])
|
63
|
+
s.add_dependency(%q<mongo>, [">= 0.20.1"])
|
67
64
|
s.add_dependency(%q<mocha>, ["= 0.9.4"])
|
68
65
|
s.add_dependency(%q<rack-test>, [">= 0"])
|
69
|
-
s.add_dependency(%q<
|
66
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
70
67
|
end
|
71
68
|
end
|
72
69
|
|
data/test/gridfs_test.rb
CHANGED
@@ -3,10 +3,6 @@ require 'test_helper'
|
|
3
3
|
class Rack::GridFSTest < Test::Unit::TestCase
|
4
4
|
include Rack::Test::Methods
|
5
5
|
|
6
|
-
def options_for_gridfs
|
7
|
-
{ :hostname => 'myhostname.mydomain', :port => 8765, :database => 'mydatabase', :prefix => 'myprefix' }
|
8
|
-
end
|
9
|
-
|
10
6
|
def stub_mongodb_connection
|
11
7
|
Rack::GridFS.any_instance.stubs(:connect!).returns(true)
|
12
8
|
end
|
@@ -20,19 +16,16 @@ class Rack::GridFSTest < Test::Unit::TestCase
|
|
20
16
|
end
|
21
17
|
|
22
18
|
def app
|
19
|
+
gridfs_opts = test_database_options
|
23
20
|
Rack::Builder.new do
|
24
|
-
use Rack::GridFS,
|
21
|
+
use Rack::GridFS, gridfs_opts
|
25
22
|
run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
|
-
def load_artifact(filename,
|
30
|
-
|
31
|
-
|
32
|
-
File.open(File.join(File.dirname(__FILE__), 'artifacts', filename), 'r') do |orig|
|
33
|
-
dest.puts orig.read
|
34
|
-
end
|
35
|
-
end
|
26
|
+
def load_artifact(filename, content_type)
|
27
|
+
contents = File.read(File.join(File.dirname(__FILE__), 'artifacts', filename))
|
28
|
+
Mongo::Grid.new(db).put(contents, :filename => filename, :content_type => content_type)
|
36
29
|
end
|
37
30
|
|
38
31
|
context "Rack::GridFS" do
|
@@ -41,51 +34,52 @@ class Rack::GridFSTest < Test::Unit::TestCase
|
|
41
34
|
|
42
35
|
setup do
|
43
36
|
stub_mongodb_connection
|
37
|
+
@options = { :hostname => 'myhostname.mydomain', :port => 8765, :database => 'mydatabase', :prefix => 'myprefix' }
|
44
38
|
end
|
45
39
|
|
46
40
|
should "have a hostname option" do
|
47
|
-
mware = Rack::GridFS.new(nil,
|
48
|
-
assert_equal
|
41
|
+
mware = Rack::GridFS.new(nil, @options)
|
42
|
+
assert_equal @options[:hostname], mware.hostname
|
49
43
|
end
|
50
44
|
|
51
45
|
should "have a default hostname" do
|
52
|
-
mware = Rack::GridFS.new(nil,
|
46
|
+
mware = Rack::GridFS.new(nil, @options.except(:hostname))
|
53
47
|
assert_equal 'localhost', mware.hostname
|
54
48
|
end
|
55
49
|
|
56
50
|
should "have a port option" do
|
57
|
-
mware = Rack::GridFS.new(nil,
|
58
|
-
assert_equal
|
51
|
+
mware = Rack::GridFS.new(nil, @options)
|
52
|
+
assert_equal @options[:port], mware.port
|
59
53
|
end
|
60
54
|
|
61
55
|
should "have a default port" do
|
62
|
-
mware = Rack::GridFS.new(nil,
|
56
|
+
mware = Rack::GridFS.new(nil, @options.except(:port))
|
63
57
|
assert_equal Mongo::Connection::DEFAULT_PORT, mware.port
|
64
58
|
end
|
65
59
|
|
66
60
|
should "have a database option" do
|
67
|
-
mware = Rack::GridFS.new(nil,
|
68
|
-
assert_equal
|
61
|
+
mware = Rack::GridFS.new(nil, @options)
|
62
|
+
assert_equal @options[:database], mware.database
|
69
63
|
end
|
70
64
|
|
71
65
|
should "not have a default database" do
|
72
|
-
mware = Rack::GridFS.new(nil,
|
66
|
+
mware = Rack::GridFS.new(nil, @options.except(:database))
|
73
67
|
assert_nil mware.database
|
74
68
|
end
|
75
69
|
|
76
70
|
should "have a prefix option" do
|
77
|
-
mware = Rack::GridFS.new(nil,
|
78
|
-
assert_equal mware.prefix,
|
71
|
+
mware = Rack::GridFS.new(nil, @options)
|
72
|
+
assert_equal mware.prefix, @options[:prefix]
|
79
73
|
end
|
80
74
|
|
81
75
|
should "have a default prefix" do
|
82
|
-
mware = Rack::GridFS.new(nil,
|
76
|
+
mware = Rack::GridFS.new(nil, @options.except(:prefix))
|
83
77
|
assert_equal mware.prefix, 'gridfs'
|
84
78
|
end
|
85
79
|
|
86
80
|
should "connect to the MongoDB server" do
|
87
81
|
Rack::GridFS.any_instance.expects(:connect!).returns(true).once
|
88
|
-
Rack::GridFS.new(nil,
|
82
|
+
Rack::GridFS.new(nil, @options)
|
89
83
|
end
|
90
84
|
|
91
85
|
end
|
@@ -98,29 +92,33 @@ class Rack::GridFSTest < Test::Unit::TestCase
|
|
98
92
|
end
|
99
93
|
end
|
100
94
|
|
101
|
-
context "with
|
95
|
+
context "with files in GridFS" do
|
102
96
|
setup do
|
103
|
-
load_artifact('test.txt', '
|
104
|
-
load_artifact('test.html', '
|
97
|
+
@text_id = load_artifact('test.txt', 'text/plain')
|
98
|
+
@html_id = load_artifact('test.html', 'text/html')
|
99
|
+
end
|
100
|
+
|
101
|
+
teardown do
|
102
|
+
db.collection('fs.files').remove
|
105
103
|
end
|
106
104
|
|
107
105
|
should "return TXT files stored in GridFS" do
|
108
|
-
get
|
109
|
-
assert_equal "Lorem ipsum dolor sit amet
|
106
|
+
get "/gridfs/#{@text_id}"
|
107
|
+
assert_equal "Lorem ipsum dolor sit amet.", last_response.body
|
110
108
|
end
|
111
109
|
|
112
110
|
should "return the proper content type for TXT files" do
|
113
|
-
get
|
111
|
+
get "/gridfs/#{@text_id}"
|
114
112
|
assert_equal 'text/plain', last_response.content_type
|
115
113
|
end
|
116
114
|
|
117
115
|
should "return HTML files stored in GridFS" do
|
118
|
-
get
|
116
|
+
get "/gridfs/#{@html_id}"
|
119
117
|
assert_match /html.*?body.*Test/m, last_response.body
|
120
118
|
end
|
121
|
-
|
119
|
+
|
122
120
|
should "return the proper content type for HTML files" do
|
123
|
-
get
|
121
|
+
get "/gridfs/#{@html_id}"
|
124
122
|
assert_equal 'text/html', last_response.content_type
|
125
123
|
end
|
126
124
|
|
@@ -129,15 +127,9 @@ class Rack::GridFSTest < Test::Unit::TestCase
|
|
129
127
|
assert last_response.not_found?
|
130
128
|
end
|
131
129
|
|
132
|
-
should "handle complex file paths" do
|
133
|
-
load_artifact('test.html', 'stuff/187d/foo.html', 'text/html')
|
134
|
-
get '/gridfs/stuff/187d/foo.html'
|
135
|
-
assert_equal 'text/html', last_response.content_type
|
136
|
-
end
|
137
|
-
|
138
130
|
should "work for small images" do
|
139
|
-
load_artifact('3wolfmoon.jpg', '
|
140
|
-
get
|
131
|
+
image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
|
132
|
+
get "/gridfs/#{image_id}"
|
141
133
|
assert last_response.ok?
|
142
134
|
assert_equal 'image/jpeg', last_response.content_type
|
143
135
|
end
|
data/test/test_helper.rb
CHANGED
@@ -7,8 +7,13 @@ require 'rack/builder'
|
|
7
7
|
require 'rack/mock'
|
8
8
|
require 'rack/test'
|
9
9
|
|
10
|
-
gem 'mongo', '>= 0.15.1'
|
11
|
-
|
12
10
|
require 'mongo'
|
13
|
-
require 'mongo/gridfs'
|
14
11
|
require File.join(File.dirname(__FILE__), '..', 'lib', 'rack', 'gridfs')
|
12
|
+
|
13
|
+
|
14
|
+
class Hash
|
15
|
+
def except(*keys)
|
16
|
+
rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
|
17
|
+
reject { |key,| rejected.include?(key) }
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-gridfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Carlson
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-05-11 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,25 +22,15 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: activesupport
|
27
|
-
type: :runtime
|
28
|
-
version_requirement:
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: "0"
|
34
|
-
version:
|
35
25
|
- !ruby/object:Gem::Dependency
|
36
26
|
name: mongo
|
37
27
|
type: :runtime
|
38
28
|
version_requirement:
|
39
29
|
version_requirements: !ruby/object:Gem::Requirement
|
40
30
|
requirements:
|
41
|
-
- - "
|
31
|
+
- - ">="
|
42
32
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.
|
33
|
+
version: 0.20.1
|
44
34
|
version:
|
45
35
|
- !ruby/object:Gem::Dependency
|
46
36
|
name: mocha
|
@@ -63,7 +53,7 @@ dependencies:
|
|
63
53
|
version: "0"
|
64
54
|
version:
|
65
55
|
- !ruby/object:Gem::Dependency
|
66
|
-
name:
|
56
|
+
name: shoulda
|
67
57
|
type: :development
|
68
58
|
version_requirement:
|
69
59
|
version_requirements: !ruby/object:Gem::Requirement
|