summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Rakoczy, Matthew Horan & Ryan Ong <pair+arakoczy+mhoran+rong@pivotallabs.com>2012-11-07 15:33:50 -0500
committerAlex Rakoczy, Matthew Horan & Ryan Ong <pair+arakoczy+mhoran+rong@pivotallabs.com>2012-11-07 15:33:50 -0500
commit518dc80ea5cfb94c79dfb316a781d6aea74ea79a (patch)
tree51490bfa2441bed94fe4fe8dbaab88ef98aaaadf
parent1824547e8dfa8c2b553a913a6ad0935dd6ff7d12 (diff)
downloadrack-518dc80ea5cfb94c79dfb316a781d6aea74ea79a.tar.gz
Initialize Rack::Sendfile with accel mappings
Instead of requiring the X-Accel-Mapping header to be sent by nginx, this allows separation of concerns between application and server configuration.
-rw-r--r--lib/rack/sendfile.rb13
-rw-r--r--test/spec_sendfile.rb52
2 files changed, 53 insertions, 12 deletions
diff --git a/lib/rack/sendfile.rb b/lib/rack/sendfile.rb
index c82145ae..f24892fa 100644
--- a/lib/rack/sendfile.rb
+++ b/lib/rack/sendfile.rb
@@ -93,9 +93,12 @@ module Rack
class Sendfile
F = ::File
- def initialize(app, variation=nil)
+ def initialize(app, variation=nil, mappings={})
@app = app
@variation = variation
+ @mappings = mappings.map do |internal, external|
+ [/^#{internal}/i, external]
+ end
end
def call(env)
@@ -131,10 +134,12 @@ module Rack
env['HTTP_X_SENDFILE_TYPE']
end
- def map_accel_path(env, file)
- if mapping = env['HTTP_X_ACCEL_MAPPING']
+ def map_accel_path(env, path)
+ if mapping = @mappings.detect { |internal,_| internal =~ path }
+ path.sub(*mapping)
+ elsif mapping = env['HTTP_X_ACCEL_MAPPING']
internal, external = mapping.split('=', 2).map{ |p| p.strip }
- file.sub(/^#{internal}/i, external)
+ path.sub(/^#{internal}/i, external)
end
end
end
diff --git a/test/spec_sendfile.rb b/test/spec_sendfile.rb
index bb9ad87b..5c538aba 100644
--- a/test/spec_sendfile.rb
+++ b/test/spec_sendfile.rb
@@ -21,14 +21,12 @@ describe Rack::Sendfile do
lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
end
- def sendfile_app(body=sendfile_body)
- Rack::Lint.new Rack::Sendfile.new(simple_app(body))
+ def sendfile_app(body, mappings = {})
+ Rack::Lint.new Rack::Sendfile.new(simple_app(body), nil, mappings)
end
- @request = Rack::MockRequest.new(sendfile_app)
-
- def request(headers={})
- yield @request.get('/', headers)
+ def request(headers={}, body=sendfile_body, mappings={})
+ yield Rack::MockRequest.new(sendfile_app(body, mappings)).get('/', headers)
end
it "does nothing when no X-Sendfile-Type header present" do
@@ -80,10 +78,48 @@ describe Rack::Sendfile do
end
it 'does nothing when body does not respond to #to_path' do
- @request = Rack::MockRequest.new(sendfile_app(['Not a file...']))
- request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
+ request({'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile'}, ['Not a file...']) do |response|
response.body.should.equal 'Not a file...'
response.headers.should.not.include 'X-Sendfile'
end
end
+
+ it "sets X-Accel-Redirect response header and discards body when initialized with multiple mapping" do
+ begin
+ dir1 = Dir.mktmpdir
+ dir2 = Dir.mktmpdir
+
+ first_body = ['hello world']
+ first_body.define_singleton_method(:to_path) do
+ File.expand_path(FileUtils.touch(File.join(dir1, 'rack_sendfile')).first)
+ end
+
+ second_body = ['goodbye world']
+ second_body.define_singleton_method(:to_path) do
+ File.expand_path(FileUtils.touch(File.join(dir2, 'rack_sendfile')).first)
+ end
+
+ mappings = {
+ "#{dir1}/" => '/foo/bar/',
+ "#{dir2}/" => '/wibble/'
+ }
+
+ request({'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect'}, first_body, mappings) do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['Content-Length'].should.equal '0'
+ response.headers['X-Accel-Redirect'].should.equal '/foo/bar/rack_sendfile'
+ end
+
+ request({'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect'}, second_body, mappings) do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['Content-Length'].should.equal '0'
+ response.headers['X-Accel-Redirect'].should.equal '/wibble/rack_sendfile'
+ end
+ ensure
+ FileUtils.remove_entry_secure dir1
+ FileUtils.remove_entry_secure dir2
+ end
+ end
end