diff options
author | azul <azul@riseup.net> | 2016-08-29 10:19:22 +0000 |
---|---|---|
committer | azul <azul@riseup.net> | 2016-08-29 10:19:22 +0000 |
commit | 6e2d31e3f7c515f65d92533bcdb035438461a00c (patch) | |
tree | 4efa7445db3a0521a14d75e626d64f85434a3ea5 /lib/nickserver | |
parent | c134e0940a44ba3fb3f0f8ee86faa8053a9e0b44 (diff) | |
parent | 0784391a21b75ca52892e992a614b0f927ade00e (diff) |
Merge branch 'refactor/request-handling' into 'master'
refactor: restructure the way we handle requests to make it more consistent.
Requests are handled at a lot of different ways in different styles right now.
Let's make this more consistent and flexible to add email lookup at other leap providers.
See merge request !2
Diffstat (limited to 'lib/nickserver')
-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 |