【问题标题】:How do I make Ruby's RestClient gem respect content_type on post?如何让 Ruby 的 RestClient gem 在 post 上尊重 content_type?
【发布时间】:2019-10-07 19:48:21
【问题描述】:

例如,在 RestClient 控制台中:

RestClient.post 'http://localhost:5001', {:a => 'b'}, :content_type => 'application/json'

这不会发送 application/json 作为内容类型。相反,我看到:

Content-Type: application/x-www-form-urlencoded

我能够追踪到 restclient/payload.rb 的更改:

  class UrlEncoded < Base
  ...

  def headers
    super.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
  end
end

将 super.merge 替换为 super 会导致内容类型受到尊重,但显然这不是一个真正的解决方案。有谁知道解决这个问题的正确方法?谢谢。

【问题讨论】:

    标签: ruby rest-client


    【解决方案1】:

    您可能希望将 json 作为字符串而不是哈希值作为有效负载。例如,这样做:

    RestClient.post 'http://localhost:5001','{"a":"b"}',:content_type => 'application/json'
    

    如果您查看 payload.rb,它表明如果有效负载是字符串,它将使用 Base 类而不是 UrlEncoded 类。试试看,看看是否适合你。

    【讨论】:

      【解决方案2】:

      事实:

      对于:post 请求,当payload 是Hash 时,Content-Type 标头将始终被覆盖为application/x-www-form-urlencoded。

      可通过 rest-client (2.0.0) 重现。

      解决方案:

      将哈希有效负载转换为 json 字符串。

      require 'json'
      
      payload.to_json
      

      rest-client 的仓库中有一个ticket:

      【讨论】:

        【解决方案3】:

        我想补充一点,我的问题是在使用 RestClient::Request.execute(而不是 RestClient.post 或 RestClient.get)时。

        问题在于我如何设置:content_type 和:accept。从我看到的示例中,我觉得它们应该是这样的顶级选项:

        res = RestClient::Request.execute(
          :method => :get,
          :url => url,
          :verify_ssl =>  false,
          :content_type => :json,
          :accept => :json,
          :headers => { 
            :Authorization => "Bearer #{token}", 
          },
          :payload => '{"a":"b"}'
        )
        

        但实际上你必须像这样将它们放在:headers 中:

        res = RestClient::Request.execute(
          :method => :get,
          :url => url,
          :verify_ssl =>  false,
          :headers => { 
            :Authorization => "Bearer #{token}", 
            :content_type => :json,
            :accept => :json
          },
          :payload => '{"a":"b"}'
        )
        

        【讨论】:

          【解决方案4】:

          我试图通过 POST 以表单数据格式提交用户名和密码,以及 csrf 令牌和身份验证 cookie。将有效负载转换为 json 并明确设置内容类型标头没有帮助。我最终将有效负载作为查询字符串传递,并将其转换为 JSON:

          RestClient::Request.execute(
            method: :post, 
            url: 'http://app_url/login.do',
            payload: "username=username&password=password&_csrf=token",
            headers: {'X-XSRF-TOKEN' => 'token'},
            cookies: {'XSRF-TOKEN' =>  cookie_object}
          )
          

          另一种选择是使用 encode_www_form,但查询字符串更适合我的特定用例。

          虽然这不是一种常见的情况,并且完全取决于后端预期的参数格式,但如果服务器期望 url 编码作为 POST 正文,则在 POST 正文中传递查询字符串仍然是一个可行的选择。希望这可能对某人有所帮助。

          【讨论】:

            猜你喜欢
            • 2012-05-16
            • 2018-03-09
            • 2014-11-07
            • 2015-09-26
            • 1970-01-01
            • 2019-07-01
            • 1970-01-01
            • 2017-07-13
            • 2018-11-18
            相关资源
            最近更新 更多