rack-mogilefs 0.2.0 → 0.3.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 +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +24 -0
- data/HISTORY.md +8 -0
- data/README.md +36 -31
- data/Rakefile +4 -1
- data/lib/rack/mogilefs.rb +1 -0
- data/lib/rack/mogilefs/endpoint.rb +25 -67
- data/lib/rack/mogilefs/endpoint/base.rb +47 -0
- data/lib/rack/mogilefs/endpoint/caching.rb +40 -0
- data/lib/rack/mogilefs/endpoint/client.rb +41 -0
- data/lib/rack/mogilefs/endpoint/mapper.rb +25 -0
- data/lib/rack/mogilefs/endpoint/reproxy.rb +36 -0
- data/lib/rack/mogilefs/endpoint/rescues.rb +36 -0
- data/lib/rack/mogilefs/version.rb +5 -0
- data/rack-mogilefs.gemspec +27 -0
- data/release.rb +6 -0
- data/test/caching_test.rb +38 -0
- data/test/content_type_test.rb +34 -0
- data/test/mapper_test.rb +19 -0
- data/test/mogilefs_test.rb +0 -63
- data/test/reproxy_test.rb +23 -0
- data/test/rescues_test.rb +41 -0
- data/test/test_helper.rb +11 -1
- metadata +32 -24
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rack-mogilefs (0.3.0)
|
5
|
+
mogilefs-client (~> 2.1.0)
|
6
|
+
rack (~> 1.1.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
mocha (0.9.8)
|
12
|
+
rake
|
13
|
+
mogilefs-client (2.1.0)
|
14
|
+
rack (1.1.0)
|
15
|
+
rake (0.8.7)
|
16
|
+
|
17
|
+
PLATFORMS
|
18
|
+
ruby
|
19
|
+
|
20
|
+
DEPENDENCIES
|
21
|
+
mocha
|
22
|
+
mogilefs-client (~> 2.1.0)
|
23
|
+
rack (~> 1.1.0)
|
24
|
+
rack-mogilefs!
|
data/HISTORY.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 0.3.0 (2010-12-30)
|
2
|
+
|
3
|
+
* Major refactoring of internals
|
4
|
+
* Codebase is now more modular, easier to extend and customize
|
5
|
+
* Add support for Cache-Control header
|
6
|
+
* Add debug flag to turn off built-in exception handling and make bugs easier
|
7
|
+
to find
|
8
|
+
|
1
9
|
## 0.2.0 (2010-11-29)
|
2
10
|
|
3
11
|
* Add X-Reproxy-Url support
|
data/README.md
CHANGED
@@ -4,33 +4,6 @@ If you are using Nginx you'll probably want to serve MogileFS files with
|
|
4
4
|
the [MogileFS Module](http://www.grid.net.ru/nginx/mogilefs.en.html), but if
|
5
5
|
you need a quick way to serve them out of a Rack app, this should help.
|
6
6
|
|
7
|
-
## Caveats ( serving files vs reproxying )
|
8
|
-
|
9
|
-
Serving files through Ruby is slow. The preferred method is to set an
|
10
|
-
X-Reproxy-Url header from your app and let the web server serve the file. For
|
11
|
-
Nginx, you could have a config like this:
|
12
|
-
|
13
|
-
location /reproxy {
|
14
|
-
internal;
|
15
|
-
set $reproxy $upstream_http_x_reproxy_url;
|
16
|
-
proxy_pass $reproxy;
|
17
|
-
proxy_hide_header Content-Type;
|
18
|
-
}
|
19
|
-
|
20
|
-
For Apache, there is [mod_reproxy](http://github.com/jamis/mod_reproxy)
|
21
|
-
|
22
|
-
`Rack::MogileFS` will use this method if you pass a strategy option of `:reproxy`
|
23
|
-
|
24
|
-
use Rack::MogileFS, :strategy => :reproxy
|
25
|
-
|
26
|
-
`Rack::MogileFS` will look up the internal urls for the file, and set two
|
27
|
-
headers to reproxy the request:
|
28
|
-
|
29
|
-
X-Accel-Redirect: /reproxy
|
30
|
-
X-Reproxy-Url: http://internal.ip/path/to/mogile/file.fid
|
31
|
-
|
32
|
-
You'll have to make sure your web server knows how to handle this request.
|
33
|
-
|
34
7
|
## Getting Started:
|
35
8
|
|
36
9
|
First install the gem:
|
@@ -39,10 +12,6 @@ First install the gem:
|
|
39
12
|
|
40
13
|
There are a variety of ways to use it:
|
41
14
|
|
42
|
-
### Rack middleware
|
43
|
-
# (config.ru)
|
44
|
-
use Rack::MogileFS, :path => %r{^/assets/*}
|
45
|
-
|
46
15
|
### Rails 3:
|
47
16
|
|
48
17
|
# (config/routes.rb)
|
@@ -61,6 +30,10 @@ There are a variety of ways to use it:
|
|
61
30
|
end
|
62
31
|
end
|
63
32
|
|
33
|
+
### Rack middleware
|
34
|
+
# (config.ru)
|
35
|
+
use Rack::MogileFS, :path => %r{^/assets/*}
|
36
|
+
|
64
37
|
## File Lookup
|
65
38
|
|
66
39
|
`Rack::MogileFS` uses the request path (`PATH_INFO`) for the MogileFS key. The
|
@@ -100,3 +73,35 @@ and initialize a MogileFS client like this:
|
|
100
73
|
You can override this by passing in a MogileFS client of your own:
|
101
74
|
|
102
75
|
Rack::MogileFS::Endpoint.new :client => MyMogileFSClient.new
|
76
|
+
|
77
|
+
## Caveats ( serving files vs reproxying )
|
78
|
+
|
79
|
+
Serving files through Ruby can be slow. `Rack::MogileFS` will read the entire
|
80
|
+
file into memory before sending it downstream. If you have varnish/squid/a CDN
|
81
|
+
sitting in front of rails then this isn't so problematic.
|
82
|
+
|
83
|
+
The preferred method is to set an X-Reproxy-Url header from your app and let
|
84
|
+
the web server serve the file instead of `Rack::MogileFS`. For Nginx, you
|
85
|
+
could have a config like this:
|
86
|
+
|
87
|
+
location /reproxy {
|
88
|
+
internal;
|
89
|
+
set $reproxy $upstream_http_x_reproxy_url;
|
90
|
+
proxy_pass $reproxy;
|
91
|
+
proxy_hide_header Content-Type;
|
92
|
+
}
|
93
|
+
|
94
|
+
For Apache, there is [mod_reproxy](http://github.com/jamis/mod_reproxy)
|
95
|
+
|
96
|
+
`Rack::MogileFS` will use this method if you pass a strategy option of `:reproxy`
|
97
|
+
|
98
|
+
use Rack::MogileFS, :strategy => :reproxy
|
99
|
+
|
100
|
+
`Rack::MogileFS` will look up the internal urls for the file, and set two
|
101
|
+
headers to reproxy the request:
|
102
|
+
|
103
|
+
X-Accel-Redirect: /reproxy
|
104
|
+
X-Reproxy-Url: http://internal.ip/path/to/mogile/file.fid
|
105
|
+
|
106
|
+
You'll have to make sure your web server knows how to handle this request.
|
107
|
+
|
data/Rakefile
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
1
4
|
require 'rake/clean'
|
2
5
|
require 'rake/testtask'
|
3
6
|
|
@@ -17,4 +20,4 @@ task :coverage do
|
|
17
20
|
rm_f "coverage.data"
|
18
21
|
system "rcov -x /Users -Ilib:test test/*_test.rb"
|
19
22
|
system "open coverage/index.html" if PLATFORM['darwin']
|
20
|
-
end
|
23
|
+
end
|
data/lib/rack/mogilefs.rb
CHANGED
@@ -1,82 +1,40 @@
|
|
1
|
+
require 'rack/mogilefs/endpoint/base'
|
2
|
+
require 'rack/mogilefs/endpoint/caching'
|
3
|
+
require 'rack/mogilefs/endpoint/client'
|
4
|
+
require 'rack/mogilefs/endpoint/mapper'
|
5
|
+
require 'rack/mogilefs/endpoint/reproxy'
|
6
|
+
require 'rack/mogilefs/endpoint/rescues'
|
7
|
+
|
1
8
|
module Rack
|
2
9
|
class MogileFS
|
3
10
|
class Endpoint
|
4
11
|
|
5
|
-
|
6
|
-
|
7
|
-
:client => nil,
|
8
|
-
:mapper => nil,
|
9
|
-
:strategy => :serve,
|
10
|
-
:default_content_type => "image/png"
|
11
|
-
}.merge(options)
|
12
|
-
|
13
|
-
@options[:client] ||= default_client
|
14
|
-
end
|
15
|
-
|
16
|
-
def call(env)
|
17
|
-
path = key_for_path(env['PATH_INFO'].dup)
|
12
|
+
class File
|
13
|
+
attr_accessor :path, :data
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
else
|
22
|
-
serve_file(path)
|
15
|
+
def initialize(path, data)
|
16
|
+
@path, @data = path, data
|
23
17
|
end
|
24
18
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
[ 503, { "Content-Type" => "text/html" }, [e.message] ]
|
29
|
-
rescue ::MogileFS::Error => e
|
30
|
-
[ 500, { "Content-Type" => "text/html" }, [e.message] ]
|
31
|
-
end
|
32
|
-
|
33
|
-
protected
|
34
|
-
|
35
|
-
def reproxy(path)
|
36
|
-
paths = client.get_paths(path)
|
37
|
-
|
38
|
-
[ 200, {
|
39
|
-
"Content-Type" => content_type(path),
|
40
|
-
"X-Accel-Redirect" => "/reproxy",
|
41
|
-
"X-Reproxy-Url" => paths.join(" ")
|
42
|
-
}, [] ]
|
43
|
-
end
|
44
|
-
|
45
|
-
def serve_file(path)
|
46
|
-
data = client.get_file_data(path)
|
47
|
-
size = Utils.bytesize(data).to_s
|
48
|
-
|
49
|
-
[ 200, {
|
50
|
-
"Content-Type" => content_type(path),
|
51
|
-
"Content-Length" => size
|
52
|
-
}, [data] ]
|
53
|
-
end
|
54
|
-
|
55
|
-
def key_for_path(path)
|
56
|
-
@options[:mapper].respond_to?(:call) ? @options[:mapper].call(path) : path
|
57
|
-
end
|
58
|
-
|
59
|
-
def content_type(path)
|
60
|
-
Mime.mime_type(::File.extname(path), @options[:default_content_type])
|
61
|
-
end
|
62
|
-
|
63
|
-
def client
|
64
|
-
@options[:client]
|
65
|
-
end
|
19
|
+
def extname
|
20
|
+
::File.extname(@path)
|
21
|
+
end
|
66
22
|
|
67
|
-
|
68
|
-
|
69
|
-
|
23
|
+
def length
|
24
|
+
Utils.bytesize(@data).to_s
|
25
|
+
end
|
70
26
|
|
71
|
-
|
72
|
-
|
73
|
-
yml = YAML.load_file( Rails.root.join("config/mogilefs.yml") )
|
74
|
-
yml[Rails.env]["connection"].symbolize_keys
|
75
|
-
else
|
76
|
-
{ :domain => "default", :hosts => ["127.0.0.1:7001"] }
|
27
|
+
def content_type(default=nil)
|
28
|
+
Mime.mime_type(extname, default)
|
77
29
|
end
|
78
30
|
end
|
79
31
|
|
32
|
+
include Base
|
33
|
+
include Client
|
34
|
+
include Caching
|
35
|
+
include Mapper
|
36
|
+
include Reproxy
|
37
|
+
include Rescues
|
80
38
|
end
|
81
39
|
end
|
82
40
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Rack
|
2
|
+
class MogileFS
|
3
|
+
class Endpoint
|
4
|
+
|
5
|
+
# This contains the base functionality for serving a MogileFS file. Most
|
6
|
+
# of the useful stuff is layered on top the base class in other modules
|
7
|
+
module Base
|
8
|
+
def initialize(options={})
|
9
|
+
@options = {
|
10
|
+
:default_content_type => "image/png"
|
11
|
+
}.merge(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
path = key_for_path( env['PATH_INFO'].dup )
|
16
|
+
serve_file(path)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def serve_file(path)
|
22
|
+
data = client.get_file_data(path)
|
23
|
+
file = File.new(path, data)
|
24
|
+
|
25
|
+
[ 200, headers(file), [data] ]
|
26
|
+
end
|
27
|
+
|
28
|
+
def client
|
29
|
+
@options[:client]
|
30
|
+
end
|
31
|
+
|
32
|
+
def key_for_path(path)
|
33
|
+
path
|
34
|
+
end
|
35
|
+
|
36
|
+
def headers(file)
|
37
|
+
{
|
38
|
+
"Content-Type" => file.content_type(@options[:default_content_type]),
|
39
|
+
"Content-Length" => file.length
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rack
|
2
|
+
class MogileFS
|
3
|
+
class Endpoint
|
4
|
+
|
5
|
+
# Adds support for expires headers. You can specify a number or a proc
|
6
|
+
# that will recieve (path, ext, mime) as arguements. You should return
|
7
|
+
# the number of seconds to cache.
|
8
|
+
module Caching
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
@options[:expires] ||= false
|
12
|
+
end
|
13
|
+
|
14
|
+
def headers(file)
|
15
|
+
super.merge( cache_control_header(file) )
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def cache_control_header(file)
|
21
|
+
if @options[:expires]
|
22
|
+
{ "Cache-Control" => "max-age=#{max_age(file)}, public" }
|
23
|
+
else
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def max_age(file)
|
29
|
+
if @options[:expires].respond_to?(:call)
|
30
|
+
@options[:expires].call(file.path, file.extname, file.content_type)
|
31
|
+
else
|
32
|
+
@options[:expires]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rack
|
2
|
+
class MogileFS
|
3
|
+
class Endpoint
|
4
|
+
|
5
|
+
# Provides a default client if one is not passed in a a param. It is
|
6
|
+
# recommended to use the default client if you can
|
7
|
+
module Client
|
8
|
+
def initialize(*)
|
9
|
+
super
|
10
|
+
@options[:client] ||= default_client
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_client
|
14
|
+
::MogileFS::MogileFS.new(config)
|
15
|
+
end
|
16
|
+
|
17
|
+
# If `Rack::MogileFS` detects it is inside a Rails app, it will look
|
18
|
+
# for a yaml config in `config/mogilefs.yml` that looks like this:
|
19
|
+
#
|
20
|
+
# development:
|
21
|
+
# connection:
|
22
|
+
# domain: "development.myapp.com"
|
23
|
+
# hosts:
|
24
|
+
# - 127.0.0.1:7001
|
25
|
+
# - 127.0.0.1:7001
|
26
|
+
# class: "file"
|
27
|
+
# staging:
|
28
|
+
# ...
|
29
|
+
def config
|
30
|
+
if defined?(Rails)
|
31
|
+
yml = YAML.load_file( Rails.root.join("config/mogilefs.yml") )
|
32
|
+
yml[Rails.env]["connection"].symbolize_keys
|
33
|
+
else
|
34
|
+
{ :domain => "default", :hosts => ["127.0.0.1:7001"] }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rack
|
2
|
+
class MogileFS
|
3
|
+
class Endpoint
|
4
|
+
|
5
|
+
# Adds ability to pass in a custom mapper to map PATH_INFO to a
|
6
|
+
# MogileFS key. By default it is assumed that the path is the same as
|
7
|
+
# the key. For example your keys will look like this:
|
8
|
+
#
|
9
|
+
# "/assets/images/myimage.gif"
|
10
|
+
#
|
11
|
+
# Create a custom mapper like this:
|
12
|
+
#
|
13
|
+
# Rack::MogileFS::Endpoint.new(
|
14
|
+
# :mapper => lambda { |path| "/namespace/" + path }
|
15
|
+
# )
|
16
|
+
module Mapper
|
17
|
+
def key_for_path(path)
|
18
|
+
@options[:mapper].respond_to?(:call) ?
|
19
|
+
@options[:mapper].call(path) : super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rack
|
2
|
+
class MogileFS
|
3
|
+
class Endpoint
|
4
|
+
|
5
|
+
# Adds reproxy support. To activate:
|
6
|
+
#
|
7
|
+
# Rack::MogileFS::Endpoint.new :strategy => :reproxy
|
8
|
+
module Reproxy
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
@options[:strategy] ||= :serve
|
12
|
+
end
|
13
|
+
|
14
|
+
def serve_file(path)
|
15
|
+
if @options[:strategy] == :reproxy
|
16
|
+
reproxy(path)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def reproxy(path)
|
23
|
+
paths = client.get_paths(path)
|
24
|
+
file = File.new(path, nil)
|
25
|
+
|
26
|
+
[ 200, {
|
27
|
+
"Content-Type" => file.content_type,
|
28
|
+
"X-Accel-Redirect" => "/reproxy",
|
29
|
+
"X-Reproxy-Url" => paths.join(" ")
|
30
|
+
}, [] ]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rack
|
2
|
+
class MogileFS
|
3
|
+
class Endpoint
|
4
|
+
|
5
|
+
# Catches some potential MogileFS exceptions and will return sensible
|
6
|
+
# HTTP status codes. You can disable with:
|
7
|
+
#
|
8
|
+
# Rack::MogileFS::Endpoint.new :debug => true
|
9
|
+
module Rescues
|
10
|
+
def initialize(*)
|
11
|
+
super
|
12
|
+
@options[:debug] ||= false
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
if @options[:debug]
|
17
|
+
super
|
18
|
+
else
|
19
|
+
with_rescues { super }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_rescues
|
24
|
+
yield
|
25
|
+
rescue ::MogileFS::Backend::UnknownKeyError => e
|
26
|
+
[ 404, { "Content-Type" => "text/html" }, [e.message] ]
|
27
|
+
rescue ::MogileFS::UnreachableBackendError => e
|
28
|
+
[ 503, { "Content-Type" => "text/html" }, [e.message] ]
|
29
|
+
rescue ::MogileFS::Error => e
|
30
|
+
[ 500, { "Content-Type" => "text/html" }, [e.message] ]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rack/mogilefs/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rack-mogilefs"
|
7
|
+
s.version = Rack::MogileFS::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
|
10
|
+
s.date = "2010-09-10"
|
11
|
+
s.summary = "A rack middleware and/or endpoint to serve up files from MogileFS"
|
12
|
+
s.email = "bmarini@gmail.com"
|
13
|
+
s.homepage = "http://github.com/bmarini/rack-mogilefs"
|
14
|
+
s.description = "A rack middleware and/or endpoint to serve up files from MogileFS"
|
15
|
+
s.authors = ["Ben Marini"]
|
16
|
+
|
17
|
+
s.rubyforge_project = "rack-mogilefs"
|
18
|
+
|
19
|
+
s.add_dependency "mogilefs-client", "~> 2.1.0"
|
20
|
+
s.add_dependency "rack", "~> 1.1.0"
|
21
|
+
s.add_development_dependency "mocha"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
data/release.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestCaching < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@client = MockMogileFsClient.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_expires_with_int
|
9
|
+
@client.expects(:get_file_data).with("/assets/image.png").returns("")
|
10
|
+
|
11
|
+
app_with(
|
12
|
+
:path => %r{^/assets/*},
|
13
|
+
:client => @client,
|
14
|
+
:expires => 300
|
15
|
+
)
|
16
|
+
|
17
|
+
get '/assets/image.png'
|
18
|
+
assert_status 200
|
19
|
+
assert_cache_control "max-age=300, public"
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_expires_with_lambda
|
23
|
+
@client.expects(:get_file_data).with("/assets/image.jpg").returns("")
|
24
|
+
|
25
|
+
app_with(
|
26
|
+
:path => %r{^/assets/*},
|
27
|
+
:client => @client,
|
28
|
+
:expires => lambda { |path, ext, mime|
|
29
|
+
mime == "image/jpeg" ? 600 : 300
|
30
|
+
}
|
31
|
+
)
|
32
|
+
|
33
|
+
get '/assets/image.jpg'
|
34
|
+
assert_status 200
|
35
|
+
assert_cache_control "max-age=600, public"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestContentType < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@client = MockMogileFsClient.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_content_type_lookup
|
9
|
+
app_with :path => %r{^/assets/*}, :client => @client
|
10
|
+
get '/assets/asset.txt'
|
11
|
+
|
12
|
+
assert_status 200
|
13
|
+
assert_content_type "text/plain"
|
14
|
+
|
15
|
+
get '/assets/asset.png'
|
16
|
+
|
17
|
+
assert_status 200
|
18
|
+
assert_content_type "image/png"
|
19
|
+
|
20
|
+
get '/assets/asset.xml'
|
21
|
+
|
22
|
+
assert_status 200
|
23
|
+
assert_content_type "application/xml"
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_default_content_type
|
27
|
+
app_with :path => %r{^/assets/*}, :client => @client
|
28
|
+
get '/assets/asset.xxx'
|
29
|
+
|
30
|
+
assert_status 200
|
31
|
+
assert_content_type "image/png"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/test/mapper_test.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestMapper < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@client = MockMogileFsClient.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_custom_key_mapping
|
9
|
+
@client.expects(:get_file_data).with("image.png").returns("")
|
10
|
+
app_with(
|
11
|
+
:path => %r{^/assets/*},
|
12
|
+
:client => @client,
|
13
|
+
:mapper => lambda { |p| p.sub('/assets/', '') }
|
14
|
+
)
|
15
|
+
|
16
|
+
get '/assets/image.png'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/test/mogilefs_test.rb
CHANGED
@@ -12,32 +12,6 @@ class TestMiddleWare < Test::Unit::TestCase
|
|
12
12
|
assert_body "Hello, World!"
|
13
13
|
end
|
14
14
|
|
15
|
-
def test_unreachable_exception
|
16
|
-
app_with :path => %r{^/assets/*}
|
17
|
-
get '/assets/unreachable.txt'
|
18
|
-
|
19
|
-
assert_status 503
|
20
|
-
assert_body "couldn't connect to mogilefsd backend"
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_unknown_key_exception
|
24
|
-
@client.expects(:get_file_data).raises(MogileFS::Backend::UnknownKeyError)
|
25
|
-
|
26
|
-
app_with :path => %r{^/assets/*}, :client => @client
|
27
|
-
get '/assets/unknown.txt'
|
28
|
-
|
29
|
-
assert_status 404
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_mogilefs_exception
|
33
|
-
@client.expects(:get_file_data).raises(MogileFS::Error)
|
34
|
-
|
35
|
-
app_with :path => %r{^/assets/*}, :client => @client
|
36
|
-
get '/assets/error.txt'
|
37
|
-
|
38
|
-
assert_status 500
|
39
|
-
end
|
40
|
-
|
41
15
|
def test_middleware_with_mock_mogile_client
|
42
16
|
app_with :path => %r{^/assets/*}, :client => @client
|
43
17
|
get '/assets/asset.txt'
|
@@ -45,41 +19,4 @@ class TestMiddleWare < Test::Unit::TestCase
|
|
45
19
|
assert_body "Mock Data for /assets/asset.txt"
|
46
20
|
end
|
47
21
|
|
48
|
-
def test_content_type_lookup
|
49
|
-
app_with :path => %r{^/assets/*}, :client => @client
|
50
|
-
get '/assets/asset.txt'
|
51
|
-
|
52
|
-
assert_status 200
|
53
|
-
assert_content_type "text/plain"
|
54
|
-
|
55
|
-
get '/assets/asset.png'
|
56
|
-
|
57
|
-
assert_status 200
|
58
|
-
assert_content_type "image/png"
|
59
|
-
|
60
|
-
get '/assets/asset.xml'
|
61
|
-
|
62
|
-
assert_status 200
|
63
|
-
assert_content_type "application/xml"
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_default_content_type
|
67
|
-
app_with :path => %r{^/assets/*}, :client => @client
|
68
|
-
get '/assets/asset.xxx'
|
69
|
-
|
70
|
-
assert_status 200
|
71
|
-
assert_content_type "image/png"
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_custom_key_mapping
|
75
|
-
@client.expects(:get_file_data).with("image.png").returns("")
|
76
|
-
app_with(
|
77
|
-
:path => %r{^/assets/*},
|
78
|
-
:client => @client,
|
79
|
-
:mapper => lambda { |p| p.sub('/assets/', '') }
|
80
|
-
)
|
81
|
-
|
82
|
-
get '/assets/image.png'
|
83
|
-
end
|
84
|
-
|
85
22
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestReproxy < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@client = MockMogileFsClient.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_reproxy
|
9
|
+
@client.expects(:get_paths).with("/assets/image.png").returns( %w(/path/1.png /path/2.png) )
|
10
|
+
|
11
|
+
app_with(
|
12
|
+
:path => %r{^/assets/*},
|
13
|
+
:client => @client,
|
14
|
+
:strategy => :reproxy
|
15
|
+
)
|
16
|
+
|
17
|
+
get '/assets/image.png'
|
18
|
+
assert_status 200
|
19
|
+
assert_content_type "image/png"
|
20
|
+
assert_equal_header "/reproxy", "X-Accel-Redirect"
|
21
|
+
assert_equal_header "/path/1.png /path/2.png", "X-Reproxy-Url"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestRescues < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@client = MockMogileFsClient.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_debug_mode
|
9
|
+
app_with :path => %r{^/assets/*}, :debug => true
|
10
|
+
assert_raises(MogileFS::UnreachableBackendError) do
|
11
|
+
get '/assets/unreachable.txt'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_unreachable_exception
|
16
|
+
app_with :path => %r{^/assets/*}
|
17
|
+
get '/assets/unreachable.txt'
|
18
|
+
|
19
|
+
assert_status 503
|
20
|
+
assert_body "couldn't connect to mogilefsd backend"
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_unknown_key_exception
|
24
|
+
@client.expects(:get_file_data).raises(MogileFS::Backend::UnknownKeyError)
|
25
|
+
|
26
|
+
app_with :path => %r{^/assets/*}, :client => @client
|
27
|
+
get '/assets/unknown.txt'
|
28
|
+
|
29
|
+
assert_status 404
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_mogilefs_exception
|
33
|
+
@client.expects(:get_file_data).raises(MogileFS::Error)
|
34
|
+
|
35
|
+
app_with :path => %r{^/assets/*}, :client => @client
|
36
|
+
get '/assets/error.txt'
|
37
|
+
|
38
|
+
assert_status 500
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
|
2
4
|
require "test/unit"
|
3
5
|
require "rack"
|
4
6
|
require "rack/mock"
|
@@ -34,6 +36,14 @@ class Test::Unit::TestCase
|
|
34
36
|
end
|
35
37
|
|
36
38
|
def assert_content_type(content_type)
|
37
|
-
|
39
|
+
assert_equal_header content_type, "Content-Type"
|
40
|
+
end
|
41
|
+
|
42
|
+
def assert_cache_control(cache_control)
|
43
|
+
assert_equal_header cache_control, "Cache-Control"
|
44
|
+
end
|
45
|
+
|
46
|
+
def assert_equal_header(expected, header)
|
47
|
+
assert_equal expected, @response.headers[header]
|
38
48
|
end
|
39
49
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-mogilefs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ben Marini
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
hash: 19
|
46
46
|
segments:
|
@@ -51,7 +51,7 @@ dependencies:
|
|
51
51
|
type: :runtime
|
52
52
|
version_requirements: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
54
|
+
name: mocha
|
55
55
|
prerelease: false
|
56
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
@@ -64,20 +64,6 @@ dependencies:
|
|
64
64
|
version: "0"
|
65
65
|
type: :development
|
66
66
|
version_requirements: *id003
|
67
|
-
- !ruby/object:Gem::Dependency
|
68
|
-
name: mocha
|
69
|
-
prerelease: false
|
70
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
hash: 3
|
76
|
-
segments:
|
77
|
-
- 0
|
78
|
-
version: "0"
|
79
|
-
type: :development
|
80
|
-
version_requirements: *id004
|
81
67
|
description: A rack middleware and/or endpoint to serve up files from MogileFS
|
82
68
|
email: bmarini@gmail.com
|
83
69
|
executables: []
|
@@ -87,13 +73,30 @@ extensions: []
|
|
87
73
|
extra_rdoc_files: []
|
88
74
|
|
89
75
|
files:
|
90
|
-
-
|
91
|
-
-
|
92
|
-
-
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- Gemfile.lock
|
79
|
+
- HISTORY.md
|
93
80
|
- README.md
|
94
81
|
- Rakefile
|
95
|
-
-
|
82
|
+
- lib/rack-mogilefs.rb
|
83
|
+
- lib/rack/mogilefs.rb
|
84
|
+
- lib/rack/mogilefs/endpoint.rb
|
85
|
+
- lib/rack/mogilefs/endpoint/base.rb
|
86
|
+
- lib/rack/mogilefs/endpoint/caching.rb
|
87
|
+
- lib/rack/mogilefs/endpoint/client.rb
|
88
|
+
- lib/rack/mogilefs/endpoint/mapper.rb
|
89
|
+
- lib/rack/mogilefs/endpoint/reproxy.rb
|
90
|
+
- lib/rack/mogilefs/endpoint/rescues.rb
|
91
|
+
- lib/rack/mogilefs/version.rb
|
92
|
+
- rack-mogilefs.gemspec
|
93
|
+
- release.rb
|
94
|
+
- test/caching_test.rb
|
95
|
+
- test/content_type_test.rb
|
96
|
+
- test/mapper_test.rb
|
96
97
|
- test/mogilefs_test.rb
|
98
|
+
- test/reproxy_test.rb
|
99
|
+
- test/rescues_test.rb
|
97
100
|
- test/test_helper.rb
|
98
101
|
has_rdoc: true
|
99
102
|
homepage: http://github.com/bmarini/rack-mogilefs
|
@@ -124,11 +127,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
127
|
version: "0"
|
125
128
|
requirements: []
|
126
129
|
|
127
|
-
rubyforge_project:
|
130
|
+
rubyforge_project: rack-mogilefs
|
128
131
|
rubygems_version: 1.3.7
|
129
132
|
signing_key:
|
130
133
|
specification_version: 3
|
131
134
|
summary: A rack middleware and/or endpoint to serve up files from MogileFS
|
132
135
|
test_files:
|
136
|
+
- test/caching_test.rb
|
137
|
+
- test/content_type_test.rb
|
138
|
+
- test/mapper_test.rb
|
133
139
|
- test/mogilefs_test.rb
|
140
|
+
- test/reproxy_test.rb
|
141
|
+
- test/rescues_test.rb
|
134
142
|
- test/test_helper.rb
|