Module: HttpGetter

Defined in:
lib/http_getter.rb

Defined Under Namespace

Classes: Error, HttpError, TimeoutError

Class Method Summary collapse

Class Method Details

.execute(uri, request, opts = {}) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/http_getter.rb', line 86

def self.execute(uri, request, opts = {})
  timeout = opts[:timeout] || 60
  open_timeout = opts[:open_timeout] || 10
  max_retries = opts[:max_retries] || 2
  raw = opts[:__raw__] == true

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = uri.scheme == 'https'
  http.open_timeout = open_timeout
  http.read_timeout = timeout

  retries = 0
  begin
    response = http.request(request)
    parse(response, raw)
  rescue Net::OpenTimeout, Net::ReadTimeout => e
    retries += 1
    if retries <= max_retries
      sleep(2 ** retries)
      retry
    end
    raise TimeoutError, "请求超时(已重试 #{max_retries} 次): #{e.message}"
  ensure
    http.finish if http.started?
  end
end

.get(url, params = {}, headers = {}, opts = {}) ⇒ Hash/String

核心 GET 方法 ============

Parameters:

  • url (String)

    完整 URL 或路径;若已含 query,params 会追加在其后

  • params (Hash) (defaults to: {})

    查询参数,自动用 URI.encode_www_form 编码到 query string

  • headers (Hash) (defaults to: {})

    自定义请求头(自动覆盖默认头)

  • opts (Hash) (defaults to: {})

    选项: :timeout, :open_timeout, :max_retries

Returns:

  • (Hash/String)

    解析后的 JSON 或原始响应体



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/http_getter.rb', line 42

def self.get(url, params = {}, headers = {}, opts = {})
  uri = URI.parse(url)
  unless params.empty?
    extra = URI.encode_www_form(params)
    uri.query = uri.query ? "#{uri.query}&#{extra}" : extra
  end

  req = Net::HTTP::Get.new(uri)
  req['User-Agent'] = headers['User-Agent'] || 'ruby-http-getter/1.0'
  req['Accept'] = headers['Accept'] || 'application/json'

  # 认证头(支持 Bearer Token)
  if headers['Authorization'] || headers[:authorization]
    req['Authorization'] = headers['Authorization'] || headers[:authorization]
  end

  # 追加其余自定义头
  headers.each do |k, v|
    next if %w[Accept Authorization User-Agent].include?(k.to_s)
    req[k.to_s] = v.to_s
  end

  execute(uri, req, opts)
end

.get_json(url, params = {}, headers = {}, opts = {}) ⇒ Object

GET JSON(API 调用最常用) 自动设置 Accept: application/json,期望服务端返回 JSON



71
72
73
74
# File 'lib/http_getter.rb', line 71

def self.get_json(url, params = {}, headers = {}, opts = {})
  headers = headers.merge('Accept' => 'application/json')
  get(url, params, headers, opts)
end

.get_text(url, params = {}, headers = {}, opts = {}) ⇒ Object

GET 纯文本(原始响应体,不做 JSON 解析) 自动设置 Accept: text/plain,返回原始 String



78
79
80
81
82
# File 'lib/http_getter.rb', line 78

def self.get_text(url, params = {}, headers = {}, opts = {})
  headers = headers.merge('Accept' => 'text/plain')
  opts = opts.merge(__raw__: true)
  get(url, params, headers, opts)
end

.parse(response, raw = false) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/http_getter.rb', line 113

def self.parse(response, raw = false)
  body = response.body.to_s
  code = response.code.to_i

  if code >= 400
    begin
      err = JSON.parse(body)
      msg = err.dig('error', 'message') || body
    rescue
      msg = body
    end
    raise HttpError, "HTTP #{code}: #{msg}"
  end

  return body if raw

  JSON.parse(body) rescue body
end