From 964cd0b049e67ca10bd37b67c4b14ccd37064511 Mon Sep 17 00:00:00 2001 From: Azul Date: Fri, 16 Sep 2016 14:32:55 +0200 Subject: deal with network issues in nicknym source This is a first step. In case the suspected nicknym server cannot be reached we will now move on and try other sources. It's robably not what we want in the long run. In order to know wether no key exists or we just failed to connect to some servers a different http response code would be nice if network errors occured. This simplifies testing such scenarios in the unit test and makes the remote tests skip on network failure. --- lib/nickserver/nicknym/source.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/nickserver') diff --git a/lib/nickserver/nicknym/source.rb b/lib/nickserver/nicknym/source.rb index 45daeaf..0638869 100644 --- a/lib/nickserver/nicknym/source.rb +++ b/lib/nickserver/nicknym/source.rb @@ -8,6 +8,8 @@ module Nickserver def available_for?(domain) status, body = adapter.get "https://#{domain}/provider.json" status == 200 && provider_with_mx?(body) + rescue HTTP::ConnectionError + return false end def query(email) -- cgit v1.2.3 From a1c7d68b05f142322a190b450971d27c076310a9 Mon Sep 17 00:00:00 2001 From: Azul Date: Mon, 19 Sep 2016 09:51:38 +0200 Subject: refactor: separate handler chain from dispatcher Handler Chain is of handlers that respond to call. Invoking handle(*args) on the chain will call the handlers with the given args until one of them returns a result that is truethy (i.e. not false or nil). Extracted from the dispatcher so we can also handle exceptions there in the future. (So that if one of the network connections to the request_handlers fails we can continue while still tracking the failed exception.) --- lib/nickserver/dispatcher.rb | 9 ++------- lib/nickserver/handler_chain.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 lib/nickserver/handler_chain.rb (limited to 'lib/nickserver') diff --git a/lib/nickserver/dispatcher.rb b/lib/nickserver/dispatcher.rb index 7a584e5..9968e95 100644 --- a/lib/nickserver/dispatcher.rb +++ b/lib/nickserver/dispatcher.rb @@ -35,10 +35,7 @@ module Nickserver protected def handle(request) - handler_chain.each do |handler| - response = handler.call request - return response if response - end + handler_chain.handle request rescue RuntimeError => exc puts "Error: #{exc}" puts exc.backtrace @@ -46,13 +43,11 @@ module Nickserver end def handler_chain - [ - RequestHandlers::InvalidEmailHandler, + HandlerChain.new RequestHandlers::InvalidEmailHandler, RequestHandlers::LocalEmailHandler, RequestHandlers::HkpEmailHandler, RequestHandlers::FingerprintHandler, Proc.new { Nickserver::Response.new(404, "404 Not Found\n") } - ] end def send_response(response) diff --git a/lib/nickserver/handler_chain.rb b/lib/nickserver/handler_chain.rb new file mode 100644 index 0000000..a0eba4d --- /dev/null +++ b/lib/nickserver/handler_chain.rb @@ -0,0 +1,26 @@ +# +# Handler Chain +# +# A chain of handlers that respond to call. Invoking handle(*args) on the chain +# will call the handlers with the given args until one of them returns a result +# that is truethy (i.e. not false or nil). +# +# Extracted from the dispatcher so we can also handle exceptions here in the +# future. +# + +module Nickserver + class HandlerChain + + def initialize(*handlers) + @handlers = handlers + end + + def handle(*args) + result = nil + _handled_by = @handlers.find{|h| result = h.call(*args)} + result + end + + end +end -- cgit v1.2.3 From dd71240fe4f4f968b9b687917cb6d7ad5812ba48 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 20 Sep 2016 09:14:43 +0200 Subject: rescue and track exceptions in handler chain --- lib/nickserver/handler_chain.rb | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'lib/nickserver') diff --git a/lib/nickserver/handler_chain.rb b/lib/nickserver/handler_chain.rb index a0eba4d..afc24a5 100644 --- a/lib/nickserver/handler_chain.rb +++ b/lib/nickserver/handler_chain.rb @@ -5,8 +5,11 @@ # will call the handlers with the given args until one of them returns a result # that is truethy (i.e. not false or nil). # -# Extracted from the dispatcher so we can also handle exceptions here in the -# future. +# You can specify exception classes to rescue with +# handler_chain.continue_on ErrorClass1, ErrorClass2 +# These exceptions will be rescued and tracked. The chain will proceed even if +# one handler raised the given exception. Afterwards you can inspect them with +# handler_chain.rescued_exceptions # module Nickserver @@ -14,13 +17,32 @@ module Nickserver def initialize(*handlers) @handlers = handlers + @exceptions_to_rescue = [] + @rescued_exceptions = [] + end + + def continue_on(*exceptions) + self.exceptions_to_rescue += exceptions end def handle(*args) result = nil - _handled_by = @handlers.find{|h| result = h.call(*args)} + _handled_by = @handlers.find{|h| result = try_handler(h, *args)} result end + attr_reader :rescued_exceptions + + protected + + attr_writer :rescued_exceptions + attr_accessor :exceptions_to_rescue + + def try_handler(handler, *args) + result = handler.call(*args) + rescue *exceptions_to_rescue + self.rescued_exceptions << $! + result = false + end end end -- cgit v1.2.3 From 6f507ed7b4f53054313173ce795ffd2cbcecd0b7 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 21 Sep 2016 12:48:11 +0200 Subject: feature: activate nicknym lookup --- lib/nickserver/dispatcher.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/nickserver') diff --git a/lib/nickserver/dispatcher.rb b/lib/nickserver/dispatcher.rb index 9968e95..75f6083 100644 --- a/lib/nickserver/dispatcher.rb +++ b/lib/nickserver/dispatcher.rb @@ -14,8 +14,10 @@ # require 'nickserver/request' +require 'nickserver/handler_chain' require 'nickserver/request_handlers/invalid_email_handler' require 'nickserver/request_handlers/local_email_handler' +require 'nickserver/request_handlers/leap_email_handler' require 'nickserver/request_handlers/hkp_email_handler' require 'nickserver/request_handlers/fingerprint_handler' @@ -45,6 +47,7 @@ module Nickserver def handler_chain HandlerChain.new RequestHandlers::InvalidEmailHandler, RequestHandlers::LocalEmailHandler, + RequestHandlers::LeapEmailHandler, RequestHandlers::HkpEmailHandler, RequestHandlers::FingerprintHandler, Proc.new { Nickserver::Response.new(404, "404 Not Found\n") } -- cgit v1.2.3 From 48cdd4b1ee0685674aa998d4daa295656d80ead3 Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 22 Sep 2016 11:07:47 +0200 Subject: feature: 502 on ConnectionErrors If one source raises a 502 and no other handler has any result we'll respond with a 502 - bad gateway. --- lib/nickserver/dispatcher.rb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'lib/nickserver') diff --git a/lib/nickserver/dispatcher.rb b/lib/nickserver/dispatcher.rb index 75f6083..869f721 100644 --- a/lib/nickserver/dispatcher.rb +++ b/lib/nickserver/dispatcher.rb @@ -24,6 +24,7 @@ require 'nickserver/request_handlers/fingerprint_handler' module Nickserver class Dispatcher + def initialize(responder) @responder = responder end @@ -45,12 +46,26 @@ module Nickserver end def handler_chain - HandlerChain.new RequestHandlers::InvalidEmailHandler, + @handler_chain ||= init_handler_chain + end + + def init_handler_chain + chain = HandlerChain.new RequestHandlers::InvalidEmailHandler, RequestHandlers::LocalEmailHandler, RequestHandlers::LeapEmailHandler, RequestHandlers::HkpEmailHandler, RequestHandlers::FingerprintHandler, + Proc.new {|_req| proxy_error_response }, Proc.new { Nickserver::Response.new(404, "404 Not Found\n") } + chain.continue_on HTTP::ConnectionError + return chain + end + + def proxy_error_response + exception = handler_chain.rescued_exceptions.first + if exception + Nickserver::Response.new(502, exception.to_s) + end end def send_response(response) -- cgit v1.2.3 From 1202e3b03c3bb88cd3a63dae3866167564f1d25d Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 22 Sep 2016 11:31:01 +0200 Subject: hand on connection errors to dispatcher so it can handle it --- lib/nickserver/nicknym/source.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/nickserver') diff --git a/lib/nickserver/nicknym/source.rb b/lib/nickserver/nicknym/source.rb index 0638869..45daeaf 100644 --- a/lib/nickserver/nicknym/source.rb +++ b/lib/nickserver/nicknym/source.rb @@ -8,8 +8,6 @@ module Nickserver def available_for?(domain) status, body = adapter.get "https://#{domain}/provider.json" status == 200 && provider_with_mx?(body) - rescue HTTP::ConnectionError - return false end def query(email) -- cgit v1.2.3 From 68ffe9928620d3e5e3b96152ed4d37da90f6a89b Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 22 Sep 2016 12:27:53 +0200 Subject: return nil on 404 in hkp source This way the other RequestHandlers can give it a try. If none handles it we'll get a 404 anyway. But maybe there's been an exception before so a 502 should be send. --- lib/nickserver/hkp/source.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/nickserver') diff --git a/lib/nickserver/hkp/source.rb b/lib/nickserver/hkp/source.rb index e104aa8..82c94a0 100644 --- a/lib/nickserver/hkp/source.rb +++ b/lib/nickserver/hkp/source.rb @@ -19,7 +19,7 @@ module Nickserver; module Hkp if status == 200 best = pick_best_key(response) get_key_by_fingerprint(best.keyid, nick) - else + elsif status != 404 # 404 means no key found and we proceed Nickserver::Response.new(status, response) end end -- cgit v1.2.3