skinandbones-rack-gridfs 0.1.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/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ rdoc
2
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Blake Carlson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,47 @@
1
+ = Rack::GridFS
2
+
3
+ Rack:GridFS is a Rack middleware for creating HTTP endpoints for files
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 create a key for looking
6
+ up the file in the GridFS store.
7
+
8
+ For example,
9
+
10
+ GET '/gridfs/images/foo.jpg'
11
+
12
+ If the prefix is "gridfs", then the key will be be "images/foo.jpg".
13
+
14
+ == Dependencies
15
+
16
+ * ActiveSupport (activesupport)
17
+ * Mongo Ruby Driver (mongodb-mongo)
18
+
19
+ == Usage
20
+
21
+ You must specify MongoDB database details:
22
+ - hostname: the hostname/IP where the MongoDB server is running. Default 'localhost'.
23
+ - port: the port of the MongoDB server. Default 27017.
24
+ - database: the MongoDB database to connect to.
25
+ - prefix: a string used to match against incoming paths and route to through the middleware. Default 'gridfs'.
26
+
27
+ == Sinatra Example
28
+
29
+ require 'rubygems'
30
+ require 'sinatra'
31
+
32
+ require 'rack/gridfs'
33
+ use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
34
+
35
+ get /.*/ do
36
+ "Whatchya talking about?"
37
+ end
38
+
39
+ == TODO
40
+
41
+ - Make it awesome.
42
+ - What's up with the performance?
43
+ - Gem it up. Anyone care?
44
+
45
+ == Copyright
46
+
47
+ Copyright (c) 2009 Blake Carlson. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,66 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "rack-gridfs"
8
+ gem.summary = "Rack middleware for creating HTTP endpoints for files stored in MongoDB's GridFS"
9
+ gem.email = "blake@coin-operated.net"
10
+ gem.homepage = "http://github.com/skinandbones/rack-gridfs"
11
+ gem.authors = ["Blake Carlson"]
12
+ gem.rubyforge_project = "rack-gridfs"
13
+
14
+ gem.add_dependency('rack')
15
+ gem.add_dependency('activesupport')
16
+ gem.add_dependency('mongodb-mongo', '0.14')
17
+
18
+ gem.add_development_dependency('mocha', '0.9.4')
19
+ gem.add_development_dependency('rack-test')
20
+ gem.add_development_dependency('thoughtbot-shoulda')
21
+ end
22
+
23
+ Jeweler::RubyforgeTasks.new do |rubyforge|
24
+ rubyforge.doc_task = "rdoc"
25
+ end
26
+ rescue LoadError
27
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
28
+ end
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |test|
32
+ test.libs << 'lib' << 'test'
33
+ test.pattern = 'test/**/*_test.rb'
34
+ test.verbose = true
35
+ end
36
+
37
+ begin
38
+ require 'rcov/rcovtask'
39
+ Rcov::RcovTask.new do |test|
40
+ test.libs << 'test'
41
+ test.pattern = 'test/**/*_test.rb'
42
+ test.verbose = true
43
+ end
44
+ rescue LoadError
45
+ task :rcov do
46
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
47
+ end
48
+ end
49
+
50
+ task :test => :check_dependencies
51
+
52
+ task :default => :test
53
+
54
+ require 'rake/rdoctask'
55
+ Rake::RDocTask.new do |rdoc|
56
+ if File.exist?('VERSION')
57
+ version = File.read('VERSION')
58
+ else
59
+ version = ""
60
+ end
61
+
62
+ rdoc.rdoc_dir = 'rdoc'
63
+ rdoc.title = "Rack::GridFS #{version}"
64
+ rdoc.rdoc_files.include('README*')
65
+ rdoc.rdoc_files.include('lib/**/*.rb')
66
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'rack', 'gridfs')
5
+ use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
6
+
7
+ get /.*/ do
8
+ "Whatchya talking about?"
9
+ end
@@ -0,0 +1,66 @@
1
+ require 'timeout'
2
+ require 'mongo'
3
+ require 'mongo/gridfs'
4
+ require 'active_support/core_ext'
5
+
6
+ module Rack
7
+
8
+ class GridFSConnectonError < StandardError ; end
9
+
10
+ class GridFS
11
+
12
+ attr_reader :hostname, :port, :database, :prefix, :connection
13
+
14
+ def initialize(app, options = {})
15
+ options.reverse_merge!(
16
+ :hostname => 'localhost',
17
+ :port => XGen::Mongo::Connection::DEFAULT_PORT,
18
+ :prefix => 'gridfs'
19
+ )
20
+
21
+ @app = app
22
+ @hostname = options[:hostname]
23
+ @port = options[:port]
24
+ @database = options[:database]
25
+ @prefix = options[:prefix]
26
+ @connection = nil
27
+
28
+ connect!
29
+ end
30
+
31
+ def call(env)
32
+ request = Rack::Request.new(env)
33
+ if request.path_info =~ /^\/#{prefix}\/(.+)$/
34
+ gridfs_request($1)
35
+ else
36
+ @app.call(env)
37
+ end
38
+ end
39
+
40
+ def not_found
41
+ [404, {'Content-Type' => 'text/plain'}, ['File not found.']]
42
+ end
43
+
44
+ def gridfs_request(key)
45
+ if XGen::Mongo::GridFS::GridStore.exist?(connection, key)
46
+ XGen::Mongo::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
+
54
+ private
55
+
56
+ def connect!
57
+ Timeout::timeout(5) do
58
+ @connection = XGen::Mongo::Connection.new(hostname).db(database)
59
+ end
60
+ rescue Exception => e
61
+ raise Rack::GridFSConnectonError, "Unable to connect to the MongoDB server (#{e.to_s})"
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rack-gridfs}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Blake Carlson"]
12
+ s.date = %q{2009-09-21}
13
+ s.email = %q{blake@coin-operated.net}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE",
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "LICENSE",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "example/gridfs_server.rb",
25
+ "lib/rack/gridfs.rb",
26
+ "rack-gridfs.gemspec",
27
+ "test/artifacts/3wolfmoon.jpg",
28
+ "test/artifacts/test.html",
29
+ "test/artifacts/test.txt",
30
+ "test/gridfs_test.rb",
31
+ "test/test_helper.rb"
32
+ ]
33
+ s.has_rdoc = true
34
+ s.homepage = %q{http://github.com/skinandbones/rack-gridfs}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubyforge_project = %q{rack-gridfs}
38
+ s.rubygems_version = %q{1.3.2}
39
+ s.summary = %q{Rack middleware for creating HTTP endpoints for files stored in MongoDB's GridFS}
40
+ s.test_files = [
41
+ "test/gridfs_test.rb",
42
+ "test/test_helper.rb"
43
+ ]
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
+ s.add_runtime_dependency(%q<rack>, [">= 0"])
51
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
52
+ s.add_runtime_dependency(%q<mongodb-mongo>, ["= 0.14"])
53
+ s.add_development_dependency(%q<mocha>, ["= 0.9.4"])
54
+ s.add_development_dependency(%q<rack-test>, [">= 0"])
55
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
56
+ else
57
+ s.add_dependency(%q<rack>, [">= 0"])
58
+ s.add_dependency(%q<activesupport>, [">= 0"])
59
+ s.add_dependency(%q<mongodb-mongo>, ["= 0.14"])
60
+ s.add_dependency(%q<mocha>, ["= 0.9.4"])
61
+ s.add_dependency(%q<rack-test>, [">= 0"])
62
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<rack>, [">= 0"])
66
+ s.add_dependency(%q<activesupport>, [">= 0"])
67
+ s.add_dependency(%q<mongodb-mongo>, ["= 0.14"])
68
+ s.add_dependency(%q<mocha>, ["= 0.9.4"])
69
+ s.add_dependency(%q<rack-test>, [">= 0"])
70
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
71
+ end
72
+ end
Binary file
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
2
+ "http://www.w3.org/TR/html4/strict.dtd">
3
+
4
+ <html lang="en">
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
7
+ <title>test</title>
8
+ <meta name="generator" content="TextMate http://macromates.com/">
9
+ <meta name="author" content="Blake Carlson">
10
+ <!-- Date: 2009-09-20 -->
11
+ </head>
12
+ <body>
13
+ Test
14
+ </body>
15
+ </html>
@@ -0,0 +1 @@
1
+ Lorem ipsum dolor sit amet.
@@ -0,0 +1,149 @@
1
+ require 'test_helper'
2
+
3
+ class Rack::GridFSTest < Test::Unit::TestCase
4
+ include Rack::Test::Methods
5
+
6
+ def options_for_gridfs
7
+ { :hostname => 'myhostname.mydomain', :port => 8765, :database => 'mydatabase', :prefix => 'myprefix' }
8
+ end
9
+
10
+ def stub_mongodb_connection
11
+ Rack::GridFS.any_instance.stubs(:connect!).returns(true)
12
+ end
13
+
14
+ def test_database_options
15
+ { :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs' }
16
+ end
17
+
18
+ def db
19
+ @db ||= Mongo::Connection.new(test_database_options[:hostname], test_database_options[:port]).db(test_database_options[:database])
20
+ end
21
+
22
+ def app
23
+ Rack::Builder.new do
24
+ use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
25
+ run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
26
+ end
27
+ end
28
+
29
+ def load_artifact(filename, key, content_type)
30
+ GridFS::GridStore.unlink(db, key)
31
+ GridFS::GridStore.open(db, key, 'w', :content_type => content_type) do |dest|
32
+ File.open(File.join(File.dirname(__FILE__), 'artifacts', filename), 'r') do |orig|
33
+ dest.puts orig.read
34
+ end
35
+ end
36
+ end
37
+
38
+ context "Rack::GridFS" do
39
+
40
+ context "on initialization" do
41
+
42
+ setup do
43
+ stub_mongodb_connection
44
+ end
45
+
46
+ should "have a hostname option" do
47
+ mware = Rack::GridFS.new(nil, options_for_gridfs)
48
+ assert_equal options_for_gridfs[:hostname], mware.hostname
49
+ end
50
+
51
+ should "have a default hostname" do
52
+ mware = Rack::GridFS.new(nil, options_for_gridfs.except(:hostname))
53
+ assert_equal 'localhost', mware.hostname
54
+ end
55
+
56
+ should "have a port option" do
57
+ mware = Rack::GridFS.new(nil, options_for_gridfs)
58
+ assert_equal options_for_gridfs[:port], mware.port
59
+ end
60
+
61
+ should "have a default port" do
62
+ mware = Rack::GridFS.new(nil, options_for_gridfs.except(:port))
63
+ assert_equal Mongo::Connection::DEFAULT_PORT, mware.port
64
+ end
65
+
66
+ should "have a database option" do
67
+ mware = Rack::GridFS.new(nil, options_for_gridfs)
68
+ assert_equal options_for_gridfs[:database], mware.database
69
+ end
70
+
71
+ should "not have a default database" do
72
+ mware = Rack::GridFS.new(nil, options_for_gridfs.except(:database))
73
+ assert_nil mware.database
74
+ end
75
+
76
+ should "have a prefix option" do
77
+ mware = Rack::GridFS.new(nil, options_for_gridfs)
78
+ assert_equal mware.prefix, options_for_gridfs[:prefix]
79
+ end
80
+
81
+ should "have a default prefix" do
82
+ mware = Rack::GridFS.new(nil, options_for_gridfs.except(:prefix))
83
+ assert_equal mware.prefix, 'gridfs'
84
+ end
85
+
86
+ should "connect to the MongoDB server" do
87
+ Rack::GridFS.any_instance.expects(:connect!).returns(true).once
88
+ Rack::GridFS.new(nil, options_for_gridfs)
89
+ end
90
+
91
+ end
92
+
93
+ should "delegate requests with a non-matching prefix" do
94
+ %w( / /posts /posts/1 /posts/1/comments ).each do |path|
95
+ get path
96
+ assert last_response.ok?
97
+ assert 'Hello, World!', last_response.body
98
+ end
99
+ end
100
+
101
+ context "with a files in GridFS" do
102
+ setup do
103
+ load_artifact('test.txt', 'test.txt', 'text/plain')
104
+ load_artifact('test.html', 'test.html', 'text/html')
105
+ end
106
+
107
+ should "return TXT files stored in GridFS" do
108
+ get '/gridfs/test.txt'
109
+ assert_equal "Lorem ipsum dolor sit amet.\n", last_response.body
110
+ end
111
+
112
+ should "return the proper content type for TXT files" do
113
+ get '/gridfs/test.txt'
114
+ assert_equal 'text/plain', last_response.content_type
115
+ end
116
+
117
+ should "return HTML files stored in GridFS" do
118
+ get '/gridfs/test.html'
119
+ assert_match /html.*?body.*Test/m, last_response.body
120
+ end
121
+
122
+ should "return the proper content type for HTML files" do
123
+ get '/gridfs/test.html'
124
+ assert_equal 'text/html', last_response.content_type
125
+ end
126
+
127
+ should "return a not found for a unknown path" do
128
+ get '/gridfs/unknown'
129
+ assert last_response.not_found?
130
+ end
131
+
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
+ should "work for small images" do
139
+ load_artifact('3wolfmoon.jpg', 'images/3wolfmoon.jpg', 'image/jpeg')
140
+ get '/gridfs/images/3wolfmoon.jpg'
141
+ assert last_response.ok?
142
+ assert_equal 'image/jpeg', last_response.content_type
143
+ end
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ require 'rack/builder'
7
+ require 'rack/mock'
8
+ require 'rack/test'
9
+
10
+ require 'mongo'
11
+ require 'mongo/gridfs'
12
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'rack', 'gridfs')
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skinandbones-rack-gridfs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Blake Carlson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-21 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rack
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
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
+ - !ruby/object:Gem::Dependency
36
+ name: mongodb-mongo
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "="
42
+ - !ruby/object:Gem::Version
43
+ version: "0.14"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: mocha
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.4
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack-test
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: thoughtbot-shoulda
67
+ type: :development
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ description:
76
+ email: blake@coin-operated.net
77
+ executables: []
78
+
79
+ extensions: []
80
+
81
+ extra_rdoc_files:
82
+ - LICENSE
83
+ - README.rdoc
84
+ files:
85
+ - .gitignore
86
+ - LICENSE
87
+ - README.rdoc
88
+ - Rakefile
89
+ - VERSION
90
+ - example/gridfs_server.rb
91
+ - lib/rack/gridfs.rb
92
+ - rack-gridfs.gemspec
93
+ - test/artifacts/3wolfmoon.jpg
94
+ - test/artifacts/test.html
95
+ - test/artifacts/test.txt
96
+ - test/gridfs_test.rb
97
+ - test/test_helper.rb
98
+ has_rdoc: true
99
+ homepage: http://github.com/skinandbones/rack-gridfs
100
+ licenses:
101
+ post_install_message:
102
+ rdoc_options:
103
+ - --charset=UTF-8
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: "0"
111
+ version:
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: "0"
117
+ version:
118
+ requirements: []
119
+
120
+ rubyforge_project: rack-gridfs
121
+ rubygems_version: 1.3.5
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: Rack middleware for creating HTTP endpoints for files stored in MongoDB's GridFS
125
+ test_files:
126
+ - test/gridfs_test.rb
127
+ - test/test_helper.rb