1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
# frozen_string_literal: false
require 'gh'
require 'multi_json'
module GH
# Public: Class wrapping low level Github responses.
#
# Delegates safe methods to the parsed body (expected to be an Array or Hash).
class Response
include Enumerable
include GH::Case
attr_accessor :headers, :data, :body, :url
# subset of safe methods that both Array and Hash implement
extend Forwardable
def_delegators(:@data, :[], :assoc, :each, :empty?, :flatten, :include?, :index, :inspect, :length,
:pretty_print, :pretty_print_cycle, :rassoc, :select, :size, :to_a, :values_at)
# Internal: Initializes a new instance.
#
# headers - HTTP headers as a Hash
# body - HTTP body as a String
def initialize(body = '{}', headers = {}, url = nil)
@url = url
@headers = headers.transform_keys { |k| k.downcase }
case body
when nil, '' then @data = {}
when respond_to(:to_str) then @body = body.to_str
when respond_to(:to_hash) then @data = body.to_hash
when respond_to(:to_ary) then @data = body.to_ary
else raise ArgumentError, "cannot parse #{body.inspect}"
end
@body.force_encoding('utf-8') if @body.respond_to? :force_encoding
@body ||= MultiJson.encode(@data)
@data ||= MultiJson.decode(@body)
rescue EncodingError
raise "Invalid encoding in #{url}, please contact github."
end
# Public: Duplicates the instance. Will also duplicate some instance variables to behave as expected.
#
# Returns new Response instance.
def dup
super.dup_ivars
end
# Public: Returns the response body as a String.
def to_s
@body.dup
end
# Public: Returns true or false indicating whether it supports method.
def respond_to?(method, *)
return super unless (method.to_s == 'to_hash') || (method.to_s == 'to_ary')
data.respond_to? method
end
# Public: Implements to_hash conventions, please check respond_to?(:to_hash).
def to_hash
return method_missing(__method__) unless respond_to? __method__
@data.dup.to_hash
end
# Public: Implements to_ary conventions, please check respond_to?(:to_hash).
def to_ary
return method_missing(__method__) unless respond_to? __method__
@data.dup.to_ary
end
# Public: ...
def to_gh
self
end
# Public: ...
def ==(other)
super or @data == other
end
protected
def dup_ivars
@headers = @headers.dup
@data = @data.dup
@body = @body.dup
self
end
private
def content_type
headers['content-type']
end
end
end
|