diff --git a/lib/sinatra.rb b/lib/sinatra.rb
index 7bf29287..8be5644a 100644
--- a/lib/sinatra.rb
+++ b/lib/sinatra.rb
@@ -192,8 +192,8 @@ module Sinatra
def block
Proc.new do
- send_file Sinatra.application.options.public +
- request.path_info
+ send_file Sinatra.application.options.public + request.path_info,
+ :disposition => nil
end
end
@@ -246,7 +246,8 @@ module Sinatra
# * :type - specifies an HTTP content type.
# Defaults to 'application/octet-stream'.
# * :disposition - specifies whether the file will be shown inline or downloaded.
- # Valid values are 'inline' and 'attachment' (default).
+ # Valid values are 'inline' and 'attachment' (default). When set to nil, the
+ # Content-Disposition and Content-Transfer-Encoding headers are omitted entirely.
# * :stream - whether to send the file to the user agent as it is read (true)
# or to read the entire file before sending (false). Defaults to true.
# * :buffer_size - specifies size (in bytes) of the buffer used to stream the file.
@@ -331,9 +332,9 @@ module Sinatra
private
def send_file_headers!(options)
- options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
+ options = DEFAULT_SEND_FILE_OPTIONS.merge(options)
[:length, :type, :disposition].each do |arg|
- raise ArgumentError, ":#{arg} option required" if options[arg].nil?
+ raise ArgumentError, ":#{arg} option required" unless options.key?(arg)
end
# Send a "304 Not Modified" if the last_modified option is provided and matches
@@ -343,17 +344,19 @@ module Sinatra
throw :halt, [ 304, '' ] if last_modified == request.env['HTTP_IF_MODIFIED_SINCE']
end
- disposition = options[:disposition].dup || 'attachment'
-
- disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
-
headers(
'Content-Length' => options[:length].to_s,
- 'Content-Type' => options[:type].strip, # fixes a problem with extra '\r' with some browsers
- 'Content-Disposition' => disposition,
- 'Content-Transfer-Encoding' => 'binary'
+ 'Content-Type' => options[:type].strip # fixes a problem with extra '\r' with some browsers
)
+ # Omit Content-Disposition and Content-Transfer-Encoding headers if
+ # the :disposition option set to nil.
+ if !options[:disposition].nil?
+ disposition = options[:disposition].dup || 'attachment'
+ disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
+ headers 'Content-Disposition' => disposition, 'Content-Transfer-Encoding' => 'binary'
+ end
+
# Fix a problem with IE 6.0 on opening downloaded files:
# If Cache-Control: no-cache is set (which Rails does by default),
# IE removes the file it just downloaded from its cache immediately
diff --git a/test/streaming_test.rb b/test/streaming_test.rb
index 197ac1b5..8449b4e3 100644
--- a/test/streaming_test.rb
+++ b/test/streaming_test.rb
@@ -70,6 +70,13 @@ context "Static files (by default)" do
body.should.be.empty
end
+ specify "should omit Content-Disposition headers" do
+ get_it('/foo.xml')
+ should.be.ok
+ headers['Content-Disposition'].should.be.nil
+ headers['Content-Transfer-Encoding'].should.be.nil
+ end
+
end
context "SendData" do
@@ -89,4 +96,17 @@ context "SendData" do
body.should.equal 'asdf'
end
+ specify "should include a Content-Disposition header" do
+ get '/' do
+ send_file File.dirname(__FILE__) + '/public/foo.xml'
+ end
+
+ get_it '/'
+
+ should.be.ok
+ headers['Content-Disposition'].should.not.be.nil
+ headers['Content-Disposition'].should.equal 'attachment; filename="foo.xml"'
+ headers['Content-Transfer-Encoding'].should.equal 'binary'
+ end
+
end