rack_grid 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+