Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

unbreak send_file compat specs; add media_type helper

  • Loading branch information...
commit 1c124f5d44de24d2122fd7c2c914f1efbb3f658a 1 parent ed923ca
@rtomayko rtomayko authored
View
2  compat/streaming_test.rb
@@ -105,7 +105,7 @@
end
# Deprecated. The Content-Disposition is no longer handled by sendfile.
- xspecify "should include a Content-Disposition header" do
+ specify "should include a Content-Disposition header" do
get '/' do
send_file File.dirname(__FILE__) + '/public/foo.xml'
end
View
56 lib/sinatra/base.rb
@@ -61,43 +61,45 @@ def session
env['rack.session'] ||= {}
end
- # Set the content type of the response body (HTTP 'Content-Type' header).
- #
- # The +type+ argument may be a media type (e.g., 'text/html',
- # 'application/xml+atom', 'image/png') or a Symbol key into the
- # Rack::File::MIME_TYPES table.
- #
- # Media type parameters, such as "charset", may also be specified using the
- # optional hash argument:
- # get '/foo.html' do
- # content_type 'text/html', :charset => 'utf-8'
- # "<h1>Hello World</h1>"
- # end
+ # Look up a media type by file extension in Rack's mime registry.
+ def media_type(type)
+ return type if type.nil? || type.to_s.include?('/')
+ Rack::File::MIME_TYPES[type.to_s.sub(/^\./, '')]
+ end
+
+ # Set the Content-Type of the response body given a media type or file
+ # extension.
def content_type(type, params={})
- mediatype =
- if type.kind_of?(Symbol)
- Rack::File::MIME_TYPES[type.to_s]
- else
- type
- end
- fail "Invalid or undefined media type: #{type.inspect}" if mediatype.nil?
+ media_type = self.media_type(type)
+ fail "Unknown media type: %p" % type if media_type.nil?
if params.any?
params = params.collect { |kv| "%s=%s" % kv }.join(', ')
- response['Content-Type'] = [mediatype, params].join(";")
+ response['Content-Type'] = [media_type, params].join(";")
else
- response['Content-Type'] = mediatype
+ response['Content-Type'] = media_type
+ end
+ end
+
+ # Set the Content-Disposition to "attachment" with the specified filename,
+ # instructing the user agents to prompt to save.
+ def attachment(filename=nil)
+ response['Content-Disposition'] = 'attachment'
+ if filename
+ params = '; filename="%s"' % File.basename(filename)
+ response['Content-Disposition'] << params
end
end
- def send_file(path)
+ # Use the contents of the file as the response body and attempt to
+ def send_file(path, opts={})
stat = File.stat(path)
last_modified stat.mtime
- response['Content-Length'] ||= stat.size.to_s
- response['Content-Type'] =
- Rack::File::MIME_TYPES[File.extname(path)[1..-1]] ||
+ content_type media_type(opts[:type]) ||
+ media_type(File.extname(path)) ||
response['Content-Type'] ||
'application/octet-stream'
- throw :halt, StaticFile.open(path, 'rb')
+ response['Content-Length'] ||= (opts[:length] || stat.size).to_s
+ halt StaticFile.open(path, 'rb')
rescue Errno::ENOENT
not_found
end
@@ -614,7 +616,7 @@ def metadef(message, &block)
pass unless options.static? && options.public?
path = options.public + unescape(request.path_info)
pass unless File.file?(path)
- send_file path
+ send_file path, :disposition => nil
end
error ::Exception do
View
9 lib/sinatra/compat.rb
@@ -41,6 +41,15 @@ def headers(header=nil)
# Deprecated. Use: etag
alias :entity_tag :etag
+ # The :disposition option is deprecated; use: #attachment. This method
+ # setting the Content-Transfer-Encoding header is deprecated.
+ def send_file(path, opts={})
+ opts[:disposition] = 'attachment' if !opts.key?(:disposition)
+ attachment opts[:filename] || path if opts[:filename] || opts[:disposition]
+ response['Content-Transfer-Encoding'] = 'binary' if opts[:disposition]
+ super(path, opts)
+ end
+
def options ; self.class.options ; end
class << self
View
30 test/helpers_test.rb
@@ -159,6 +159,25 @@ class Test::Unit::TestCase
end
end
+ describe '#media_type' do
+ include Sinatra::Helpers
+ it "looks up media types in Rack's MIME registry" do
+ Rack::File::MIME_TYPES['foo'] = 'application/foo'
+ media_type('foo').should.equal 'application/foo'
+ media_type('.foo').should.equal 'application/foo'
+ media_type(:foo).should.equal 'application/foo'
+ end
+ it 'returns nil when given nil' do
+ media_type(nil).should.be.nil
+ end
+ it 'returns nil when media type not registered' do
+ media_type(:bizzle).should.be.nil
+ end
+ it 'returns the argument when given a media type string' do
+ media_type('text/plain').should.equal 'text/plain'
+ end
+ end
+
describe '#content_type' do
it 'sets the Content-Type header' do
mock_app {
@@ -201,6 +220,17 @@ class Test::Unit::TestCase
response['Content-Type'].should.equal 'application/foo'
body.should.equal 'I AM FOO'
end
+
+ it 'fails when no mime type is registered for the argument provided' do
+ mock_app {
+ get '/foo.xml' do
+ content_type :bizzle
+ "I AM FOO"
+ end
+ }
+
+ lambda { get '/foo.xml' }.should.raise RuntimeError
+ end
end
describe '#send_file' do
Please sign in to comment.
Something went wrong with that request. Please try again.