我有一个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
但是,这会更改默认响应格式,并且不会更改默认请求格式。 我需要做的是更改解析参数的默认请求格式。
答案 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