diff options
author | Alex Rakoczy, Matthew Horan & Ryan Ong <pair+arakoczy+mhoran+rong@pivotallabs.com> | 2012-11-07 15:33:50 -0500 |
---|---|---|
committer | Alex Rakoczy, Matthew Horan & Ryan Ong <pair+arakoczy+mhoran+rong@pivotallabs.com> | 2012-11-07 15:33:50 -0500 |
commit | 518dc80ea5cfb94c79dfb316a781d6aea74ea79a (patch) | |
tree | 51490bfa2441bed94fe4fe8dbaab88ef98aaaadf | |
parent | 1824547e8dfa8c2b553a913a6ad0935dd6ff7d12 (diff) | |
download | rack-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.rb | 13 | ||||
-rw-r--r-- | test/spec_sendfile.rb | 52 |
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 |