Make Static omit Content-Disposition header when serving files.

send_file_headers! now accepts nil for :disposition. When nil, omit both
the Content-Disposition and Content-Transfer-Encoding headers.

Modified Static to specify a nil :disposition. I believe this is more
in line with how most web servers serve static directories by default. User
agents are free to choose whether the entity should be displayed inline or
treated as an attachment.

Note that, although files served by the Static handler omit the
Content-Disposition header by default, explicit calls to send_file and
send_data in events default to :disposition => 'attachment'.
This commit is contained in:
Ryan Tomayko 2008-03-26 12:54:14 -04:00
parent 9a5d69a87f
commit bacfa20d9f
2 changed files with 35 additions and 12 deletions

View File

@ -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
# * <tt>:type</tt> - specifies an HTTP content type.
# Defaults to 'application/octet-stream'.
# * <tt>:disposition</tt> - 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.
# * <tt>:stream</tt> - 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.
# * <tt>:buffer_size</tt> - 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

View File

@ -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