Permalink
Browse files

Introduces #unsafe_send_file (#216)

* Introduces #unsafe_send_file

- We still provide send_file as a safe alternative, only sending files
located on the public directory
- `#unsafe_send_file` allows the user to send a file from anywhere while
reminding him that this might be risky.

- Fixes #210 and #211

* remove debug statement

* small documentation fix
  • Loading branch information...
mereghost authored and jodosha committed Feb 27, 2017
1 parent d51b4e8 commit 7cb2a87ff2cb10512114722eb2b78e7e40da250d
Showing with 50 additions and 2 deletions.
  1. +27 −0 lib/hanami/action/rack.rb
  2. +8 −0 test/fixtures.rb
  3. +15 −2 test/integration/send_file_test.rb
@@ -257,6 +257,7 @@ def body=(body)
end

# Send a file as response.
# <tt>This method only sends files from the public directory</tt>
#
# It automatically handle the following cases:
#
@@ -287,6 +288,32 @@ def send_file(path)
halt result[0], result[2]
end

# Send a file as response from anywhere in the file system.
#
# @see Hanami::Action::Rack#send_file
#
# @param path [String, Pathname] path to the file to be sent
# @return [void]
#
# @since x.x.x
#
# @example
# require 'hanami/controller'
#
# class Show
# include Hanami::Action
#
# def call(params)
# # ...
# unsafe_send_file Pathname.new('/tmp/path/to/file')
# end
# end
def unsafe_send_file(path)
result = File.new(path, Pathname.new(path).dirname).call(@_env)
headers.merge!(result[1])
halt result[0], result[2]
end

# Check if the current request is a HEAD
#
# @return [TrueClass,FalseClass] the result of the check
@@ -1120,6 +1120,14 @@ def call(params)
end
end

class Unsafe
include SendFileTest::Action

def call(params)
unsafe_send_file Pathname.new('Gemfile')
end
end

class Flow
include SendFileTest::Action

@@ -2,8 +2,9 @@
require 'rack/test'

SendFileRoutes = Hanami::Router.new(namespace: SendFileTest) do
get '/files/flow', to: 'files#flow'
get '/files/:id', to: 'files#show'
get '/files/flow', to: 'files#flow'
get '/files/:id(.:format)', to: 'files#show'
get '/files/unsafe', to: 'files#unsafe'
end

SendFileApplication = Rack::Builder.new do
@@ -17,6 +18,18 @@ def app
SendFileApplication
end

describe 'send files from anywhere in the system' do
it 'responds 200 when the file exists' do
get '/files/unsafe', {}
file = Pathname.new('Gemfile')

last_response.status.must_equal 200
last_response.headers['Content-Length'].to_i.must_equal file.size
last_response.headers['Content-Type'].must_equal 'text/plain'
last_response.body.size.must_equal(file.size)
end
end

describe 'when file exists, app responds 200' do
it 'sets Content-Type according to file type' do
get '/files/1', {}

0 comments on commit 7cb2a87

Please sign in to comment.