summaryrefslogtreecommitdiff
path: root/lib/nickserver
diff options
context:
space:
mode:
authorazul <azul@riseup.net>2016-08-29 10:19:22 +0000
committerazul <azul@riseup.net>2016-08-29 10:19:22 +0000
commit6e2d31e3f7c515f65d92533bcdb035438461a00c (patch)
tree4efa7445db3a0521a14d75e626d64f85434a3ea5 /lib/nickserver
parentc134e0940a44ba3fb3f0f8ee86faa8053a9e0b44 (diff)
parent0784391a21b75ca52892e992a614b0f927ade00e (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.rb65
-rw-r--r--lib/nickserver/error_response.rb11
-rw-r--r--lib/nickserver/invalid_source.rb14
-rw-r--r--lib/nickserver/lookup.rb31
-rw-r--r--lib/nickserver/reel_server.rb4
-rw-r--r--lib/nickserver/request.rb30
-rw-r--r--lib/nickserver/request_handler.rb95
-rw-r--r--lib/nickserver/request_handlers/email_handler.rb22
-rw-r--r--lib/nickserver/request_handlers/fingerprint_handler.rb27
-rw-r--r--lib/nickserver/request_handlers/invalid_email_handler.rb15
-rw-r--r--lib/nickserver/request_handlers/local_email_handler.rb32
-rw-r--r--lib/nickserver/source.rb3
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