rack_grid 0.0.2

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.
Files changed (4) hide show
  1. data/README.txt +31 -0
  2. data/lib/rack_grid.rb +113 -0
  3. data/test/test_rack_grid.rb +0 -0
  4. metadata +68 -0
data/README.txt ADDED
@@ -0,0 +1,31 @@
1
+ Rack::Grid
2
+
3
+ Rack::Grid is used to serve a GridFS file from rack.
4
+ Especially useful combined with Mongoid::Grid or MongoODM::Grid
5
+
6
+ Installation
7
+
8
+ # gem install rack_grid
9
+
10
+ Usage Example with Sinatra.
11
+
12
+ # app.rb
13
+ require 'rack_grid'
14
+ configure do
15
+ use Rack::Grid, {
16
+ :host => 'localhost', # MongoDB Hostname (default: localhost)
17
+ :port => 27017, # MongoDB Port (default: 27017)
18
+ :username => 'user', # Optional MongoDB Username
19
+ :password => 'pass', # Optional MongoDB Password
20
+ :prefix => 'grid', # URL Prefix (eg: /grid/xxxxxxx/file.ext)
21
+ :cache_control => 300, # Cache Control setting
22
+ :database => 'mydb' # Required database name
23
+ }
24
+ end
25
+
26
+ # view.erb
27
+ <img src="/grid/4ba69fde8c8f369a6e000003/filename.jpg" alt="My Image" />
28
+
29
+
30
+ Inspired by
31
+ http://github.com/skinandbones/rack-gridfs
data/lib/rack_grid.rb ADDED
@@ -0,0 +1,113 @@
1
+ require 'timeout'
2
+ require 'mongo'
3
+ module Rack
4
+ class Grid
5
+ class ConnectionError < StandardError ; end
6
+
7
+ attr_reader :host, :port, :database, :prefix, :username, :password
8
+
9
+ def initialize(app, options = {})
10
+ opts = {}
11
+ options.each { |k,v| opts[k.to_s] = v }
12
+ options = {
13
+ 'host' => 'localhost',
14
+ 'prefix' => 'grid',
15
+ 'port' => Mongo::Connection::DEFAULT_PORT
16
+ }.merge(opts)
17
+
18
+ @app = app
19
+ @host = options['host']
20
+ @port = options['port']
21
+ @database = options['database']
22
+ @prefix = options['prefix']
23
+ @username = options['username']
24
+ @password = options['password']
25
+ @db = options['db']
26
+
27
+ @cache_control = options['cache_control']
28
+ end
29
+
30
+ def db
31
+ @db = @db.call() if Proc === @db
32
+ connect! unless @db
33
+ @db
34
+ end
35
+
36
+ ##
37
+ # Strip the _id out of the path. This allows the user to send something
38
+ # like /grid/4ba69fde8c8f369a6e000003/filename.jpg to find the file
39
+ # with an id of 4ba69fde8c8f369a6e000003.
40
+ def call(env)
41
+ @env = env
42
+ request = Rack::Request.new(@env)
43
+ if request.path_info =~ /^\/#{prefix}\/(\w+).*$/
44
+ grid_request($1)
45
+ else
46
+ @app.call(env)
47
+ end
48
+ end
49
+
50
+ ##
51
+ # Get file from GridFS or return a 404
52
+ def grid_request(id)
53
+ file = Mongo::Grid.new(db).get(BSON::ObjectId.from_string(id))
54
+ etag, last_modified = file.instance_variable_get(:@md5), Time.at( file.upload_date.to_i )
55
+ headers = {
56
+ 'ETag' => "\"#{etag}\"",
57
+ 'Last-Modified' => last_modified.httpdate,
58
+ 'Cache-Control' => cache_control_header,
59
+ }
60
+ if not_modified?( etag, last_modified )
61
+ [304, headers, 'Not Modified']
62
+ else
63
+ [200, headers.update('Content-Type' => file.content_type), [file.read]]
64
+ end
65
+ rescue Mongo::GridError, BSON::InvalidObjectId
66
+ [404, {'Content-Type' => 'text/plain'}, ['File not found.']]
67
+ end
68
+
69
+ private
70
+ def connect!
71
+ Timeout::timeout(5) do
72
+ @db = Mongo::Connection.new(host,port).db(database)
73
+ db.authenticate(username, password) if (username || password)
74
+ end
75
+ rescue StandardError => e
76
+ raise ConnectionError, "Timeout connecting to GridFS (#{e.to_s})"
77
+ end
78
+
79
+ DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
80
+ def cache_control_header
81
+ if @cache_control.blank?
82
+ DEFAULT_CACHE_CONTROL
83
+
84
+ elsif @cache_control[:no_cache]
85
+ 'no-cache'
86
+
87
+ else
88
+ extras = @cache_control[:extras]
89
+ max_age = @cache_control[:max_age]
90
+
91
+ options = []
92
+ options << "max-age=#{max_age.to_i}" if max_age
93
+ options << (@cache_control[:public] ? 'public' : 'private')
94
+ options << 'must-revalidate' if @cache_control[:must_revalidate]
95
+ options.concat(extras) if extras
96
+
97
+ options.join(', ')
98
+ end
99
+ end
100
+
101
+ def not_modified?( etag, last_modified )
102
+ if_none_match = @env['HTTP_IF_NONE_MATCH']
103
+ if if_modified_since = @env['HTTP_IF_MODIFIED_SINCE']
104
+ if_modified_since = Time.rfc2822( if_modified_since ) rescue nil
105
+ end
106
+
107
+ not_modified = if_none_match.present? || if_modified_since.present?
108
+ not_modified &&= (if_none_match == "\"#{etag}\"") if if_none_match && etag
109
+ not_modified &&= (if_modified_since >= last_modified) if if_modified_since && last_modified
110
+ not_modified
111
+ end
112
+ end
113
+ end
File without changes
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack_grid
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.2
6
+ platform: ruby
7
+ authors:
8
+ - Dusty Doris
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-10 00:00:00 -04:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: mongo
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: Rack helper for presenting MongoDB GridFS Files
28
+ email: github@dusty.name
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files:
34
+ - README.txt
35
+ files:
36
+ - README.txt
37
+ - lib/rack_grid.rb
38
+ - test/test_rack_grid.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/dusty/rack_grid
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project: none
63
+ rubygems_version: 1.6.2
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Rack helper for presenting MongoDB GridFS Files
67
+ test_files: []
68
+