class Grape::Middleware::Formatter
Constants
- DEFAULT_OPTIONS
Public Instance Methods
Source
# File lib/grape/middleware/formatter.rb, line 15 def after return unless @app_response status, headers, bodies = *@app_response if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) [status, headers, []] else build_formatted_response(status, headers, bodies) end end
Source
# File lib/grape/middleware/formatter.rb, line 10 def before negotiate_content_type read_body_input end
Private Instance Methods
Source
# File lib/grape/middleware/formatter.rb, line 29 def build_formatted_response(status, headers, bodies) headers = ensure_content_type(headers) if bodies.is_a?(Grape::ServeStream::StreamResponse) Grape::ServeStream::SendfileResponse.new([], status, headers) do |resp| resp.body = bodies.stream end else # Allow content-type to be explicitly overwritten formatter = fetch_formatter(headers, options) bodymap = ActiveSupport::Notifications.instrument('format_response.grape', formatter: formatter, env: env) do bodies.collect { |body| formatter.call(body, env) } end Rack::Response.new(bodymap, status, headers) end rescue Grape::Exceptions::InvalidFormatter => e throw :error, status: 500, message: e.message, backtrace: e.backtrace, original_exception: e end
Source
# File lib/grape/middleware/formatter.rb, line 57 def ensure_content_type(headers) if headers[Rack::CONTENT_TYPE] headers else headers.merge(Rack::CONTENT_TYPE => content_type_for(env[Grape::Env::API_FORMAT])) end end
Set the content type header for the API
format if it is not already present.
@param headers [Hash] @return [Hash]
Source
# File lib/grape/middleware/formatter.rb, line 48 def fetch_formatter(headers, options) api_format = env.fetch(Grape::Env::API_FORMAT) { mime_types[headers[Rack::CONTENT_TYPE]] } Grape::Formatter.formatter_for(api_format, options[:formatters]) end
Source
# File lib/grape/middleware/formatter.rb, line 130 def format_from_extension request_path = rack_request.path.try(:scrub) dot_pos = request_path.rindex('.') return unless dot_pos extension = request_path[dot_pos + 1..] extension if content_type_for(extension) end
Source
# File lib/grape/middleware/formatter.rb, line 139 def format_from_header accept_header = env['HTTP_ACCEPT'].try(:scrub) return if accept_header.blank? media_type = Rack::Utils.best_q_match(accept_header, mime_types.keys) mime_types[media_type] if media_type end
Source
# File lib/grape/middleware/formatter.rb, line 121 def negotiate_content_type fmt = format_from_extension || query_params['format'] || options[:format] || format_from_header || options[:default_format] if content_type_for(fmt) env[Grape::Env::API_FORMAT] = fmt.to_sym else throw :error, status: 406, message: "The requested format '#{fmt}' is not supported." end end
Source
# File lib/grape/middleware/formatter.rb, line 65 def read_body_input input = rack_request.body # reads RACK_INPUT return if input.nil? return unless read_body_input? input.try(:rewind) body = env[Grape::Env::API_REQUEST_INPUT] = input.read begin read_rack_input(body) ensure input.try(:rewind) end end
Source
# File lib/grape/middleware/formatter.rb, line 114 def read_body_input? (rack_request.post? || rack_request.put? || rack_request.patch? || rack_request.delete?) && !(rack_request.form_data? && rack_request.content_type) && !rack_request.parseable_data? && (rack_request.content_length.to_i.positive? || rack_request.env['HTTP_TRANSFER_ENCODING'] == 'chunked') end
this middleware will not try to format the following content-types since Rack already handles them when calling Rack’s ‘params` function
-
application/x-www-form-urlencoded
-
multipart/form-data
-
multipart/related
-
multipart/mixed
Source
# File lib/grape/middleware/formatter.rb, line 79 def read_rack_input(body) return if body.empty? media_type = rack_request.media_type fmt = media_type ? mime_types[media_type] : options[:default_format] throw :error, status: 415, message: "The provided content-type '#{media_type}' is not supported." unless content_type_for(fmt) parser = Grape::Parser.parser_for fmt, options[:parsers] if parser begin body = (env[Grape::Env::API_REQUEST_BODY] = parser.call(body, env)) if body.is_a?(Hash) env[Rack::RACK_REQUEST_FORM_HASH] = if env.key?(Rack::RACK_REQUEST_FORM_HASH) env[Rack::RACK_REQUEST_FORM_HASH].merge(body) else body end env[Rack::RACK_REQUEST_FORM_INPUT] = env[Rack::RACK_INPUT] end rescue Grape::Exceptions::Base => e raise e rescue StandardError => e throw :error, status: 400, message: e.message, backtrace: e.backtrace, original_exception: e end else env[Grape::Env::API_REQUEST_BODY] = body end end