module Rack class AcceptOnly def initialize(app, permitted_type = nil) raise "Keep the permitted content-type simple please" if permitted_type && permitted_type.match(%r{[*; ]}) @app = app @permitted_type = permitted_type end def call(env) acceptable_types = get_acceptable_types(env) return @app.call(env) unless !acceptable_types.empty? || @permitted_type if !match_against_types?(acceptable_types, @permitted_type) return unacceptable(@permitted_type) end reply = @app.call(env) reply_type = reply[1]['Content-Type'] return server_error unless reply_type if @permitted_type && reply_type != @permitted_type reply = server_error end if !match_against_types?(acceptable_types, reply_type) reply = unacceptable(reply_type) end reply end def get_acceptable_types(env) return [] unless env['HTTP_ACCEPT'] acceptable_types = env['HTTP_ACCEPT'].split(",") acceptable_types.collect do |type| temp = type.strip.split(";")[0].gsub("*", "(.+)") Regexp.new("^#{temp}$") end end def match_against_types?(types, string) return true unless !types.empty? && string types.each do |type| return true if string.match(type) end false end def unacceptable(supplyable_type) [406, {'Content-Type' => supplyable_type, "Content-Length" => "0"}, [""]] end def server_error [500, {"Content-Length" => "0"}, [""]] end end end