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:
Markus Prinz 2009-01-07 20:32:31 +01:00 committed by Ryan Tomayko
parent 9681803a42
commit 38778eddda
3 changed files with 65 additions and 3 deletions

View File

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

View File

@ -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, []

View File

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