Add filtering support for Accept HTTP header.
Adds an "provides"-option to a route definition, which can either be a string specifying a MIME type, a symbol that Rack can resolve to a MIME type, or an array of either.
This commit is contained in:
parent
9681803a42
commit
38778eddda
4
CHANGES
4
CHANGES
|
@ -1,5 +1,9 @@
|
|||
= 0.9.0 (unreleased)
|
||||
|
||||
* New ":provides" route condition takes an array of mime types and
|
||||
matches only when an Accept request header is present with a
|
||||
corresponding type. [cypher]
|
||||
|
||||
* Work with and require Rack >= 0.9
|
||||
|
||||
* Regular expressions may now be used in route pattens; captures are
|
||||
|
|
|
@ -10,6 +10,10 @@ module Sinatra
|
|||
def user_agent
|
||||
@env['HTTP_USER_AGENT']
|
||||
end
|
||||
|
||||
def accept
|
||||
@env['HTTP_ACCEPT'].split(',').map { |a| a.strip }
|
||||
end
|
||||
end
|
||||
|
||||
class Response < Rack::Response
|
||||
|
@ -88,9 +92,7 @@ module Sinatra
|
|||
|
||||
# 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?('/')
|
||||
type = ".#{type}" unless type.to_s[0] == ?.
|
||||
Rack::Mime.mime_type(type, nil)
|
||||
Base.media_type(type)
|
||||
end
|
||||
|
||||
# Set the Content-Type of the response body given a media type or file
|
||||
|
@ -479,6 +481,13 @@ module Sinatra
|
|||
end
|
||||
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?('/')
|
||||
type = ".#{type}" unless type.to_s[0] == ?.
|
||||
Rack::Mime.mime_type(type, nil)
|
||||
end
|
||||
|
||||
def before(&block)
|
||||
@filters << block
|
||||
end
|
||||
|
@ -502,6 +511,21 @@ module Sinatra
|
|||
}
|
||||
end
|
||||
|
||||
def accept_mime_types(types)
|
||||
types = [types] unless types.kind_of? Array
|
||||
types.map!{|t| media_type(t)}
|
||||
|
||||
condition {
|
||||
matching_types = (request.accept & types)
|
||||
unless matching_types.empty?
|
||||
response.headers['Content-Type'] = matching_types.first
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def get(path, opts={}, &block)
|
||||
conditions = @conditions.dup
|
||||
route 'GET', path, opts, &block
|
||||
|
@ -519,6 +543,7 @@ module Sinatra
|
|||
def route(method, path, opts={}, &block)
|
||||
host_name opts[:host] if opts.key?(:host)
|
||||
user_agent opts[:agent] if opts.key?(:agent)
|
||||
accept_mime_types opts[:provides] if opts.key?(:provides)
|
||||
|
||||
pattern, keys = compile(path)
|
||||
conditions, @conditions = @conditions, []
|
||||
|
|
|
@ -302,4 +302,37 @@ describe "Routing" do
|
|||
status.should.equal 200
|
||||
body.should.equal 'Hello Bar'
|
||||
end
|
||||
|
||||
it "filters by accept header" do
|
||||
mock_app {
|
||||
get '/', :provides => :xml do
|
||||
request.env['HTTP_ACCEPT']
|
||||
end
|
||||
}
|
||||
|
||||
get '/', :env => { :accept => 'application/xml' }
|
||||
should.be.ok
|
||||
body.should.equal 'application/xml'
|
||||
response.headers['Content-Type'].should.equal 'application/xml'
|
||||
|
||||
get '/', :env => { :accept => 'text/html' }
|
||||
should.not.be.ok
|
||||
end
|
||||
|
||||
it "allows multiple mime types for accept header" do
|
||||
types = ['image/jpeg', 'image/pjpeg']
|
||||
|
||||
mock_app {
|
||||
get '/', :provides => types do
|
||||
request.env['HTTP_ACCEPT']
|
||||
end
|
||||
}
|
||||
|
||||
types.each do |type|
|
||||
get '/', :env => { :accept => type }
|
||||
should.be.ok
|
||||
body.should.equal type
|
||||
response.headers['Content-Type'].should.equal type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue