将 curl 调用转换为法拉第请求

converting a curl call to a faraday request

我有以下 curl 请求 -

`curl --socks5 #{proxy} --connect-timeout 10 -H "Accept: application/json" #{url}`

我想写法拉第请求而不是 curl 调用。我正在这样做 -

faraday =  Faraday.new("#{url}", ssl:{verify: false} do |f|
    f.proxy "#{proxy}"
end
faraday.get

我正在收到回复,但回复中没有 body 或 headers。以下是回复 -

#<Faraday::Response:0x0056075d353ad0 @on_complete_callbacks=[], @env=#<Faraday::Env @method=:get @url=#<URI::HTTP:0x0056075d358328 URL:main_url> @request=#<Faraday::RequestOptions proxy=#<Faraday::ProxyOptions uri=#<URI::HTTP:0x0056075dce69d0 URL:proxy_url>>> @request_headers={"User-Agent"=>"Faraday v0.9.2"} @ssl=#<Faraday::SSLOptions (empty)> @response=#<Faraday::Response:0x0056075d353ad0 ...>>>

我做错了什么?

这就是我使用法拉第 post 请求从 Microsoft Exchange API 获取访问令牌的方式。

url = "https://login.microsoftonline.com/#{ENV['TENANT']}/oauth2/token"

conn = Faraday.new url: url do |faraday|
  faraday.request  :url_encoded             # form-encode POST params
  faraday.response :logger                  # log requests to STDOUT
  faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
end

response = conn.post do |req|
  req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
  req.body = {
    client_id: URI::encode(ENV['CLIENT_ID']),
    client_secret: URI::encode(ENV['CLIENT_SECRET']),
    resource: URI::encode('https://graph.microsoft.com'),
    grant_type: URI::encode('client_credentials'),
  }
  Rails.logger.info "Body #{req.body.inspect}"
end

if response.status.to_i == 200
  response_body = ActiveSupport::JSON.decode(response.body)
  return response_body['access_token']
else
  return false
end

希望对您有所帮助。

转换为 Faraday 最困难的问题是您需要使用 SOCKS5 代理。 Faraday 不支持 SOCKS 代理(有一个 open pull-request for this)。

解决此问题的唯一方法是 monkey-patch Faraday 以使用 socksify gem which adds support for SOCKS proxies to Net::HTTP (the default Faraday network adapter). The procedure is nicely described in this gist,我主要是在此处复制粘贴稍作改动的版本。

基本上您需要按照以下步骤操作:

  1. 安装 faradaysocksify gem
  2. Monkey-patch Faraday 以支持 SOCKS。将此代码放入 Rails 初始化程序中。请注意,该补丁仅在您不需要向 SOCKS 代理进行身份验证时适用(如您的 curl 命令所建议的那样)。如果您需要代理身份验证,请参阅支持它的补丁版本的要点。补丁如下:

    class Faraday::Adapter::NetHttp
      def net_http_connection(env)
        if proxy = env[:request][:proxy]
          if proxy[:socks]
            Net::HTTP::SOCKSProxy(proxy[:uri].host, proxy[:uri].port)
          else
            Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:uri].user, proxy[:uri].password)
          end
        else
            Net::HTTP
        end.new(env[:url].host, env[:url].port)
      end
    end
    
  3. 创建请求。我注意到您可能正在尝试发出 HTTPS 请求,所以我考虑了这一点,以及 curl 参数中的超时:

    PROXY_OPTS = {
            uri:  URI.parse('https://proxy_url:1080'),
            socks: true  
        }
    
    SSL_OPTS = { verify: false }
    
    connection = Faraday.new(url: "https://example.com",
                             ssl: SSL_OPTS,
                             request: { proxy: PROXY_OPTS }) do |faraday|
      faraday.options.timeout = 10           # open/read timeout in seconds
      faraday.options.open_timeout = 10      # connection open timeout in seconds
      faraday.response :logger               # log debug info
      faraday.adapter  :net_http             # use the Net:HTTP adapter
    
      faraday.headers['Accept'] = 'application/json'  # your custom headers
    end
    
    response = connection.get
    response.body
    

最后请注意,忽略对等验证(SSL 选项中的verify: false)是不安全的!您应该改为正确配置 Faraday 以使用证书存储来验证对等证书。这完全记录在案 here.