summaryrefslogtreecommitdiff
path: root/lib/nickserver/request_handler.rb
blob: 1239c448950d9591a6b1069708a7ed126f91d439 (plain)
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
102
103
104
105
106
require 'nickserver/hkp/source'
require 'nickserver/couch_db/source'
require 'nickserver/request'

module Nickserver
  class RequestHandler

    def initialize(responder)
      @responder = responder
    end

    def respond_to(params, headers)
      request = Nickserver::Request.new params, headers
      response = handle request
      send_response response.status, response.content
    end

    protected

    def handle(request)
      handler = handler_for_request request
      handler.call request
    rescue RuntimeError => exc
      puts "Error: #{exc}"
      puts exc.backtrace
      ErrorResponse.new(exc.to_s)
    end

    def handler_for_request(request)
      if request.email
        EmailHandler.new
      elsif request.fingerprint
        FingerprintHandler.new
      else
        Proc.new { Nickserver::Response.new(404, "Not Found\n") }
      end
    end

    class EmailHandler

      def call(request)
        email = EmailAddress.new(request.email)
        if email.invalid?
          ErrorResponse.new("Not a valid address")
        else
          send_key(email, request)
        end
      end

      protected

      def send_key(email, request)
        if local_address?(email, request)
          source = Nickserver::CouchDB::Source.new
        else
          source = Nickserver::Hkp::Source.new
        end
        source.query(email)
      rescue MissingHostHeader
        ErrorResponse.new("HTTP request must include a Host header.")
      end

      #
      # Return true if the user address is for a user of this service provider.
      # e.g. if the provider is example.org, then alice@example.org returns true.
      #
      # If 'domain' is not configured, we rely on the Host header of the HTTP request.
      #
      def local_address?(email, request)
        domain = Config.domain || request.domain
        raise MissingHostHeader if domain == ''
        email.domain? domain
      end
    end

    class FingerprintHandler

      def call(request)
        fingerprint = request.fingerprint
        if fingerprint.length == 40 && !fingerprint[/\H/]
          source = Nickserver::Hkp::Source.new
          source.get_key_by_fingerprint(fingerprint)
        else
          ErrorResponse.new('Fingerprint invalid: ' + fingerprint)
        end
      end

    end

    class ErrorResponse < Nickserver::Response
      def initialize(message)
        @status = 500
        @message = message + "\n"
      end
    end

    def send_response(status = 200, content = '')
      responder.respond status, content
    end

    attr_reader :responder

    class MissingHostHeader < StandardError
    end
  end
end