【问题标题】:Ruby on Rails: How do detect if access by JSON?Ruby on Rails:如何检测是否通过 JSON 访问?
【发布时间】:2011-11-26 12:29:46
【问题描述】:

我得到一个调用控制器方法 getInfo 的 GET URL。可以通过 mydomain.com/getInfo.json?params=BLAHBLAH 或 mydomain.com/getInfo?params=BLAHBLAH

调用

在控制器中,有没有办法检测用户如何调用它?

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    是的。在控制器中,您可以调用request.format 方法来确定用户请求的格式。

    如果您需要的不仅仅是格式,您可以查看request.url 以获取完整的 URL。有关request 对象的更多详细信息,请参见here

    【讨论】:

    • 提示:您可以对返回的Mime::Type 进行== 比较,例如request.format == 'json'。还有一个方便的#html? 方法,例如before_action :do_something if: "request.format.html?"
    【解决方案2】:

    在你的控制器的特定方法中,你可以响应不同的格式——例如:

    respond_to do |format|
      format.html
      format.json { render :json => @user }
    end
    

    您可以响应各种格式(xml、js、json 等) - 您可以在此处获取有关 respond_to 以及如何在控制器中使用它的更多信息:

    http://apidock.com/rails/ActionController/MimeResponds/InstanceMethods/respond_to

    【讨论】:

    • 对这个非常烦人 - 这个例子有效,但这并不是OP真正要求的。此示例设置对各种类型调用的响应,它实际上并没有告诉您的应用程序此特定调用是 JSON API 请求还是“HTML 请求”
    【解决方案3】:

    这是一个实际的有点做作的工作示例,它回答了如何检测调用是 JSON/XML API 调用还是“HTML”调用的问题。 (Accepted answer不回答那个问题,只是告诉你如何应对各种格式)

    # We can use this in a before_filter
    skip_before_action :verify_authenticity_token, if: :api_request?
    
    # Or in the action
    def show
      @user = if api_request?
                User.where(api_token: params[:token]).first
              else
                User.find(params[:id])
              end
      respond_to do |format|
        format.html 
        format.json { render :json => @user }
      end
    end
    
    private
      def api_request?
        request.format.json? || request.format.xml?
      end
    

    使用respond_to 设置不同类型的响应,但它不会告诉您的应用程序是如何进行调用的,除非您添加一些额外的代码来执行此操作(请参见下面的粗略示例,只是为了说明这一点。 )

    我不建议这样做,询问 request 更安全,并且有用 10 倍,因为下面的方法仅在请求生命周期的后期(在将响应发送回客户端之前)有用。如果您在之前的过滤器中有任何逻辑,这根本不起作用。

    # Have no way of using it in a before_filter
    # In your controller
    def show
      # I want to know if the call was JSON API - right here 
      # This approach wouldn't help at all. 
      @user = User.find(params[:id])
      respond_to do |format|
        format.html { @api_request = false}
        format.json { @api_request = true; render :json => @user }
      end
    end
    
    def api_request?
      @api_request
    end
    

    【讨论】:

      【解决方案4】:

      检查 json 的方法列表

      request.format == 'json'
      request.format == :json
      request.format.json?
      request.path.match('json')
      request.url.match('json')
      respond_to do |format|
        format.json { render json: [] }
      end
      

      您还可以检查请求是否为 ajax 请求

      request.xhr?
      

      【讨论】:

      • 谢谢,非常有用,因为我想知道请求是 json 还是 javascript。
      【解决方案5】:

      就这么简单:

      request.path_parameters[:format] == 'json'
      

      【讨论】:

      • 虽然这不是这个问题的合适答案(使用 @michaeldcruz 建议的 respond_to ),但这是将当前扩展名添加到链接的好方法,例如,一个 rabl 文件引用其他 URL 可以在 json 和 xml 中工作。
      【解决方案6】:

      如果您需要检查它是否是 Ajax 请求,您可以使用 request.xhr? 来检查 header[X-Requested-With]

      示例代码sn-p

      if request.xhr?
        # Do the ajax stuff
      else
        # Do normal stuff
      end
      

      【讨论】:

      • 我在找这个!这是一个更好的解决方案,但我相信该标题是非标准的(stackoverflow.com/a/26245601/179311)。当您使用它们的 ajax 助手时,它被原型、jQuery 和一些其他库使用,如果您滚动自己的 ajax 调用,可以添加标头。
      猜你喜欢
      • 2021-07-09
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多