Class: Rack::Conneg
- Inherits:
-
Object
- Object
- Rack::Conneg
- Defined in:
- lib/rack/conneg.rb
Constant Summary collapse
- VERSION =
'0.1.3'
Instance Method Summary collapse
-
#accept_all_extensions? ⇒ Boolean
Should content negotiation accept any file extention passed as part of the URI path, even if it’s not one of the registered provided types?.
- #call(env) ⇒ Object
-
#fallback ⇒ Object
What MIME type should be used as a fallback if negotiation fails? Defaults to ‘text/html’ since that’s what’s used to deliver most error message content.
-
#ignore(route) ⇒ Object
Specifies a route prefix or Regexp that should be ignored by the content negotiator.
-
#initialize(app) ⇒ Conneg
constructor
A new instance of Conneg.
-
#provide(*args) ⇒ Object
Register one or more content types that the application offers.
-
#set(key, value) ⇒ Object
Set a content negotiation option.
Constructor Details
#initialize(app) ⇒ Conneg
Returns a new instance of Conneg.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/rack/conneg.rb', line 10 def initialize(app) @app = app @ignores = [] @opts = { :accept_all_extensions => false, :fallback => 'text/html' } @types = [] @app.class.module_eval { def negotiated_ext ; @rack_conneg_ext ; end #:nodoc:# def negotiated_type ; @rack_conneg_type ; end #:nodoc:# def respond_to wants = { '*/*' => Proc.new { raise TypeError, "No handler for #{@rack_conneg_type}" } } def wants.method_missing(ext, *args, &handler) type = ext == :other ? '*/*' : Rack::Mime::MIME_TYPES[".#{ext.to_s}"] self[type] = handler end yield wants (wants[@rack_conneg_type] || wants['*/*']).call end } if block_given? yield self end end |
Instance Method Details
#accept_all_extensions? ⇒ Boolean
Should content negotiation accept any file extention passed as part of the URI path, even if it’s not one of the registered provided types?
87 88 89 |
# File 'lib/rack/conneg.rb', line 87 def accept_all_extensions? @opts[:accept_all_extensions] ? true : false end |
#call(env) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/rack/conneg.rb', line 40 def call(env) extension = nil path_info = env['PATH_INFO'] unless @ignores.find { |ignore| ignore.match(path_info) } # First, check to see if there's an explicit type requested # via the file extension mime_type = Rack::Mime.mime_type(::File.extname(path_info),nil) if mime_type env['PATH_INFO'] = path_info.sub!(/(\..+?)$/,'') extension = $1 if !(accept_all_extensions? || @types.include?(mime_type)) mime_type = nil end else # Create an array of types out of the HTTP_ACCEPT header, sorted # by q value and original order accept_types = env['HTTP_ACCEPT'].split(/,/) accept_types.each_with_index { |t,i| (accept_type,weight) = t.split(/;/) weight = weight.nil? ? 1.0 : weight.split(/\=/).last.to_f accept_types[i] = { :type => accept_type, :weight => weight, :order => i } } accept_types.sort! { |a,b| ord = b[:weight] <=> a[:weight] if ord == 0 ord = a[:order] <=> b[:order] end ord } # Find the first item in accept_types that matches a registered # content type accept_types.find { |t| re = %r{^#{Regexp.escape(t[:type].gsub(/\*/,'.+'))}$} @types.find { |type| re.match(type) ? mime_type = type : nil } } end mime_type ||= fallback @app.instance_variable_set('@rack_conneg_ext',env['rack.conneg.ext'] = extension) @app.instance_variable_set('@rack_conneg_type',env['rack.conneg.type'] = mime_type) end @app.call(env) unless @app.nil? end |
#fallback ⇒ Object
What MIME type should be used as a fallback if negotiation fails? Defaults to ‘text/html’ since that’s what’s used to deliver most error message content.
93 94 95 |
# File 'lib/rack/conneg.rb', line 93 def fallback find_mime_type(@opts[:fallback]) end |
#ignore(route) ⇒ Object
Specifies a route prefix or Regexp that should be ignored by the content negotiator. Use for static files or any other route that should be passed through unaltered.
99 100 101 102 |
# File 'lib/rack/conneg.rb', line 99 def ignore(route) route_re = route.kind_of?(Regexp) ? route : %r{^#{route}} @ignores << route_re end |
#provide(*args) ⇒ Object
Register one or more content types that the application offers. Can be a content type string, a file extension, or a symbol (e.g., ‘application/xml’, ‘.xml’, and :xml are all equivalent).
106 107 108 109 110 111 |
# File 'lib/rack/conneg.rb', line 106 def provide(*args) args.flatten.each { |type| mime_type = find_mime_type(type) @types << mime_type } end |
#set(key, value) ⇒ Object
Set a content negotiation option. Valid options are:
-
:accept_all_extensions - true if all file extensions should be mapped to MIME types whether or not their associated types are specifically provided
-
:fallback - a content type string, file extention, or symbol representing the MIME type to fall back on if negotiation fails
118 119 120 121 122 123 124 |
# File 'lib/rack/conneg.rb', line 118 def set(key, value) opt_key = key.to_sym if !@opts.include?(opt_key) raise IndexError, "Unknown option: #{key.to_s}" end @opts[opt_key] = value end |