lib/grape/middleware/formatter.rb in grape-0.1.5 vs lib/grape/middleware/formatter.rb in grape-0.2.0
- old
+ new
@@ -1,30 +1,42 @@
require 'grape/middleware/base'
-require 'multi_json'
module Grape
module Middleware
class Formatter < Base
include Formats
def default_options
- {
+ {
:default_format => :txt,
:formatters => {},
- :content_types => {}
+ :content_types => {},
+ :parsers => {}
}
end
def headers
- env.dup.inject({}){|h,(k,v)| h[k.downcase] = v; h}
+ env.dup.inject({}){|h,(k,v)| h[k.downcase[5..-1]] = v if k.downcase.start_with?('http_'); h}
end
def before
- fmt = format_from_extension || format_from_header || options[:default_format]
-
+ fmt = format_from_extension || options[:format] || format_from_header || options[:default_format]
if content_types.key?(fmt)
- env['api.format'] = fmt
+ if !env['rack.input'].nil? and (body = env['rack.input'].read).strip.length != 0
+ parser = parser_for fmt
+ unless parser.nil?
+ begin
+ body = parser.call(body)
+ env['rack.request.form_hash'] = !env['rack.request.form_hash'].nil? ? env['rack.request.form_hash'].merge(body) : body
+ env['rack.request.form_input'] = env['rack.input']
+ rescue
+ # It's possible that it's just regular POST content -- just back off
+ end
+ end
+ env['rack.input'].rewind
+ end
+ env['api.format'] = fmt
else
throw :error, :status => 406, :message => 'The requested format is not supported.'
end
end
@@ -38,51 +50,33 @@
hit
end
end
def format_from_header
- mime_array.each do |t|
+ mime_array.each do |t|
if mime_types.key?(t)
return mime_types[t]
end
end
nil
end
def mime_array
- accept = headers['accept']
- if accept
- accept.gsub(/\b/,'').
- scan(/(\w+\/[\w+]+)(?:;[^,]*q=([0-9.]+)[^,]*)?/i).
- sort_by{|a| -a[1].to_f}.
- map{|a| a[0]}
- else
- []
- end
+ accept = headers['accept'] or return []
+
+ accept.gsub(/\b/,'').scan(%r((\w+/[\w+.-]+)(?:(?:;[^,]*?)?;\s*q=([\d.]+))?)).sort_by { |_, q| -q.to_f }.map {|mime, _|
+ mime.sub(%r(vnd\.[^+]+\+), '')
+ }
end
def after
status, headers, bodies = *@app_response
formatter = formatter_for env['api.format']
bodymap = bodies.collect do |body|
formatter.call(body)
end
headers['Content-Type'] = content_types[env['api.format']]
Rack::Response.new(bodymap, status, headers).to_a
- end
-
- def encode_json(object)
- if object.respond_to? :serializable_hash
- MultiJson.encode(object.serializable_hash)
- elsif object.respond_to? :to_json
- object.to_json
- else
- MultiJson.encode(object)
- end
- end
-
- def encode_txt(object)
- object.respond_to?(:to_txt) ? object.to_txt : object.to_s
end
end
end
end