File: resource.rb

package info (click to toggle)
ruby-swd 2.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 184 kB
  • sloc: ruby: 510; makefile: 6
file content (81 lines) | stat: -rw-r--r-- 2,116 bytes parent folder | download
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