lib/grape/middleware/formatter.rb in grape-0.2.4 vs lib/grape/middleware/formatter.rb in grape-0.2.5
- old
+ new
@@ -15,74 +15,102 @@
def headers
env.dup.inject({}){|h,(k,v)| h[k.to_s.downcase[5..-1]] = v if k.to_s.downcase.start_with?('http_'); h}
end
def before
- fmt = format_from_extension || format_from_params || options[:format] || format_from_header || options[:default_format]
- if content_type_for(fmt)
- if !env['rack.input'].nil? and (body = env['rack.input'].read).strip.length != 0
- parser = Grape::Parser::Base.parser_for fmt, options
- unless parser.nil?
+ negotiate_content_type
+ read_body_input
+ end
+
+ def after
+ status, headers, bodies = *@app_response
+ formatter = Grape::Formatter::Base.formatter_for env['api.format'], options
+ bodymap = bodies.collect do |body|
+ formatter.call body, env
+ end
+ headers['Content-Type'] = content_type_for(env['api.format']) unless headers['Content-Type']
+ Rack::Response.new(bodymap, status, headers).to_a
+ end
+
+ private
+
+ def read_body_input
+ request_method = request.request_method.to_s.upcase
+ if [ 'POST', 'PUT' ].include?(request_method) && (! request.form_data?) && (request.content_length.to_i > 0)
+ if env['rack.input'] && (body = env['rack.input'].read).strip.length > 0
begin
- body = parser.call body, env
- 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
+ fmt = mime_types[format_from_content_type]
+ if content_type_for(fmt)
+ parser = Grape::Parser::Base.parser_for fmt, options
+ unless parser.nil?
+ begin
+ body = parser.call body, env
+ env['rack.request.form_hash'] = env['rack.request.form_hash'] ? 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
+ else
+ throw :error, :status => 406, :message => 'The requested content-type is not supported.'
+ end
+ ensure
+ env['rack.input'].rewind
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
- def format_from_extension
- parts = request.path.split('.')
+ def negotiate_content_type
+ fmt = format_from_extension || format_from_params || options[:format] || format_from_header || options[:default_format]
+ if content_type_for(fmt)
+ env['api.format'] = fmt
+ else
+ throw :error, :status => 406, :message => 'The requested format is not supported.'
+ end
+ end
- if parts.size > 1
- extension = parts.last
+ def format_from_content_type
+ fmt = env['CONTENT_TYPE']
# avoid symbol memory leak on an unknown format
- return extension.to_sym if content_type_for(extension)
+ return fmt.to_sym if content_type_for(fmt)
+ fmt
end
- nil
- end
- def format_from_params
- fmt = Rack::Utils.parse_nested_query(env['QUERY_STRING'])["format"]
- # avoid symbol memory leak on an unknown format
- return fmt.to_sym if content_type_for(fmt)
- fmt
- end
+ def format_from_extension
+ parts = request.path.split('.')
- def format_from_header
- mime_array.each do |t|
- if mime_types.key?(t)
- return mime_types[t]
+ if parts.size > 1
+ extension = parts.last
+ # avoid symbol memory leak on an unknown format
+ return extension.to_sym if content_type_for(extension)
end
+ nil
end
- nil
- end
- def mime_array
- accept = headers['accept'] or return []
+ def format_from_params
+ fmt = Rack::Utils.parse_nested_query(env['QUERY_STRING'])["format"]
+ # avoid symbol memory leak on an unknown format
+ return fmt.to_sym if content_type_for(fmt)
+ fmt
+ end
- accept.gsub(/\b/,'').scan(%r((\w+/[\w+.-]+)(?:(?:;[^,]*?)?;\s*q=([\d.]+))?)).sort_by { |_, q| -q.to_f }.map {|mime, _|
- mime.sub(%r(vnd\.[^+]+\+), '')
- }
- end
+ def format_from_header
+ mime_array.each do |t|
+ if mime_types.key?(t)
+ return mime_types[t]
+ end
+ end
+ nil
+ end
- def after
- status, headers, bodies = *@app_response
- formatter = Grape::Formatter::Base.formatter_for env['api.format'], options
- bodymap = bodies.collect do |body|
- formatter.call body, env
+ def mime_array
+ 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
- headers['Content-Type'] = content_type_for(env['api.format']) unless headers['Content-Type']
- Rack::Response.new(bodymap, status, headers).to_a
- end
end
end
end