Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Support using rack-gridfs as a middleware OR endpoint

  • Loading branch information...
commit c36a447035ff33a628e3a9ae57bbd7749ef386d9 1 parent 652ae6b
Ben Marini authored
View
1  .gitignore
@@ -3,3 +3,4 @@ pkg
*.gem
.bundle
Gemfile.lock
+coverage
View
59 lib/rack/gridfs.rb
@@ -5,58 +5,33 @@ module Rack
class GridFSConnectionError < StandardError ; end
class GridFS
+ autoload :Endpoint, "rack/gridfs/endpoint"
- def initialize(app, options = {})
- options = {
- :hostname => 'localhost',
- :port => Mongo::Connection::DEFAULT_PORT,
- :prefix => 'gridfs',
- :lookup => :id
- }.merge(options)
-
- @app = app
- @prefix = options[:prefix].gsub(/^\//, '')
- @lookup = options[:lookup]
- @db = nil
-
- @hostname, @port, @database, @username, @password =
- options.values_at(:hostname, :port, :database, :username, :password)
-
- connect!
+ def initialize(app, options={})
+ @app = app
+ @options = normalize_options(options)
end
def call(env)
- request = Rack::Request.new(env)
- if request.path_info =~ /^\/#{@prefix}\/(.+)$/
- gridfs_request($1)
+ if env['PATH_INFO'] =~ %r{^/#{@options[:prefix]}/*}
+ endpoint.call(env)
else
@app.call(env)
end
end
private
- def connect!
- Timeout::timeout(5) do
- @db = Mongo::Connection.new(@hostname, @port).db(@database)
- @db.authenticate(@username, @password) if @username
- end
- rescue Exception => e
- raise Rack::GridFSConnectionError, "Unable to connect to the MongoDB server (#{e.to_s})"
- end
- def gridfs_request(identifier)
- file = find_file(identifier)
- [200, {'Content-Type' => file.content_type}, file]
- rescue Mongo::GridFileNotFound, BSON::InvalidObjectId
- [404, {'Content-Type' => 'text/plain'}, ['File not found.']]
- end
-
- def find_file(identifier)
- case @lookup.to_sym
- when :id then Mongo::Grid.new(@db).get(BSON::ObjectId.from_string(identifier))
- when :path then Mongo::GridFileSystem.new(@db).open(identifier, "r")
- end
+ def normalize_options(options)
+ options.tap do |opts|
+ opts[:prefix] ||= "gridfs"
+ opts[:prefix].gsub!(/^\//, '')
+ opts[:mapper] ||= lambda { |p| p[%r{^/#{options[:prefix]}/(.+)}, 1] }
end
+ end
- end # GridFS class
-end # Rack module
+ def endpoint
+ @endpoint ||= Endpoint.new(@options)
+ end
+ end
+end
View
61 lib/rack/gridfs/endpoint.rb
@@ -0,0 +1,61 @@
+module Rack
+ class GridFS
+ class Endpoint
+
+ def initialize(options = {})
+ options = {
+ :hostname => 'localhost',
+ :port => Mongo::Connection::DEFAULT_PORT,
+ :lookup => :id
+ }.merge(options)
+
+ @lookup = options[:lookup]
+ @db = options[:db]
+ @mapper = options[:mapper]
+
+ @hostname, @port, @database, @username, @password =
+ options.values_at(:hostname, :port, :database, :username, :password)
+ end
+
+ def call(env)
+ gridfs_request( identifier_for_path(env['PATH_INFO']) )
+ end
+
+ def identifier_for_path(path)
+ @mapper.respond_to?(:call) ? @mapper.call(path) : path
+ end
+
+ def db
+ @db || connect!
+ end
+
+ private
+
+ def connect!
+ Timeout::timeout(5) do
+ @db = Mongo::Connection.new(@hostname, @port).db(@database)
+ @db.authenticate(@username, @password) if @username
+ end
+
+ return @db
+ rescue Exception => e
+ raise Rack::GridFSConnectionError, "Unable to connect to the MongoDB server (#{e.to_s})"
+ end
+
+ def gridfs_request(identifier)
+ file = find_file(identifier)
+ [200, {'Content-Type' => file.content_type}, file]
+ rescue Mongo::GridFileNotFound, BSON::InvalidObjectId
+ [404, {'Content-Type' => 'text/plain'}, ['File not found.']]
+ end
+
+ def find_file(identifier)
+ case @lookup.to_sym
+ when :id then Mongo::Grid.new(db).get(BSON::ObjectId.from_string(identifier))
+ when :path then Mongo::GridFileSystem.new(db).open(identifier, "r")
+ end
+ end
+
+ end
+ end
+end
View
2  rack-gridfs.gemspec
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
s.rubyforge_project = "rack-gridfs"
s.add_dependency('rack')
- s.add_dependency('mongo', '~> 1.1.5')
+ s.add_dependency('mongo', '~> 1.2')
s.add_development_dependency('bundler', '>= 1.0.0')
s.add_development_dependency('mocha', '0.9.4')
View
66 test/gridfs_test.rb
@@ -2,38 +2,7 @@
class Rack::GridFSTest < Test::Unit::TestCase
include Rack::Test::Methods
-
- def stub_mongodb_connection
- Rack::GridFS.any_instance.stubs(:connect!).returns(true)
- end
-
- def test_database_options
- { :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs' }
- end
-
- def db
- @db ||= Mongo::Connection.new(test_database_options[:hostname], test_database_options[:port]).db(test_database_options[:database])
- end
-
- def setup_app(opts={})
- gridfs_opts = test_database_options.merge(opts)
- Rack::Builder.new do
- use Rack::GridFS, gridfs_opts
- run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
- end
- end
-
- def load_artifact(filename, content_type, path=nil)
- contents = File.read(File.join(File.dirname(__FILE__), 'artifacts', filename))
- if path
- grid = Mongo::GridFileSystem.new(db)
- file = [path, filename].join('/')
- grid.open(file, 'w') { |f| f.write contents }
- grid.open(file, 'r')
- else
- Mongo::Grid.new(db).put(contents, :filename => filename, :content_type => content_type)
- end
- end
+ include Rack::GridFS::Test::Methods
context "Rack::GridFS" do
setup do
@@ -55,68 +24,73 @@ def app; setup_app end
end
should "have a hostname option" do
- mware = Rack::GridFS.new(nil, @options)
+ mware = Rack::GridFS::Endpoint.new(@options)
assert_equal @options[:hostname], mware.instance_variable_get(:@hostname)
end
should "have a default hostname" do
- mware = Rack::GridFS.new(nil, @options.except(:hostname))
+ mware = Rack::GridFS::Endpoint.new(@options.except(:hostname))
assert_equal 'localhost', mware.instance_variable_get(:@hostname)
end
should "have a port option" do
- mware = Rack::GridFS.new(nil, @options)
+ mware = Rack::GridFS::Endpoint.new(@options)
assert_equal @options[:port], mware.instance_variable_get(:@port)
end
should "have a default port" do
- mware = Rack::GridFS.new(nil, @options.except(:port))
+ mware = Rack::GridFS::Endpoint.new(@options.except(:port))
assert_equal Mongo::Connection::DEFAULT_PORT, mware.instance_variable_get(:@port)
end
should "have a database option" do
- mware = Rack::GridFS.new(nil, @options)
+ mware = Rack::GridFS::Endpoint.new(@options)
assert_equal @options[:database], mware.instance_variable_get(:@database)
end
should "not have a default database" do
- mware = Rack::GridFS.new(nil, @options.except(:database))
+ mware = Rack::GridFS::Endpoint.new(@options.except(:database))
assert_nil mware.instance_variable_get(:@database)
end
should "have a prefix option" do
mware = Rack::GridFS.new(nil, @options)
- assert_equal mware.instance_variable_get(:@prefix), @options[:prefix]
+ assert_equal mware.instance_variable_get(:@options)[:prefix], 'myprefix'
end
should "have a default prefix" do
mware = Rack::GridFS.new(nil, @options.except(:prefix))
- assert_equal mware.instance_variable_get(:@prefix), 'gridfs'
+ assert_equal mware.instance_variable_get(:@options)[:prefix], 'gridfs'
+ end
+
+ should "have a normalize prefix" do
+ mware = Rack::GridFS.new(nil, @options.merge({:prefix => '/myprefix'}))
+ assert_equal mware.instance_variable_get(:@options)[:prefix], 'myprefix'
end
should "have a username option" do
- mware = Rack::GridFS.new(nil, @options)
+ mware = Rack::GridFS::Endpoint.new(@options)
assert_equal @options[:username], mware.instance_variable_get(:@username)
end
should "have a password option" do
- mware = Rack::GridFS.new(nil, @options)
+ mware = Rack::GridFS::Endpoint.new(@options)
assert_equal @options[:password], mware.instance_variable_get(:@password)
end
should "not have a default username" do
- mware = Rack::GridFS.new(nil, @options.except(:username))
+ mware = Rack::GridFS::Endpoint.new(@options.except(:username))
assert_nil mware.instance_variable_get(:@username)
end
should "not have a default password" do
- mware = Rack::GridFS.new(nil, @options.except(:password))
+ mware = Rack::GridFS::Endpoint.new(@options.except(:password))
assert_nil mware.instance_variable_get(:@password)
end
should "connect to the MongoDB server" do
- Rack::GridFS.any_instance.expects(:connect!).returns(true).once
- Rack::GridFS.new(nil, @options)
+ Rack::GridFS::Endpoint.any_instance.expects(:connect!).returns(true).once
+ Rack::GridFS::Endpoint.new(@options).db
end
end
View
43 test/test_helper.rb
@@ -17,3 +17,46 @@ def except(*keys)
reject { |key,| rejected.include?(key) }
end
end
+
+module Rack
+ class GridFS
+ module Test
+ module Methods
+
+ def stub_mongodb_connection
+ Rack::GridFS::Endpoint.any_instance.stubs(:connect!).returns(true)
+ end
+
+ def test_database_options
+ { :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs' }
+ end
+
+ def db
+ @db ||= Mongo::Connection.new(test_database_options[:hostname], test_database_options[:port]).db(test_database_options[:database])
+ end
+
+ def setup_app(opts={})
+ gridfs_opts = test_database_options.merge(opts)
+
+ Rack::Builder.new do
+ use Rack::GridFS, gridfs_opts
+ run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
+ end
+ end
+
+ def load_artifact(filename, content_type, path=nil)
+ contents = ::File.read(::File.join(::File.dirname(__FILE__), 'artifacts', filename))
+ if path
+ grid = Mongo::GridFileSystem.new(db)
+ file = [path, filename].join('/')
+ grid.open(file, 'w') { |f| f.write contents }
+ grid.open(file, 'r')
+ else
+ Mongo::Grid.new(db).put(contents, :filename => filename, :content_type => content_type)
+ end
+ end
+
+ end
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.