Add support for parameters when creating mime types (#1256)
This commit is contained in:
parent
aee28a1bda
commit
574e5a9e3d
|
@ -43,12 +43,11 @@ module Sinatra
|
|||
end
|
||||
|
||||
def preferred_type(*types)
|
||||
accepts = accept # just evaluate once
|
||||
return accepts.first if types.empty?
|
||||
return accept.first if types.empty?
|
||||
types.flatten!
|
||||
return types.first if accepts.empty?
|
||||
accepts.detect do |pattern|
|
||||
type = types.detect { |t| File.fnmatch(pattern, t) }
|
||||
return types.first if accept.empty?
|
||||
accept.detect do |accept_header|
|
||||
type = types.detect { |t| MimeTypeEntry.new(t).accepts?(accept_header) }
|
||||
return type if type
|
||||
end
|
||||
end
|
||||
|
@ -125,6 +124,35 @@ module Sinatra
|
|||
to_str.send(*args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
class MimeTypeEntry
|
||||
attr_reader :params
|
||||
|
||||
def initialize(entry)
|
||||
params = entry.scan(HEADER_PARAM).map! do |s|
|
||||
key, value = s.strip.split('=', 2)
|
||||
value = value[1..-2].gsub(/\\(.)/, '\1') if value.start_with?('"')
|
||||
[key, value]
|
||||
end
|
||||
|
||||
@type = entry[/[^;]+/].delete(' ')
|
||||
@params = Hash[params]
|
||||
end
|
||||
|
||||
def accepts?(entry)
|
||||
File.fnmatch(entry, self) && matches_params?(entry.params)
|
||||
end
|
||||
|
||||
def to_str
|
||||
@type
|
||||
end
|
||||
|
||||
def matches_params?(params)
|
||||
return true if @params.empty?
|
||||
|
||||
params.all? { |k,v| !@params.has_key?(k) || @params[k] == v }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# The response object. See Rack::Response and Rack::Response::Helpers for
|
||||
|
|
|
@ -102,4 +102,24 @@ class RequestTest < Minitest::Test
|
|||
request = Sinatra::Request.new 'HTTP_ACCEPT' => 'application/json'
|
||||
assert !request.accept?('text/html')
|
||||
end
|
||||
|
||||
it 'will accept types that fulfill HTTP_ACCEPT parameters' do
|
||||
request = Sinatra::Request.new 'HTTP_ACCEPT' => 'application/rss+xml; version="http://purl.org/rss/1.0/"'
|
||||
|
||||
assert request.accept?('application/rss+xml; version="http://purl.org/rss/1.0/"')
|
||||
assert request.accept?('application/rss+xml; version="http://purl.org/rss/1.0/"; charset=utf-8')
|
||||
assert !request.accept?('application/rss+xml; version="https://cyber.harvard.edu/rss/rss.html"')
|
||||
end
|
||||
|
||||
it 'will accept more generic types that include HTTP_ACCEPT parameters' do
|
||||
request = Sinatra::Request.new 'HTTP_ACCEPT' => 'application/rss+xml; charset=utf-8; version="http://purl.org/rss/1.0/"'
|
||||
|
||||
assert request.accept?('application/rss+xml')
|
||||
assert request.accept?('application/rss+xml; version="http://purl.org/rss/1.0/"')
|
||||
end
|
||||
|
||||
it 'will accept types matching HTTP_ACCEPT when parameters in arbitrary order' do
|
||||
request = Sinatra::Request.new 'HTTP_ACCEPT' => 'application/rss+xml; charset=utf-8; version="http://purl.org/rss/1.0/"'
|
||||
assert request.accept?('application/rss+xml; version="http://purl.org/rss/1.0/"; charset=utf-8')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1347,6 +1347,29 @@ class RoutingTest < Minitest::Test
|
|||
assert_body 'text/xml;charset=utf-8'
|
||||
end
|
||||
|
||||
it 'matches content-type to mime_type' do
|
||||
mime_type = 'application/rss+xml;version="http://purl.org/rss/1.0/"'
|
||||
mock_app do
|
||||
configure { mime_type(:rss10, mime_type) }
|
||||
get('/', :provides => [:rss10]) { content_type }
|
||||
end
|
||||
|
||||
get '/', {}, { 'HTTP_ACCEPT' => 'application/rss+xml' }
|
||||
assert ok?
|
||||
assert_body mime_type
|
||||
end
|
||||
|
||||
it 'handles missing mime_types with 404' do
|
||||
mock_app do
|
||||
configure { mime_type(:rss10, 'application/rss+xml') }
|
||||
get('/', :provides => [:jpg]) { content_type }
|
||||
end
|
||||
|
||||
get '/', {}, { 'HTTP_ACCEPT' => 'application/rss+xml' }
|
||||
assert_equal 404, status
|
||||
assert_equal 'text/html;charset=utf-8', response['Content-Type']
|
||||
end
|
||||
|
||||
it 'passes a single url param as block parameters when one param is specified' do
|
||||
mock_app {
|
||||
get '/:foo' do |foo|
|
||||
|
|
Loading…
Reference in New Issue