如何强制Grape接受并仅返回JSON?

时间:2014-06-21 12:52:51

标签: ruby-on-rails ruby routes grape grape-api

如何限制我的API接受&在Rails&上只响应json格式Grape,我在我的Grape控制器上尝试format :json并且(例如)我可以在example.com/api/v1/ping.json上访问它,但我也可以通过example.com/api/访问它v1 / ping.xml,example.com / api / v1 / ping.foobar,扩展列表继续......

我想做的事情是,在example.com/api/v1/ping.not_json_extensions上抛出错误

我正在使用:

  • rails(4.1.1)
  • grape(0.7.0)

/config/routes.rb

mount API::Base => '/api'

/controllers/api/base.rb

module API
 class Base < Grape::API
  mount API::V1::Base
 end
end

/controllers/api/v1/base.rb

module API
 module V1
  class Base < Grape::API
   format :json
   mount API::V1::Ping
  end
 end

/controllers/api/v1/ping.rb

module API
 module V1
  class Ping < Grape::API
    include API::V1::Defaults
    desc 'Returns pong.'
    get :ping do
      { ping: params[:pong] || 'pong' }
    end
  end
 end

1 个答案:

答案 0 :(得分:2)

看看Grape's source code,这似乎是预期的行为,但防止内存泄漏的更改有效地破坏了它。

您可以手动实施正确的行为&#34;通过向API类添加显式检查(在/controllers/api/base.rb中):

before do
  # Make sure the format specified by the request extension is one
  # we support
  parts = request.path.split('.')

  if parts.size > 1
    extension = parts.last

    if !extension.eql? 'json'
      throw :error, {
        status: 406,
        message: "The requested format '#{extension}' is not supported."
      }
    end
  end
end

此代码几乎逐字地从Grape的源代码中复制(在lib/grape/middleware/formatter.rb中),并且是Grape本身检查请求中使用的扩展名的方式。

在该文件中,negotiate_content_type负责检查所请求的格式是否是API支持的格式,并明确优先考虑请求扩展。但是,从URI解析扩展的方法,format_from_extension检查格式是否受支持,如果不是,则返回nil,就好像有根本没有扩展。因此,如果请求的扩展名指定了不受支持的格式,negotiate_content_type将永远不会触发错误,即使它显然是这样做的。

你可以修复&#34;这可以通过更改formatter.rb:109的代码来自

# avoid symbol memory leak on an unknown format
return extension.to_sym if content_type_for(extension)

简单地

return extension.to_sym

评论建议代码是出于某种原因以这种方式编写的,所以请谨慎行事。