rack-gridfs 0.3.0 → 0.4.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/CHANGES.rdoc ADDED
@@ -0,0 +1,31 @@
1
+ == CHANGE LOG
2
+
3
+ === 0.4.0 / May 12, 2011
4
+
5
+ Major refactoring and loads of new features! Thanks to {Ben Marini}[https://github.com/bmarini]
6
+ for his substantial contributions to this release.
7
+
8
+ {full commit log}[https://github.com/skinandbones/rack-gridfs/compare/v0.2.0...v0.4.0]
9
+
10
+ ==== Features
11
+
12
+ - Allow configuration of MongoDB authentication (Steve Sloan)
13
+ - Allow option to look up objects by GridFS filename instead of +ObjectId+
14
+ (SHIBATA Hiroshi)
15
+ - Return iterable GridIO object instead of file contents, so Rack can stream in
16
+ chunks (Ches Martin)
17
+ - <tt>Rack::GridFS::Endpoint</tt>: support for mounting as a Rack endpoint in
18
+ addition to middleware (Ben Marini)
19
+ - Cache headers: set <tt>Last-Modified</tt> and +Etag+ so that
20
+ <tt>Rack::ConditionalGet</tt> sends 304s. +expires+ option to set
21
+ <tt>Cache-Control</tt> (Alexander Gräfe & Ben Marini)
22
+ - <tt>mime-types</tt> dependency so GridFS lib can determine content types
23
+ (Ben Marini)
24
+ - You can now pass a <tt>Mongo::DB</tt> instance instead of discrete database
25
+ configuration parameters. Connections are retried so we take advantage of a
26
+ +ReplSetConnection+ in high-availability architectures (Ben Marini)
27
+
28
+ ==== Bug Fixes
29
+
30
+ - <tt>BSON::ObjectID</tt> renamed to +ObjectId+, and other changes supporting
31
+ current versions of Mongo libraries
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Blake Carlson
1
+ Copyright (c) 2009-2011 Blake Carlson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -2,53 +2,149 @@
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 supply an id for looking
6
- up the file in the GridFS store.
5
+ will be used to match the path of a request, and further look up GridFS
6
+ files based on either their +ObjectId+ or +filename+ field.
7
7
 
8
8
  For example,
9
9
 
10
10
  GET '/gridfs/someobjectid'
11
-
11
+
12
12
  If the prefix is "gridfs", then the id will be be "someobjectid".
13
13
 
14
- == Mongo Driver Compatibility Notes
14
+ You can also use Rack::GridFS::Endpoint as a rack endpoint if you want to
15
+ handle routing another way
15
16
 
16
- This version is currently based off of mongo-0.20.1.
17
+ == Mongo Driver Compatibility Notes
17
18
 
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.
19
+ This version is currently based on mongo-1.2+. As there were significant changes
20
+ to the GridFS API prior to v1.0, you may have luck with the git-tagged version
21
+ 0.2.0 of this library with earlier versions of the driver.
22
22
 
23
23
  == Installation
24
24
 
25
- sudo gem install skinandbones-rack-gridfs --source=http://gems.github.com
25
+ gem install rack-gridfs
26
+
27
+ == Features
28
+ - Use as rack middleware or mount as a rack endpoint
29
+ - File lookup using a path or object id
30
+ - Chunked transfer encoding, keeps memory usage low
31
+ - Content-Type header set using 'mime-types' gem
32
+ - Last-Modified and Etag headers set automatically for conditional get support
33
+ - Cache-Control header support
34
+ - High availability when using replication sets
26
35
 
27
36
  == Usage
28
37
 
29
38
  require 'rack/gridfs'
30
- use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
39
+ use Rack::GridFS, :prefix => 'gridfs', :hostname => 'localhost', :port => 27017, :database => 'test'
31
40
 
32
- You must specify MongoDB database details:
33
- - hostname: the hostname/IP where the MongoDB server is running. Default 'localhost'.
34
- - port: the port of the MongoDB server. Default 27017.
35
- - database: the MongoDB database to connect to.
36
- - prefix: a string used to match against incoming paths and route to through the middleware. Default 'gridfs'.
41
+ Options:
42
+ - +prefix+: a string used to match against incoming paths and route to through
43
+ the middleware. Default 'gridfs'.
44
+ - +lookup+: whether to look up a file based on <tt>:id</tt> or <tt>:path</tt>
45
+ (example below). Default is <tt>:id</tt>.
37
46
 
38
- == Sinatra Example
47
+ You must also specify MongoDB database details:
48
+ - +hostname+: the hostname/IP where the MongoDB server is running. Default 'localhost'.
49
+ - +port+: the port of the MongoDB server. Default 27017.
50
+ - +database+: the name of the MongoDB database to connect to.
51
+ - +username+ and +password+: if you need to authenticate to MongoDB.
39
52
 
40
- # TODO: THIS COULD USE A LOT MORE EXPLANATION!
53
+ Alternatively you can pass in a <tt>Mongo::DB</tt> instance instead:
54
+ - +db+: MongoMapper.database, or Mongoid.database for example.
55
+
56
+ === Simple Sinatra Example
41
57
 
42
58
  require 'rubygems'
43
59
  require 'sinatra'
44
60
 
45
61
  require 'rack/gridfs'
46
- use Rack::GridFS, :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs'
62
+ use Rack::GridFS, :database => 'test', :prefix => 'gridfs'
47
63
 
48
64
  get /.*/ do
49
65
  "The URL did not match a file in GridFS."
50
66
  end
51
67
 
68
+ === Usage with Rails 2
69
+
70
+ To use <tt>Rack::GridFS</tt> in a Rails application, add it as middleware in
71
+ <tt>application.rb</tt> or <tt>config/environments/*</tt>with something like this:
72
+
73
+ config.middleware.insert_after Rack::Runtime, Rack::GridFS,
74
+ :prefix => 'uploads', :database => "my_app_#{Rails.env}"
75
+
76
+ Run <tt>rake middleware</tt> to decide for yourself where to best place it in
77
+ the middleware stack for your app using {the Rails convenience methods}[http://guides.rubyonrails.org/rails_on_rack.html#configuring-middleware-stack],
78
+ taking into consideration that it can probably be near the top since it simply
79
+ returns a "static" file or a 404.
80
+
81
+ === Usage with Rails 3
82
+
83
+ To use in Rails 3, you can insert into the middleware stack as above, or mount
84
+ the app directly in your routes (recommended). In <tt>config/routes.rb</tt>:
85
+
86
+ mount Rack::GridFS::Endpoint.new(:db => Mongoid.database), :at => "gridfs"
87
+
88
+ This allows for much more straightforward and sensible configuration, if you do
89
+ not require other middleware in front of GridFS (Rack-based authorization, for
90
+ instance).
91
+
92
+ === Path (filename) Lookup
93
+
94
+ The <tt>:lookup => :path</tt> option causes files to be looked up from the GridFS
95
+ store based on their +filename+ field (which can be a full file path) rather than
96
+ +ObjectId+ (requests still need to match the +prefix+ you've set). This allows
97
+ you to find files based on essentially arbitrary URLs such as:
98
+
99
+ GET '/prefix/media/images/jane_avatar.jpg'
100
+
101
+ How filenames are set is specific to your application. We'll look at an example
102
+ with Carrierwave below.
103
+
104
+ *NOTE*: The Mongo Ruby driver will try to create an index on the +filename+
105
+ field for you automatically, but if you are using filename lookup you'll want to
106
+ double-check that it is created appropriately (on slaves only if you have a
107
+ master-slave architecture, etc.).
108
+
109
+ === Carrierwave Example
110
+
111
+ Path lookup works well for usage with Carrierwave[https://github.com/jnicklas/carrierwave].
112
+ As a minimal example with Mongoid:
113
+
114
+ # config/initializers/carrierwave.rb
115
+ CarrierWave.configure do |config|
116
+ config.storage = :grid_fs
117
+ config.grid_fs_connection = Mongoid.database
118
+ config.grid_fs_access_url = "/uploads"
119
+ end
120
+
121
+ # app/uploaders/avatar_uploader.rb
122
+ class AvatarUploader < CarrierWave::Uploader::Base
123
+ # (Virtual) path where uploaded files will be stored, appended to the
124
+ # gridfs_access_url by methods used with view helpers
125
+ def store_dir
126
+ "#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
127
+ end
128
+ end
129
+
130
+ # app/models/user.rb
131
+ class User
132
+ include Mongoid::Document
133
+ mount_uploader :avatar, AvatarUploader
134
+ end
135
+
136
+ # app/views/user/show.html.erb
137
+ <%= image_tag(@user.avatar.url) if @user.avatar? %>
138
+
139
+ This will result in URL paths like <tt>/uploads/user/avatar/4d250d04a8f41c0a31000006/original_filename.jpg</tt>
140
+ being generated for the view helpers, and Carrierwave will store
141
+ <tt>user/avatar/4d250d04a8f41c0a31000006/original_filename.jpg</tt> as the
142
+ +filename+ in GridFS. Thus, you can configure <tt>Rack::GridFS</tt> to serve
143
+ these files as such:
144
+
145
+ config.middleware.insert_after Rack::Runtime, Rack::GridFS,
146
+ :prefix => 'uploads', :lookup => :path, :database => "my_app_#{Rails.env}"
147
+
52
148
  == Copyright
53
149
 
54
- Copyright (c) 2010 Blake Carlson. See LICENSE for details.
150
+ Copyright (c) 2010-2011 Blake Carlson. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,30 +1,5 @@
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('mongo', '>=0.20.1')
16
-
17
- gem.add_development_dependency('mocha', '0.9.4')
18
- gem.add_development_dependency('rack-test')
19
- gem.add_development_dependency('shoulda')
20
- end
21
- Jeweler::GemcutterTasks.new
22
- Jeweler::RubyforgeTasks.new do |rubyforge|
23
- rubyforge.doc_task = "rdoc"
24
- end
25
- rescue LoadError
26
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
27
- end
1
+ require 'bundler/setup'
2
+ Bundler::GemHelper.install_tasks
28
3
 
29
4
  require 'rake/testtask'
30
5
  Rake::TestTask.new(:test) do |test|
@@ -37,29 +12,24 @@ begin
37
12
  require 'rcov/rcovtask'
38
13
  Rcov::RcovTask.new do |test|
39
14
  test.libs << 'test'
40
- test.pattern = 'test/**/*_test.rb'
15
+ test.test_files = FileList['test/**/*_test.rb']
41
16
  test.verbose = true
17
+ test.rcov_opts << '--exclude /gems/,/Library/,/usr/,spec,lib/tasks'
42
18
  end
43
19
  rescue LoadError
44
20
  task :rcov do
45
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
21
+ abort "RCov is not available. In order to run rcov, you must: gem install rcov"
46
22
  end
47
23
  end
48
24
 
49
- task :test => :check_dependencies
50
-
51
25
  task :default => :test
52
26
 
53
27
  require 'rake/rdoctask'
54
28
  Rake::RDocTask.new do |rdoc|
55
- if File.exist?('VERSION')
56
- version = File.read('VERSION')
57
- else
58
- version = ""
59
- end
29
+ require File.expand_path("../lib/rack/gridfs/version", __FILE__)
60
30
 
61
31
  rdoc.rdoc_dir = 'rdoc'
62
- rdoc.title = "Rack::GridFS #{version}"
63
- rdoc.rdoc_files.include('README*')
32
+ rdoc.title = "Rack::GridFS #{Rack::GridFS::VERSION}"
33
+ rdoc.rdoc_files.include(%w[ README* CHANGES* ])
64
34
  rdoc.rdoc_files.include('lib/**/*.rb')
65
35
  end
data/lib/rack/gridfs.rb CHANGED
@@ -1,57 +1,52 @@
1
- require 'timeout'
2
1
  require 'mongo'
2
+ require 'mime/types'
3
3
 
4
4
  module Rack
5
-
6
5
  class GridFSConnectionError < StandardError ; end
7
-
6
+
7
+ # Rack middleware that will serve GridFS files from a specified path prefix.
8
+ # By default the prefix is stripped from the path before file lookup in
9
+ # GridFS occurs.
10
+ #
11
+ # For example:
12
+ #
13
+ # "/gridfs/filename.png" -> "filename.png"
14
+ #
15
+ # If you are using Rails you can mount the endpoint directly.
16
+ #
17
+ # For example (in config/routes.rb):
18
+ #
19
+ # mount Rack::GridFS::Endpoint, :at => "gridfs"
20
+
8
21
  class GridFS
22
+ autoload :Endpoint, "rack/gridfs/endpoint"
9
23
 
10
- attr_reader :hostname, :port, :database, :prefix, :db
11
-
12
- def initialize(app, options = {})
13
- options = {
14
- :hostname => 'localhost',
15
- :prefix => 'gridfs',
16
- :port => Mongo::Connection::DEFAULT_PORT
17
- }.merge(options)
18
-
19
- @app = app
20
- @hostname = options[:hostname]
21
- @port = options[:port]
22
- @database = options[:database]
23
- @prefix = options[:prefix]
24
- @db = nil
25
-
26
- connect!
24
+ def initialize(app, options={})
25
+ @app = app
26
+ @options = normalize_options(options)
27
27
  end
28
28
 
29
29
  def call(env)
30
- request = Rack::Request.new(env)
31
- if request.path_info =~ /^\/#{prefix}\/(.+)$/
32
- gridfs_request($1)
30
+ if env['PATH_INFO'] =~ %r{^/#{@options[:prefix]}/*}
31
+ endpoint.call(env)
33
32
  else
34
33
  @app.call(env)
35
34
  end
36
35
  end
37
36
 
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
42
- [404, {'Content-Type' => 'text/plain'}, ['File not found.']]
43
- end
44
-
45
37
  private
46
-
47
- def connect!
48
- Timeout::timeout(5) do
49
- @db = Mongo::Connection.new(hostname).db(database)
38
+
39
+ # TODO: doc explanation/example of custom mapper
40
+ def normalize_options(options)
41
+ options.tap do |opts|
42
+ opts[:prefix] ||= "gridfs"
43
+ opts[:prefix].gsub!(/^\//, '')
44
+ opts[:mapper] ||= lambda { |path| %r!^/#{options[:prefix]}/(.+)!.match(path)[1] }
50
45
  end
51
- rescue Exception => e
52
- raise Rack::GridFSConnectionError, "Unable to connect to the MongoDB server (#{e.to_s})"
53
46
  end
54
-
47
+
48
+ def endpoint
49
+ @endpoint ||= Endpoint.new(@options)
50
+ end
55
51
  end
56
-
57
52
  end
@@ -0,0 +1,13 @@
1
+ require 'rack/gridfs/endpoint/base'
2
+ require 'rack/gridfs/endpoint/caching'
3
+ require 'rack/gridfs/endpoint/connection'
4
+
5
+ module Rack
6
+ class GridFS
7
+ class Endpoint
8
+ include Base
9
+ include Connection
10
+ include Caching
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,76 @@
1
+ module Rack
2
+ class GridFS
3
+ class Endpoint
4
+ module Base
5
+ attr_reader :db
6
+
7
+ def initialize(options = {})
8
+ @options = default_options.merge(options)
9
+
10
+ @db = @options[:db]
11
+ @lookup = @options[:lookup]
12
+ @mapper = @options[:mapper]
13
+ end
14
+
15
+ def call(env)
16
+ with_rescues do
17
+ request = Rack::Request.new(env)
18
+ key = key_for_path(request.path_info)
19
+ file = find_file(key)
20
+
21
+ response_for(file, request)
22
+ end
23
+ end
24
+
25
+ def key_for_path(path)
26
+ @mapper.respond_to?(:call) ? @mapper.call(path) : path
27
+ end
28
+
29
+ protected
30
+
31
+ def default_options
32
+ {
33
+ :lookup => :id,
34
+ :mapper => lambda { |path| %r!/(.+)!.match(path)[1] }
35
+ }
36
+ end
37
+
38
+ def with_rescues
39
+ rescue_connection_failure { yield }
40
+ rescue Mongo::GridFileNotFound, BSON::InvalidObjectId => e
41
+ [ 404, {'Content-Type' => 'text/plain'}, ["File not found. #{e}"] ]
42
+ rescue Mongo::GridError => e
43
+ [ 500, {'Content-Type' => 'text/plain'}, ["An error occured. #{e}"] ]
44
+ end
45
+
46
+ def rescue_connection_failure(max_retries=60)
47
+ retries = 0
48
+ begin
49
+ yield
50
+ rescue Mongo::ConnectionFailure => e
51
+ retries += 1
52
+ raise e if retries > max_retries
53
+ sleep(0.5)
54
+ retry
55
+ end
56
+ end
57
+
58
+ def response_for(file, request)
59
+ [ 200, headers(file), file ]
60
+ end
61
+
62
+ def find_file(id_or_path)
63
+ case @lookup.to_sym
64
+ when :id then Mongo::Grid.new(db).get(BSON::ObjectId.from_string(id_or_path))
65
+ when :path then Mongo::GridFileSystem.new(db).open(id_or_path, "r")
66
+ end
67
+ end
68
+
69
+ def headers(file)
70
+ { 'Content-Type' => file.content_type }
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,34 @@
1
+ module Rack
2
+ class GridFS
3
+ class Endpoint
4
+
5
+ module Caching
6
+ def initialize(*)
7
+ super
8
+ @options[:expires] ||= false
9
+ end
10
+
11
+ protected
12
+
13
+ def headers(file)
14
+ super.merge(
15
+ 'Last-Modified' => file.upload_date.httpdate,
16
+ 'Etag' => file.files_id.to_s
17
+ ).merge(cache_control_header)
18
+ end
19
+
20
+ private
21
+
22
+ def cache_control_header
23
+ if @options[:expires]
24
+ { "Cache-Control" => "max-age=#{@options[:expires]}, public" }
25
+ else
26
+ {}
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ require 'timeout'
2
+
3
+ module Rack
4
+ class GridFS
5
+ class Endpoint
6
+
7
+ module Connection
8
+ def initialize(*)
9
+ super
10
+
11
+ @hostname, @port, @database, @username, @password =
12
+ @options.values_at(:hostname, :port, :database, :username, :password)
13
+ end
14
+
15
+ def default_options
16
+ super.merge({
17
+ :hostname => 'localhost',
18
+ :port => Mongo::Connection::DEFAULT_PORT
19
+ })
20
+ end
21
+
22
+ def db
23
+ @db ||= (super || connect!)
24
+ end
25
+
26
+ protected
27
+
28
+ def connect!
29
+ database = nil
30
+
31
+ Timeout::timeout(5) do
32
+ database = Mongo::Connection.new(@hostname, @port).db(@database)
33
+ database.authenticate(@username, @password) if @username
34
+ end
35
+
36
+ return database
37
+ rescue Exception => e
38
+ raise Rack::GridFSConnectionError, "Unable to connect to the MongoDB server (#{e.to_s})"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ class GridFS
3
+ VERSION = "0.4.0"
4
+ end
5
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-gridfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ hash: 15
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 4
9
+ - 0
10
+ version: 0.4.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Blake Carlson
@@ -9,110 +15,183 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-05-11 00:00:00 -04:00
18
+ date: 2011-05-13 00:00:00 +07:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
- name: rack
22
+ prerelease: false
17
23
  type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
23
32
  version: "0"
24
- version:
33
+ version_requirements: *id001
34
+ name: rack
25
35
  - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ type: :runtime
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 11
44
+ segments:
45
+ - 1
46
+ - 2
47
+ version: "1.2"
48
+ version_requirements: *id002
26
49
  name: mongo
50
+ - !ruby/object:Gem::Dependency
51
+ prerelease: false
27
52
  type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ version_requirements: *id003
63
+ name: mime-types
64
+ - !ruby/object:Gem::Dependency
65
+ prerelease: false
66
+ type: :development
67
+ requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
30
69
  requirements:
31
70
  - - ">="
32
71
  - !ruby/object:Gem::Version
33
- version: 0.20.1
34
- version:
72
+ hash: 23
73
+ segments:
74
+ - 1
75
+ - 0
76
+ - 0
77
+ version: 1.0.0
78
+ version_requirements: *id004
79
+ name: bundler
35
80
  - !ruby/object:Gem::Dependency
36
- name: mocha
81
+ prerelease: false
37
82
  type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
83
+ requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
40
85
  requirements:
41
86
  - - "="
42
87
  - !ruby/object:Gem::Version
43
- version: 0.9.4
44
- version:
88
+ hash: 35
89
+ segments:
90
+ - 0
91
+ - 9
92
+ - 12
93
+ version: 0.9.12
94
+ version_requirements: *id005
95
+ name: mocha
45
96
  - !ruby/object:Gem::Dependency
97
+ prerelease: false
98
+ type: :development
99
+ requirement: &id006 !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ version_requirements: *id006
46
109
  name: rack-test
110
+ - !ruby/object:Gem::Dependency
111
+ prerelease: false
47
112
  type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
113
+ requirement: &id007 !ruby/object:Gem::Requirement
114
+ none: false
50
115
  requirements:
51
116
  - - ">="
52
117
  - !ruby/object:Gem::Version
118
+ hash: 3
119
+ segments:
120
+ - 0
53
121
  version: "0"
54
- version:
122
+ version_requirements: *id007
123
+ name: rake
55
124
  - !ruby/object:Gem::Dependency
56
- name: shoulda
125
+ prerelease: false
57
126
  type: :development
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
127
+ requirement: &id008 !ruby/object:Gem::Requirement
128
+ none: false
60
129
  requirements:
61
130
  - - ">="
62
131
  - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
63
135
  version: "0"
64
- version:
65
- description:
66
- email: blake@coin-operated.net
136
+ version_requirements: *id008
137
+ name: shoulda
138
+ description: Rack middleware for creating HTTP endpoints for files stored in MongoDB's GridFS
139
+ email:
140
+ - blake@coin-operated.net
67
141
  executables: []
68
142
 
69
143
  extensions: []
70
144
 
71
145
  extra_rdoc_files:
146
+ - CHANGES.rdoc
72
147
  - LICENSE
73
148
  - README.rdoc
74
149
  files:
75
- - .gitignore
150
+ - lib/rack/gridfs/endpoint/base.rb
151
+ - lib/rack/gridfs/endpoint/caching.rb
152
+ - lib/rack/gridfs/endpoint/connection.rb
153
+ - lib/rack/gridfs/endpoint.rb
154
+ - lib/rack/gridfs/version.rb
155
+ - lib/rack/gridfs.rb
76
156
  - LICENSE
77
157
  - README.rdoc
78
158
  - Rakefile
79
- - VERSION
80
- - example/gridfs_server.rb
81
- - lib/rack/gridfs.rb
82
- - rack-gridfs.gemspec
83
- - test/artifacts/3wolfmoon.jpg
84
- - test/artifacts/test.html
85
- - test/artifacts/test.txt
86
- - test/gridfs_test.rb
87
- - test/test_helper.rb
159
+ - CHANGES.rdoc
88
160
  has_rdoc: true
89
161
  homepage: http://github.com/skinandbones/rack-gridfs
90
162
  licenses: []
91
163
 
92
164
  post_install_message:
93
- rdoc_options:
94
- - --charset=UTF-8
165
+ rdoc_options: []
166
+
95
167
  require_paths:
96
168
  - lib
97
169
  required_ruby_version: !ruby/object:Gem::Requirement
170
+ none: false
98
171
  requirements:
99
172
  - - ">="
100
173
  - !ruby/object:Gem::Version
174
+ hash: 3
175
+ segments:
176
+ - 0
101
177
  version: "0"
102
- version:
103
178
  required_rubygems_version: !ruby/object:Gem::Requirement
179
+ none: false
104
180
  requirements:
105
181
  - - ">="
106
182
  - !ruby/object:Gem::Version
107
- version: "0"
108
- version:
183
+ hash: 23
184
+ segments:
185
+ - 1
186
+ - 3
187
+ - 6
188
+ version: 1.3.6
109
189
  requirements: []
110
190
 
111
191
  rubyforge_project: rack-gridfs
112
- rubygems_version: 1.3.5
192
+ rubygems_version: 1.5.2
113
193
  signing_key:
114
194
  specification_version: 3
115
- summary: Rack middleware for creating HTTP endpoints for files stored in MongoDB's GridFS
116
- test_files:
117
- - test/gridfs_test.rb
118
- - test/test_helper.rb
195
+ summary: Serve MongoDB GridFS files from Rack
196
+ test_files: []
197
+
data/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- rdoc
2
- pkg
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.3.0
@@ -1,9 +0,0 @@
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
data/rack-gridfs.gemspec DELETED
@@ -1,69 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{rack-gridfs}
8
- s.version = "0.3.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{2010-05-11}
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.homepage = %q{http://github.com/skinandbones/rack-gridfs}
34
- s.rdoc_options = ["--charset=UTF-8"]
35
- s.require_paths = ["lib"]
36
- s.rubyforge_project = %q{rack-gridfs}
37
- s.rubygems_version = %q{1.3.5}
38
- s.summary = %q{Rack middleware for creating HTTP endpoints for files stored in MongoDB's GridFS}
39
- s.test_files = [
40
- "test/gridfs_test.rb",
41
- "test/test_helper.rb"
42
- ]
43
-
44
- if s.respond_to? :specification_version then
45
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
- s.specification_version = 3
47
-
48
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
- s.add_runtime_dependency(%q<rack>, [">= 0"])
50
- s.add_runtime_dependency(%q<mongo>, [">= 0.20.1"])
51
- s.add_development_dependency(%q<mocha>, ["= 0.9.4"])
52
- s.add_development_dependency(%q<rack-test>, [">= 0"])
53
- s.add_development_dependency(%q<shoulda>, [">= 0"])
54
- else
55
- s.add_dependency(%q<rack>, [">= 0"])
56
- s.add_dependency(%q<mongo>, [">= 0.20.1"])
57
- s.add_dependency(%q<mocha>, ["= 0.9.4"])
58
- s.add_dependency(%q<rack-test>, [">= 0"])
59
- s.add_dependency(%q<shoulda>, [">= 0"])
60
- end
61
- else
62
- s.add_dependency(%q<rack>, [">= 0"])
63
- s.add_dependency(%q<mongo>, [">= 0.20.1"])
64
- s.add_dependency(%q<mocha>, ["= 0.9.4"])
65
- s.add_dependency(%q<rack-test>, [">= 0"])
66
- s.add_dependency(%q<shoulda>, [">= 0"])
67
- end
68
- end
69
-
Binary file
@@ -1,15 +0,0 @@
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>
@@ -1 +0,0 @@
1
- Lorem ipsum dolor sit amet.
data/test/gridfs_test.rb DELETED
@@ -1,141 +0,0 @@
1
- require 'test_helper'
2
-
3
- class Rack::GridFSTest < Test::Unit::TestCase
4
- include Rack::Test::Methods
5
-
6
- def stub_mongodb_connection
7
- Rack::GridFS.any_instance.stubs(:connect!).returns(true)
8
- end
9
-
10
- def test_database_options
11
- { :hostname => 'localhost', :port => 27017, :database => 'test', :prefix => 'gridfs' }
12
- end
13
-
14
- def db
15
- @db ||= Mongo::Connection.new(test_database_options[:hostname], test_database_options[:port]).db(test_database_options[:database])
16
- end
17
-
18
- def app
19
- gridfs_opts = test_database_options
20
- Rack::Builder.new do
21
- use Rack::GridFS, gridfs_opts
22
- run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
23
- end
24
- end
25
-
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)
29
- end
30
-
31
- context "Rack::GridFS" do
32
-
33
- context "on initialization" do
34
-
35
- setup do
36
- stub_mongodb_connection
37
- @options = { :hostname => 'myhostname.mydomain', :port => 8765, :database => 'mydatabase', :prefix => 'myprefix' }
38
- end
39
-
40
- should "have a hostname option" do
41
- mware = Rack::GridFS.new(nil, @options)
42
- assert_equal @options[:hostname], mware.hostname
43
- end
44
-
45
- should "have a default hostname" do
46
- mware = Rack::GridFS.new(nil, @options.except(:hostname))
47
- assert_equal 'localhost', mware.hostname
48
- end
49
-
50
- should "have a port option" do
51
- mware = Rack::GridFS.new(nil, @options)
52
- assert_equal @options[:port], mware.port
53
- end
54
-
55
- should "have a default port" do
56
- mware = Rack::GridFS.new(nil, @options.except(:port))
57
- assert_equal Mongo::Connection::DEFAULT_PORT, mware.port
58
- end
59
-
60
- should "have a database option" do
61
- mware = Rack::GridFS.new(nil, @options)
62
- assert_equal @options[:database], mware.database
63
- end
64
-
65
- should "not have a default database" do
66
- mware = Rack::GridFS.new(nil, @options.except(:database))
67
- assert_nil mware.database
68
- end
69
-
70
- should "have a prefix option" do
71
- mware = Rack::GridFS.new(nil, @options)
72
- assert_equal mware.prefix, @options[:prefix]
73
- end
74
-
75
- should "have a default prefix" do
76
- mware = Rack::GridFS.new(nil, @options.except(:prefix))
77
- assert_equal mware.prefix, 'gridfs'
78
- end
79
-
80
- should "connect to the MongoDB server" do
81
- Rack::GridFS.any_instance.expects(:connect!).returns(true).once
82
- Rack::GridFS.new(nil, @options)
83
- end
84
-
85
- end
86
-
87
- should "delegate requests with a non-matching prefix" do
88
- %w( / /posts /posts/1 /posts/1/comments ).each do |path|
89
- get path
90
- assert last_response.ok?
91
- assert 'Hello, World!', last_response.body
92
- end
93
- end
94
-
95
- context "with files in GridFS" do
96
- setup do
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
103
- end
104
-
105
- should "return TXT files stored in GridFS" do
106
- get "/gridfs/#{@text_id}"
107
- assert_equal "Lorem ipsum dolor sit amet.", last_response.body
108
- end
109
-
110
- should "return the proper content type for TXT files" do
111
- get "/gridfs/#{@text_id}"
112
- assert_equal 'text/plain', last_response.content_type
113
- end
114
-
115
- should "return HTML files stored in GridFS" do
116
- get "/gridfs/#{@html_id}"
117
- assert_match /html.*?body.*Test/m, last_response.body
118
- end
119
-
120
- should "return the proper content type for HTML files" do
121
- get "/gridfs/#{@html_id}"
122
- assert_equal 'text/html', last_response.content_type
123
- end
124
-
125
- should "return a not found for a unknown path" do
126
- get '/gridfs/unknown'
127
- assert last_response.not_found?
128
- end
129
-
130
- should "work for small images" do
131
- image_id = load_artifact('3wolfmoon.jpg', 'image/jpeg')
132
- get "/gridfs/#{image_id}"
133
- assert last_response.ok?
134
- assert_equal 'image/jpeg', last_response.content_type
135
- end
136
- end
137
-
138
- end
139
-
140
- end
141
-
data/test/test_helper.rb DELETED
@@ -1,19 +0,0 @@
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 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