Ruby 标准库 net/http 内建了代理支持,发起 Ruby 代理请求时只需给 Net::HTTP.new 多传几个代理参数,或使用 Net::HTTP::Proxy 包装类,无需安装任何 gem 即可让请求经代理转发。两种写法本质相同,后者更适合复用与构建代理池。本文讲解配置细节、认证方式、HTTPS 场景与超时控制,并梳理常见异常与对应的排查方向。
环境准备与标准库说明
Net::HTTP 属于 Ruby 内置标准库,require 'net/http' 后即可使用,Ruby 2.7 与 3.x 系列行为一致;解析 URL 时再引入 require 'uri'。由于不依赖 Gemfile 与 bundler,这段代码可以直接放进 Rails 控制台、Rake 任务或独立脚本,迁移成本几乎为零。需要注意的是,net/http 原生只支持 HTTP 代理,若节点是 SOCKS5 协议,需要额外引入 socksify gem 对 TCPSocket 打补丁。
- 零 gem 依赖:仅标准库 net/http 与 uri,Ruby 2.7+ 开箱即用。
- 部署灵活:可运行于 Rails 控制台、Rake 任务与独立脚本。
- 协议边界:SOCKS5 需 socksify gem,标准库仅支持 HTTP 代理。
Net::HTTP 代理参数与 Net::HTTP::Proxy
Net::HTTP.new 的完整签名是 new(address, port, p_addr, p_port, p_user, p_pass),后四个参数依次是代理地址、端口与认证的账号密码,传 nil 表示对应项缺省。Net::HTTP::Proxy('127.0.0.1', 8080, 'user', 'pass') 会返回一个内置代理能力的子类,用它创建的所有实例自动携带代理配置,业务代码完全无感,这也是构建多出口代理池的推荐姿势。
完整代码示例
下面的例子通过包装类创建 HTTPS 连接,并设置了双阶段超时与异常捕获:
require 'net/http'
require 'uri'
http = Net::HTTP::Proxy('127.0.0.1', 8080, 'user', 'pass')
.new('httpbin.org', 443)
http.use_ssl = true
http.open_timeout = 5 # 与代理建立连接的超时(秒)
http.read_timeout = 15 # 读取响应的超时(秒)
begin
response = http.get('/ip')
puts "状态码: #{response.code}"
puts response.body
rescue Net::OpenTimeout
puts '连接代理超时,请检查地址与端口'
rescue Net::ReadTimeout
puts '代理已连通,但响应读取超时'
rescue Errno::ECONNREFUSED
puts '代理拒绝连接'
rescue OpenSSL::SSL::SSLError => e
puts "SSL 错误: #{e.message}"
end
open_timeout 限制与代理建立连接的时间,read_timeout 限制读取响应的等待,单位都是秒。get 方法会自动完成连接的建立与关闭;需要连续请求同一主机时,改用 http.start 的块形式可以在块内复用连接,显著减少重复握手。
HTTPS 与代理认证
目标协议是 https 时设置 use_ssl = true,Net::HTTP 会自动经代理建立 CONNECT 隧道,与目标站点的 TLS 协商在隧道内完成。建议显式设置 verify_mode = OpenSSL::SSL::VERIFY_PEER 确保证书校验;遇到使用自签证书的抓包代理,正确做法是通过 cert_store 加载其根证书,而不是简单设为 VERIFY_NONE。代理认证由 p_user 与 p_pass 两个参数完成,Net::HTTP 会自动生成 Proxy-Authorization 请求头,无需手工编码。
常见异常与注意事项
- Errno::ECONNREFUSED:代理地址或端口错误,连接被直接拒绝。
- Net::OpenTimeout:与代理握手超时,链路不通或代理过载。
- Net::ReadTimeout:代理已连通但响应缓慢,适当调大 read_timeout。
- EOFError:代理提前断开连接,常见于认证失败或并发数超限。
Article ID: 37
(本文仅供技术交流,请遵守法律法规)