Rails:将 API 请求限制为 JSON 格式

Posted

技术标签:

【中文标题】Rails:将 API 请求限制为 JSON 格式【英文标题】:Rails: Restrict API requests to JSON format 【发布时间】:2013-01-17 19:30:58 【问题描述】:

我想限制对所有 API 控制器的请求被重定向到 JSON 路径。我想使用重定向,因为 URL 也应该根据响应而改变。 一种选择是使用 before_filter 将请求重定向到相同的操作,但强制使用 JSON 格式。该示例尚未运行!

# base_controller.rb
class Api::V1::BaseController < InheritedResources::Base
  before_filter :force_response_format
  respond_to :json
  def force_response_format
    redirect_to, params[:format] = :json
  end
end

另一种选择是在路由设置中限制格式。

# routes.rb
MyApp::Application.routes.draw do
  namespace :api, defaults:  format: 'json'  do
    namespace :v1 do
      resources :posts
    end
  end
end

我希望所有请求都以 JSON 请求的形式结束:

http://localhost:3000/api/v1/posts
http://localhost:3000/api/v1/posts.html
http://localhost:3000/api/v1/posts.xml
http://localhost:3000/api/v1/posts.json
...

您会推荐哪种策略?

【问题讨论】:

【参考方案1】:

第二个选项,使用路由格式。如果用户明确请求 XML 格式,他不应该收到 JSON 响应。他应该收到一条消息,指出此 URL 不响应 XML 格式或 404。

顺便说一句,我认为你应该做的所有事情都可以很容易地做出回应。

class FooController
  respond_to :xml, :json
  def show
    @bar = Bar.find(params[:id])
    respond_with(@bar)
  end
end

【讨论】:

+1 表示评论的开头。根据我的经验,添加格式并不容易,尽管 Rails 很容易实现。 API 设计人员仍然需要考虑支持其他格式意味着什么,以及所有含义。【参考方案2】:

在您的路由中设置默认值不会将所有请求都转换为 JSON 请求。

您想要确保呈现的内容是 JSON 响应

除了你需要这样做之外,你几乎在第一个选项中就有了它

before_filter :set_default_response_format

private
  def set_default_response_format
    request.format = :json
  end

这将在您的 Base API 控制器下进行,因此当它到达您的实际操作时,格式将始终为 JSON。

【讨论】:

request.format设置为:json解决了所有响应都返回JSON的问题。但它不会更改地址栏中的 URL。 如果你在做一个 API 为什么你需要在地址栏中写 URL?请注意,执行重定向会返回 300 状态,并且它可能不是最有效的,但请不要引用我的话。 这么说,你会建议在任何情况下将请求格式重写为 JSON 吗?另一种选择是返回一些 HTTP 状态作为 mathieugagne 和你提到的。 这些是您必须为您的 API 考虑的设计选项。您是只想接受/返回 JSON,还是愿意返回 XML 和其他格式...【参考方案3】:

如果你想返回 404,或者如果格式不是 :json 则引发 RouteNotFound 错误,我会添加这样的路由约束:

需要 JSON 格式:

# routes.rb
MyApp::Application.routes.draw do
  namespace :api, constraints:  format: 'json'  do
    namespace :v1 do
      resources :posts
    end
  end
end

更多信息可以在这里找到: http://edgeguides.rubyonrails.org/routing.html#request-based-constraints

【讨论】:

我认为在这种情况下 406 是更准确的响应。知道为什么这种方法会返回 404 吗? @asymmetric 这是因为约束说“这个规则只匹配 json 请求”,所以任何非 json 请求都不会匹配,并且会一直到最后,除非你有一个特定的后续规则匹配非 json 请求并以另一个响应显式响应。

以上是关于Rails:将 API 请求限制为 JSON 格式的主要内容,如果未能解决你的问题,请参考以下文章

Airbnb案例:Ruby on Rails YAML格式化字符串时导致的远程代码执行

Rails:如何将对象数组的哈希转换为 json

Rails 为 json api 请求返回不正确的 MIME 类型(仅在测试中)

API Rails 上的获取请求不返回 json

如何限制 Rails 路由文件中的资源格式

如何构造循环API调用以使JSON结果可用?