将 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,我主要是在此处复制粘贴稍作改动的版本。
基本上您需要按照以下步骤操作:
- 安装
faraday
和 socksify
gem
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
创建请求。我注意到您可能正在尝试发出 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.
我有以下 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,我主要是在此处复制粘贴稍作改动的版本。
基本上您需要按照以下步骤操作:
- 安装
faraday
和socksify
gem 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
创建请求。我注意到您可能正在尝试发出 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.