diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/nickserver/dispatcher.rb | 65 | ||||
-rw-r--r-- | lib/nickserver/error_response.rb | 11 | ||||
-rw-r--r-- | lib/nickserver/invalid_source.rb | 14 | ||||
-rw-r--r-- | lib/nickserver/lookup.rb | 31 | ||||
-rw-r--r-- | lib/nickserver/reel_server.rb | 4 | ||||
-rw-r--r-- | lib/nickserver/request.rb | 30 | ||||
-rw-r--r-- | lib/nickserver/request_handler.rb | 95 | ||||
-rw-r--r-- | lib/nickserver/request_handlers/email_handler.rb | 22 | ||||
-rw-r--r-- | lib/nickserver/request_handlers/fingerprint_handler.rb | 27 | ||||
-rw-r--r-- | lib/nickserver/request_handlers/invalid_email_handler.rb | 15 | ||||
-rw-r--r-- | lib/nickserver/request_handlers/local_email_handler.rb | 32 | ||||
-rw-r--r-- | lib/nickserver/source.rb | 3 |
12 files changed, 205 insertions, 144 deletions
diff --git a/lib/nickserver/dispatcher.rb b/lib/nickserver/dispatcher.rb new file mode 100644 index 0000000..8bcfd05 --- /dev/null +++ b/lib/nickserver/dispatcher.rb @@ -0,0 +1,65 @@ +# +# Dispatcher +# +# Dispatch a request so it get's handled by the correct handler. +# +# The dispatcher hands a request to one handler after the other until one of +# them responds. +# +# This is similar to the Chain of Responsibility patter but we iterate over the +# 'handler_chain' array instead of a linked list. +# +# To change the order of handlers or add other handlers change the array in the +# handler_chain function. +# + +require 'nickserver/request' +require 'nickserver/request_handlers/invalid_email_handler' +require 'nickserver/request_handlers/local_email_handler' +require 'nickserver/request_handlers/email_handler' +require 'nickserver/request_handlers/fingerprint_handler' + +module Nickserver + class Dispatcher + + 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_chain.each do |handler| + response = handler.call request + return response if response + end + rescue RuntimeError => exc + puts "Error: #{exc}" + puts exc.backtrace + ErrorResponse.new(exc.to_s) + end + + def handler_chain + [ + RequestHandlers::InvalidEmailHandler.new, + RequestHandlers::LocalEmailHandler.new, + RequestHandlers::EmailHandler.new, + RequestHandlers::FingerprintHandler.new, + Proc.new { Nickserver::Response.new(404, "Not Found\n") } + ] + end + + def send_response(status = 200, content = '') + responder.respond status, content + end + + attr_reader :responder + + end +end diff --git a/lib/nickserver/error_response.rb b/lib/nickserver/error_response.rb new file mode 100644 index 0000000..1065e4e --- /dev/null +++ b/lib/nickserver/error_response.rb @@ -0,0 +1,11 @@ +require 'nickserver/response' + +module Nickserver + class ErrorResponse < Nickserver::Response + def initialize(message) + @status = 500 + @message = message + "\n" + end + + end +end diff --git a/lib/nickserver/invalid_source.rb b/lib/nickserver/invalid_source.rb deleted file mode 100644 index dac245a..0000000 --- a/lib/nickserver/invalid_source.rb +++ /dev/null @@ -1,14 +0,0 @@ -# -# This is a dummy source for invalid queries. -# It simply always returns 500 and "Not a valid address" -# - -module Nickserver - class InvalidSource - - def query(nick) - yield 500, "Not a valid address" - end - - end -end diff --git a/lib/nickserver/lookup.rb b/lib/nickserver/lookup.rb deleted file mode 100644 index 105e77e..0000000 --- a/lib/nickserver/lookup.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'nickserver/invalid_source' - -module Nickserver - class Lookup - - attr_reader :nick - - def initialize(nick) - @nick = nick - end - - def respond_with(responder) - query do |status, content| - responder.send_response status: status, content: content - end - end - - protected - - def query(&block) - source.query nick, &block - end - - def source - if nick.invalid? then Nickserver::InvalidSource - elsif nick.local? then Nickserver::Config.local_source - else Nickserver::Config.remote_source - end - end - end -end diff --git a/lib/nickserver/reel_server.rb b/lib/nickserver/reel_server.rb index 6f05e0b..b681577 100644 --- a/lib/nickserver/reel_server.rb +++ b/lib/nickserver/reel_server.rb @@ -2,7 +2,7 @@ silence_warnings do require 'reel' end require 'nickserver/adapters/celluloid_http' -require 'nickserver/request_handler' +require 'nickserver/dispatcher' module Nickserver class ReelServer < Reel::Server::HTTP @@ -32,7 +32,7 @@ module Nickserver protected def handler_for(request) - RequestHandler.new(request, Nickserver::Adapters::CelluloidHttp.new) + Dispatcher.new(request) end def params(request) diff --git a/lib/nickserver/request.rb b/lib/nickserver/request.rb new file mode 100644 index 0000000..c21c280 --- /dev/null +++ b/lib/nickserver/request.rb @@ -0,0 +1,30 @@ +module Nickserver + class Request + def initialize(params, headers) + @params = params || {} + @headers = headers + end + + def email + param("address") + end + + def fingerprint + param("fingerprint") + end + + def domain + host_header = headers['Host'] || '' + domain_part = host_header.split(':')[0] || '' + domain_part.strip.sub(/^nicknym\./, '') + end + + protected + + def param(key) + params[key] && params[key].first + end + + attr_reader :params, :headers + end +end diff --git a/lib/nickserver/request_handler.rb b/lib/nickserver/request_handler.rb deleted file mode 100644 index 856ec5d..0000000 --- a/lib/nickserver/request_handler.rb +++ /dev/null @@ -1,95 +0,0 @@ -require 'nickserver/hkp/source' -require 'nickserver/couch_db/source' - -module Nickserver - class RequestHandler - - def initialize(responder, adapter) - @responder = responder - @adapter = adapter - end - - def respond_to(params, headers) - if params && params["address"] && params["address"].any? - by_email(params, headers) - elsif params && params["fingerprint"] && params["fingerprint"].any? - by_fingerprint(params) - else - send_not_found - end - - rescue RuntimeError => exc - puts "Error: #{exc}" - puts exc.backtrace - send_error(exc.to_s) - end - - protected - - def by_email(params, headers) - email = EmailAddress.new(params["address"].first) - if email.invalid? - send_error("Not a valid address") - else - send_key(email, headers) - end - end - - def by_fingerprint(params) - fingerprint = params["fingerprint"].first - if fingerprint.length == 40 && !fingerprint[/\H/] - source = Nickserver::Hkp::Source.new(adapter) - key_response = source.get_key_by_fingerprint(fingerprint) - send_response key_response.status, key_response.content - else - send_error('Fingerprint invalid: ' + fingerprint) - end - end - - def send_key(email, headers) - if local_address?(email, headers) - source = Nickserver::CouchDB::Source.new(adapter) - else - source = Nickserver::Hkp::Source.new(adapter) - end - response = source.query(email) - send_response response.status, response.content - rescue MissingHostHeader - send_error("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, headers) - email.domain?(Config.domain || domain_from_headers(headers)) - end - - # no domain configured, use Host header - def domain_from_headers(headers) - host_header = headers['Host'] - raise MissingHostHeader if host_header.nil? - host_header.split(':')[0].strip.sub(/^nicknym\./, '') - end - - def send_error(msg = "not supported") - send_response 500, "500 #{msg}\n" - end - - def send_not_found(msg = "Not Found") - send_response 404, "404 #{msg}\n" - end - - def send_response(status = 200, content = '') - responder.respond status, content - end - - attr_reader :responder, :adapter - - class MissingHostHeader < StandardError - end - end -end diff --git a/lib/nickserver/request_handlers/email_handler.rb b/lib/nickserver/request_handlers/email_handler.rb new file mode 100644 index 0000000..96fcaf3 --- /dev/null +++ b/lib/nickserver/request_handlers/email_handler.rb @@ -0,0 +1,22 @@ +require 'nickserver/email_address' +require 'nickserver/hkp/source' + +module Nickserver + module RequestHandlers + class EmailHandler + + def call(request) + return unless request.email + email = EmailAddress.new(request.email) + source.query(email) + end + + protected + + def source + Nickserver::Hkp::Source.new + end + + end + end +end diff --git a/lib/nickserver/request_handlers/fingerprint_handler.rb b/lib/nickserver/request_handlers/fingerprint_handler.rb new file mode 100644 index 0000000..3c04fcd --- /dev/null +++ b/lib/nickserver/request_handlers/fingerprint_handler.rb @@ -0,0 +1,27 @@ +require 'nickserver/hkp/source' +require 'nickserver/error_response' + +module Nickserver + module RequestHandlers + class FingerprintHandler + + def call(request) + return unless request.fingerprint + handle_request(request) + end + + protected + + def handle_request(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 + end +end diff --git a/lib/nickserver/request_handlers/invalid_email_handler.rb b/lib/nickserver/request_handlers/invalid_email_handler.rb new file mode 100644 index 0000000..eaf8156 --- /dev/null +++ b/lib/nickserver/request_handlers/invalid_email_handler.rb @@ -0,0 +1,15 @@ +require 'nickserver/email_address' +require 'nickserver/error_response' + +module Nickserver + module RequestHandlers + class InvalidEmailHandler + def call(request) + return unless request.email + email = EmailAddress.new(request.email) + ErrorResponse.new("Not a valid address") if email.invalid? + end + + end + end +end diff --git a/lib/nickserver/request_handlers/local_email_handler.rb b/lib/nickserver/request_handlers/local_email_handler.rb new file mode 100644 index 0000000..1f2abc2 --- /dev/null +++ b/lib/nickserver/request_handlers/local_email_handler.rb @@ -0,0 +1,32 @@ +require 'nickserver/email_address' +require 'nickserver/error_response' +require 'nickserver/couch_db/source' + +module Nickserver + module RequestHandlers + class LocalEmailHandler + + def call(request) + return nil unless request.email + domain = Config.domain || request.domain + return missing_domain_response if domain.nil? || domain == '' + email = EmailAddress.new(request.email) + return nil unless email.domain?(domain) + source.query email + end + + protected + + attr_reader :domain + + def source + Nickserver::CouchDB::Source.new + end + + def missing_domain_response + ErrorResponse.new "HTTP request must include a Host header." + end + + end + end +end diff --git a/lib/nickserver/source.rb b/lib/nickserver/source.rb index b8135da..78f245b 100644 --- a/lib/nickserver/source.rb +++ b/lib/nickserver/source.rb @@ -1,13 +1,12 @@ module Nickserver class Source - def initialize(adapter) + def initialize(adapter = Nickserver::Adapters::CelluloidHttp.new) @adapter = adapter end protected attr_reader :adapter - end end |