覆盖默认的Content-Type

时间:2017-07-11 22:59:47

标签: ruby-on-rails json

我有一个Rails API,只接受JSON作为输入。如果我没有包含Content-Type:application / json的标头,则request.headers['Content-Type']默认为application/x-www-form-urlencoded,并且params不会被正确解析。整个json身体成为params的关键。结果是422,这让API用户感到困惑。

如果没有提供Content-Type标头,如何将其更改为默认解析为json?

许多其他问题回答了如何使用响应格式执行此操作。要更改此默认值,您可以使用以下命令在控制器中指定它:

 request.format = :json

或者在路径名称空间中使用类似:

 namespace :api, defaults: {format: :json} do

但是,这会更改默认响应格式,并且不会更改默认请求格式。 我需要做的是更改解析参数的默认请求格式。

3 个答案:

答案 0 :(得分:2)

parsed = JSON.parse(json_body) unless request.headers["Content-Type"] == 'application/json'

答案 1 :(得分:0)

这是我公认的可怕的解决方案,源自Micael Nussbaumer的答案。我喜欢它,如果一些Rubyists可以神奇地将这个丑陋的黑客变成一个简洁的单行内容。

module Api
  class BaseApiController < ActionController::API

  private
    # This is an ugly hack needed to make it default to json if you do not
    # specify a Content-Type.  If you see this and know of a better way please
    # say so!
    def params
      if !@params
        if request.headers["Content-Type"]=="application/x-www-form-urlencoded"
          body_string = request.body.read
          begin
            hash = JSON.parse(body_string)
            @params = ActionController::Parameters.new(hash)
          rescue
            # do nothing
          end
        end
        if !@params
          @params = super
        end
      end
      @params
    end

    ...

end

答案 2 :(得分:0)

我用Rails API(rails new my_project --api

以这种方式解决了这个问题

配置:

# config/application.rb
# ...
require './lib/middleware/consider_all_request_json_middleware'
# ...

module MyApplication
    # ...
  class Application < Rails::Application
        # ...
        config.middleware.insert_before(ActionDispatch::Static,ConsiderAllRequestJsonMiddleware)
        # ...

中间件:

# lib/middleware/consider_all_request_json_middleware.rb
class ConsiderAllRequestJsonMiddleware
  def initialize app
    @app = app
  end

  def call(env)
    if env["CONTENT_TYPE"] == 'application/x-www-form-urlencoded'
      env["CONTENT_TYPE"] = 'application/json'
    end
    @app.call(env)
  end
end

原文:https://blog.eq8.eu/til/content-type-applicationjson-by-default-in-rails-5.html