【问题标题】:Force all received requests Content-Type to JSON强制所有收到的请求 Content-Type 为 JSON
【发布时间】:2014-05-24 05:44:52
【问题描述】:

我实际上正在开发一个使用 Rails 4 的 API。如果客户端未在 Content-Type 标头中指定媒体类型,我想将请求的 Content-Type 设置为 JSON。

为了获得这种行为,我尝试在我的 ApplicationController 中添加以下 before_action

def set_request_default_content_type
  request.format = :json
end

在我的RegistrationsController#create 方法中,我有一个断点来检查一切是否正常。好吧,request.format 技巧不起作用,尽管该值设置为 application/json,但控制器(或 Rails 内部)似乎不将接收到的请求的 Content-Type 视为 JSON。

我使用以下正文(并且没有 Content-Type)进行了 POST 请求:

{"user" : {"email":"foobar@mail.net","password":"foobarfoo"}}

通过使用 Pry 进行调试,我发现:

 [2] api(#<V1::RegistrationsController>) _  request.format.to_s
 => "application/json"
 [3] api(#<V1::RegistrationsController>) _  params
 => {
       "action" => "create",
   "controller" => "v1/registrations"
 }

这意味着 Rails 没有考虑我的 request.format 配置为Mime::JSON,而是使用Mime::ALL,因此它没有解析请求的 JSON 正文。 :(

【问题讨论】:

  • 我认为你需要在你身上使用wrap_parameters() ActionController
  • ActionController::ParamsWrapper 默认启用 json 格式。但它不起作用。目前我不使用 MetalController,而是使用带有标准控制器的经典 Rails 架构。

标签: ruby-on-rails ruby api ruby-on-rails-4 rails-api


【解决方案1】:

您应该能够使用路由设置默认格式:http://guides.rubyonrails.org/routing.html#defining-defaults

resources :registrations, ... defaults: { format: 'json' }

另见:How to set the default format for a route in Rails? format-for-a-route-in-rails?answertab=active#tab-top


也可能感兴趣:

当它包含“,/”或“/”时,Rails 会忽略接受头,并返回 HTML(如果是 xhr 请求,则返回 JS)。

这是设计为在从浏览器访问时始终返回 HTML。

这不遵循 mime 类型协商规范,但它是绕过带有错误接受标头的旧浏览器的唯一方法。他们让他接受第一个 mime 类型为 image/png 或 text/xml 的标题。

【讨论】:

  • 我已经尝试使用 config/route.rb 的默认格式参数,它与我的 before_action 基本相同:[2] api(#<:registrationscontroller>) _ request.format。 to_s => "application/json" [3] api(#<:registrationscontroller>) _ request.content_type => "text/plain" [4] api(#<:registrationscontroller>) _ params => { “格式” => :json, “动作” => “创建”, “控制器” => “v1/注册” } :(
  • request.format 不会改变 request.content_type
  • 我看到了您的问题,它与请求(content_type)而不是响应(格式)有关
  • 是的,只有在请求时;)
【解决方案2】:
class V1::RegistrationsController < ApplicationController
  respond_to :json
end

将默认响应格式设为json

【讨论】:

  • 问题是关于请求内容类型,而不是响应内容类型。请求内容类型影响服务器如何解释请求,例如解析参数。
【解决方案3】:

您可以在 respond_to 块内定义 any 类型响应,这不会限制您的控制器在请求 uri 以 .json 结尾时响应,它还可以让您从显式定义响应类型中解脱出来,并将保留,独立于请求内容类型,随心所欲地响应,例如:

respond_to do |format|
  format.any  {render :json => {foo: 'bar'}}
end

【讨论】:

    【解决方案4】:

    检查此SO answer。它使用constraints如下

    defaults format: :json do
      # your v1/registration route here
    end
    

    【讨论】:

      【解决方案5】:

      基于这个post,可以创建一些中间件来翻译Content-Type: application/json的标头。

      # 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)
          env["CONTENT_TYPE"] = "application/json" if env["CONTENT_TYPE"] == "application/x-www-form-urlencoded"
      
          @app.call(env)
        end
      end
      
      

      我已经使用 Rails 6 API-only 项目对其进行了测试,它可以正常工作。

      【讨论】:

        【解决方案6】:

        您可以在routes.rb 文件中使用约束来强制使用 content_type。

        Rails 3 上的示例:

        match '/api/endpoint' => 'apis_controller#endpoint', constraints: lambda { |request| request.format = :json }
        

        该行将使对该路由的所有请求的Content-Type 成为json

        rails 3.0.6 上使用rspec 2.99rspec-rails 2.99 进行测试时,这个其他解决方案也对我有用:

        params = { username: 'username' }
        post '/your_path', params.merge({format: 'json'}).to_json, { 'CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json' }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-20
          • 2019-09-13
          • 2015-09-18
          • 2015-04-28
          • 2013-10-27
          • 1970-01-01
          相关资源
          最近更新 更多