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
|
module SWD
class Resource
include AttrRequired, AttrOptional
attr_required :principal, :service, :host, :path
attr_optional :port
class Expired < Exception; end
def initialize(attributes = {})
(optional_attributes + required_attributes).each do |key|
self.send "#{key}=", attributes[key]
end
@path ||= '/.well-known/simple-web-discovery'
attr_missing!
end
def discover!(cache_options = {})
SWD.cache.fetch(cache_key, cache_options) do
handle_response do
SWD.http_client.get endpoint.to_s
end
end
end
def endpoint
SWD.url_builder.build [nil, host, port, path, {
:principal => principal,
:service => service
}.to_query, nil]
rescue URI::Error => e
raise Exception.new(e.message)
end
private
def handle_response
json = yield.body.with_indifferent_access
if redirect = json[:SWD_service_redirect]
redirect_to redirect[:location], redirect[:expires]
else
to_response_object json
end
rescue Faraday::Error => e
case e.response_status
when nil
raise Exception.new e
when 400
raise BadRequest.new('Bad Request', e.response_body)
when 401
raise Unauthorized.new('Unauthorized', e.response_body)
when 403
raise Forbidden.new('Forbidden', e.response_body)
when 404
raise NotFound.new('Not Found', e.response_body)
else
raise HttpError.new(e.response_status, e.response_body, e.response_body)
end
end
# NOTE: overwritten in openid_connect gem.
def to_response_object(json)
Response.new json
end
def redirect_to(location, expires)
uri = URI.parse(location)
@host, @path, @port = uri.host, uri.path, uri.port
raise Expired if expires && expires.to_i < Time.now.utc.to_i
discover!
end
def cache_key
sha256 = OpenSSL::Digest::SHA256.hexdigest [
principal,
service,
host
].join(' ')
"swd:resource:#{sha256}"
end
end
end
|