diff --git a/src/Simplex/Messaging/Server/Names.hs b/src/Simplex/Messaging/Server/Names.hs index 19bae15fc..a5287956b 100644 --- a/src/Simplex/Messaging/Server/Names.hs +++ b/src/Simplex/Messaging/Server/Names.hs @@ -76,6 +76,10 @@ fetch NamesEnv {resolverEnv} d = mapResolverError :: ResolverError -> NameErrorType mapResolverError = \case HttpStatusErr 404 -> NOT_FOUND + -- 410 is a lapsed registration (past expiry, in grace or beyond): a correct + -- answer about the name, not a resolver failure, so it must not become + -- RESOLVER - that is reserved for the backing resolver/RPC breaking. + HttpStatusErr 410 -> NOT_FOUND HttpStatusErr 400 -> NOT_FOUND HttpStatusErr code -> RESOLVER ("HTTP " <> T.pack (show code)) HttpFailure _ -> RESOLVER "transport failure" diff --git a/tests/RSLVTests.hs b/tests/RSLVTests.hs index 2416d851e..fbff33a43 100644 --- a/tests/RSLVTests.hs +++ b/tests/RSLVTests.hs @@ -19,7 +19,7 @@ import Data.List.NonEmpty (NonEmpty (..)) import Data.Text (Text) import Data.Text.Encoding (encodeUtf8) import Data.Time.Clock (getCurrentTime) -import Network.HTTP.Types (Status, status200, status404, status502) +import Network.HTTP.Types (Status, status200, status404, status410, status502) import NamesResolverServer (memCfg, memCfg2, memProxyCfg, withNames) import qualified NamesResolverServer as NRS import SMPClient @@ -74,6 +74,7 @@ rslvTests :: Spec rslvTests = do describe "RSLV direct (non-forwarded)" $ do it "resolver replies 404 -> NAME NOT_FOUND (reached, not CMD PROHIBITED)" testRslvBackendNotFound + it "resolver replies 410 -> NAME NOT_FOUND (a lapsed name, not a resolver failure)" testRslvBackendGone it "resolver replies 502 -> NAME (RESOLVER ..)" testRslvBackendHttpErr it "no names config -> NAME NO_RESOLVER" testRslvDisabled it "refuses to send RSLV on a session below namesSMPVersion" testRslvVersion @@ -91,6 +92,17 @@ testRslvBackendNotFound = corrId `shouldBe` CorrId "rs01" resp `shouldBe` Right (ERR (NAME NOT_FOUND)) +-- The resolver answers 410 for a registration that has lapsed (in grace or +-- past it). That is a correct answer about the name, so it has to arrive as +-- NOT_FOUND; RESOLVER would make the client treat it as a broken resolver and +-- abort domain verification instead of reporting the name as unverified. +testRslvBackendGone :: IO () +testRslvBackendGone = + withResolverServer (status410, "{}") $ + testSMPClient @TLS $ \h -> do + (_, _, resp) <- sendRslv h "rs08" (domain "lapsed.simplex") + resp `shouldBe` Right (ERR (NAME NOT_FOUND)) + testRslvBackendHttpErr :: IO () testRslvBackendHttpErr = withResolverServer (status502, "{}") $ diff --git a/tests/SMPNamesTests.hs b/tests/SMPNamesTests.hs index 0101a40a7..783a5d4e3 100644 --- a/tests/SMPNamesTests.hs +++ b/tests/SMPNamesTests.hs @@ -13,7 +13,7 @@ import Data.IORef (readIORef) import Data.List (sort) import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) -import Network.HTTP.Types (status200, status400, status404, status500, status502) +import Network.HTTP.Types (status200, status400, status404, status410, status500, status502) import NamesResolverServer (resolveResp, testNamesConfig, withResolverServer, withResolverServerDelayed) import Simplex.Messaging.Encoding (smpDecode, smpEncode) import Simplex.Messaging.Encoding.String (strDecode) @@ -156,6 +156,14 @@ resolverSpec = do env <- newNamesEnv (testNamesConfig port) resolveName env aliceDomain `shouldReturn` Left NOT_FOUND + it "returns NOT_FOUND on 410 (registration lapsed)" $ + -- A lapsed name is a correct answer, not a resolver failure: RESOLVER + -- would make the client abort domain verification instead of reporting + -- the name as unverified. + withResolverServer (resolveResp status410 "{}") $ \port _ -> do + env <- newNamesEnv (testNamesConfig port) + resolveName env aliceDomain `shouldReturn` Left NOT_FOUND + it "returns RESOLVER on 502 (upstream failure)" $ withResolverServer (resolveResp status502 "{}") $ \port _ -> do env <- newNamesEnv (testNamesConfig port)