Skip to content
Snippets Groups Projects
Commit eda9a082 authored by azul's avatar azul
Browse files

Merge branch 'bugfix/name-resolution' into 'master'

fix: #3 handle domains without A-record

Closes #3

See merge request !15
parents cfa6395c b1738a78
Branches
Tags
1 merge request!15fix: #3 handle domains without A-record
Pipeline #
...@@ -2,6 +2,19 @@ require 'nickserver/adapters' ...@@ -2,6 +2,19 @@ require 'nickserver/adapters'
require 'nickserver/config' require 'nickserver/config'
require 'http' require 'http'
# Nickserver::Adapters::Http
#
# Basic http adapter with ssl and minimal error handling.
# Only implemented get requests so far.
#
# Error Handling:
#
# Pass a string as the 'rescue' option. If a ConnectionError occures
# which includes the string passed it will be rescued and the request
# will return nil. This allows handling the error inside the adapter so
# that for the derived CelluloidHttp Adapter the actor does not get
# killed.
module Nickserver::Adapters module Nickserver::Adapters
class Http class Http
...@@ -9,6 +22,8 @@ module Nickserver::Adapters ...@@ -9,6 +22,8 @@ module Nickserver::Adapters
url = HTTP::URI.parse url.to_s url = HTTP::URI.parse url.to_s
response = get_with_auth url, params: options[:query] response = get_with_auth url, params: options[:query]
return response.code, response.to_s return response.code, response.to_s
rescue HTTP::ConnectionError => e
raise unless options[:rescue] && e.to_s.include?(options[:rescue])
end end
protected protected
... ...
......
...@@ -8,7 +8,8 @@ module Nickserver ...@@ -8,7 +8,8 @@ module Nickserver
PORT = 6425 PORT = 6425
def available_for?(domain) def available_for?(domain)
status, body = adapter.get "https://#{domain}/provider.json" status, body = adapter.get "https://#{domain}/provider.json",
rescue: 'failed to connect: getaddrinfo'
status == 200 && provider_with_mx?(body) status == 200 && provider_with_mx?(body)
end end
... ...
......
...@@ -24,6 +24,11 @@ class SampleTest < FunctionalTest ...@@ -24,6 +24,11 @@ class SampleTest < FunctionalTest
# Regression Tests # Regression Tests
# #3 handle missing A records
def test_nicknym
assert_lookup_status 404, 'postmaster@cs.ucl.ac.uk'
end
def test_no_file_descriptors_leak def test_no_file_descriptors_leak
lookup 'test@mail.bitmask.net' lookup 'test@mail.bitmask.net'
before = open_files_count before = open_files_count
... ...
......
Integration tests for clients of remote services Integration tests for clients of remote services
================================================ ================================================
The tests in this directory are integration test with remote services. However The tests in this directory are integration test with remote services.
we aims at testing the client side of the equation as that is what we control However we aims at testing the client side of the equation as that is
here. what we control here.
So unexpected server behavious should *crash* the test if we are not dealing So unexpected server behavious should *crash* the test if we are not
with it properly yet and have no unit test for it. dealing with it properly yet and have no unit test for it.
Server responses that we do not expect but handle in the code and test in unit Server responses that we do not expect but handle in the code and test
tests make the test *skip*. in unit tests make the test *skip*.
The Behaviour we would normally expect should make the test *pass* The Behaviour we would normally expect should make the test *pass*
...@@ -10,13 +10,24 @@ require 'nickserver/email_address' ...@@ -10,13 +10,24 @@ require 'nickserver/email_address'
class RemoteNicknymSourceTest < CelluloidTest class RemoteNicknymSourceTest < CelluloidTest
include HttpAdapterHelper include HttpAdapterHelper
def test_availablility_check def test_available_for_mail
source.available_for? 'mail.bitmask.net' source.available_for? 'mail.bitmask.net'
refute source.available_for? 'dl.bitmask.net' # not a provider
rescue HTTP::ConnectionError => e rescue HTTP::ConnectionError => e
skip e.to_s skip e.to_s
end end
# not a provider
def test_not_available
refute source.available_for? 'dl.bitmask.net'
rescue HTTP::ConnectionError => e
skip e.to_s
end
# cs.ucl.ac.uk only has an MX not an A-record
def test_not_available_without_a_record
refute source.available_for? 'cs.ucl.ac.uk'
end
def test_successful_query def test_successful_query
response = source.query(email_with_key) response = source.query(email_with_key)
skip if response.status == 404 skip if response.status == 404
... ...
......
...@@ -10,32 +10,31 @@ module HttpStubHelper ...@@ -10,32 +10,31 @@ module HttpStubHelper
end end
def stub_nicknym_available_response(domain, response = {}) def stub_nicknym_available_response(domain, response = {})
stub_http_request :get, "https://#{domain}/provider.json", stub_http_get "https://#{domain}/provider.json",
response: response response,
Hash
end end
def stub_sks_vindex_reponse(uid, response = {}) def stub_sks_vindex_reponse(uid, response = {})
stub_http_request :get, config.hkp_url, stub_http_get config.hkp_url, response,
query: {op: 'vindex', search: uid, exact: 'on', options: 'mr', fingerprint: 'on'}, query: {op: 'vindex', search: uid, exact: 'on', options: 'mr', fingerprint: 'on'}
response: response
end end
def stub_sks_get_reponse(key_id, response = {}) def stub_sks_get_reponse(key_id, response = {})
stub_http_request :get, config.hkp_url, stub_http_get config.hkp_url, response,
query: {op: 'get', search: "0x"+key_id, exact: 'on', options: 'mr'}, query: {op: 'get', search: "0x"+key_id, exact: 'on', options: 'mr'}
response: response
end end
def stub_couch_response(uid, response = {}) def stub_couch_response(uid, response = {})
query = "\?key=#{"%22#{uid}%22"}&reduce=false" query = "\?key=#{"%22#{uid}%22"}&reduce=false"
stub_http_request :get, stub_http_get /#{Regexp.escape(config.couch_url)}.*#{query}/,
/#{Regexp.escape(config.couch_url)}.*#{query}/, response
response: response
end end
def stub_http_request(verb, url, options = {}) private
response = {status: 200, body: ""}.merge(options.delete(:response) || {})
options = nil if options == {} def stub_http_get(url, response, options = nil)
response = {status: 200, body: ""}.merge(response || {})
adapter.expect :get, [response[:status], response[:body]], adapter.expect :get, [response[:status], response[:body]],
[url, options].compact [url, options].compact
end end
... ...
......
require 'test_helper' require 'test_helper'
require 'http'
require 'json'
require 'nickserver/nicknym/source' require 'nickserver/nicknym/source'
require 'nickserver/email_address' require 'nickserver/email_address'
...@@ -20,6 +22,11 @@ class NicknymSourceTest < Minitest::Test ...@@ -20,6 +22,11 @@ class NicknymSourceTest < Minitest::Test
refute available_on?(200, 'blablabla') refute available_on?(200, 'blablabla')
end end
# adapter rescues name resolution errors and returns nothing
def test_not_available_without_response
refute available_on?
end
def test_proxy_successful_query def test_proxy_successful_query
assert proxies_query_response?(200, 'dummy body') assert proxies_query_response?(200, 'dummy body')
end end
...@@ -39,9 +46,9 @@ class NicknymSourceTest < Minitest::Test ...@@ -39,9 +46,9 @@ class NicknymSourceTest < Minitest::Test
adapter.verify adapter.verify
end end
def available_on?(status = 0, body = nil) def available_on?(*args)
adapter.expect :get, [status, body], adapter.expect :get, args,
['https://remote.tld/provider.json'] ['https://remote.tld/provider.json', Hash]
available = source.available_for?('remote.tld') available = source.available_for?('remote.tld')
adapter.verify adapter.verify
return available return available
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment