Usando halt () do Scalatra em um bloco try / catch

Entre Scala Optione lift’s Box(eu uso lift-mongorecord com Scalatra), raramente uso try {...} catch {...}em Scala. Mas, em uma ocasião, acabei usando-o para lidar com qualquer problema que pudesse surgir ao falar com um serviço externo.

try {
// call external service
} catch {
case e => halt(500, e.getMessage)
}

As coisas funcionaram bem no início. Posteriormente, precisei adicionar uma verificação de autorização no try {...}bloco, o que causava uma halt()falha na verificação.

try {
// call external service
if (!authorized) {
halt
(401, "Authorization required")
}
} catch {
case e => halt(500, e.getMessage)
}

Para minha surpresa, meu aplicativo retornou 500 em vez do 401 esperado se o serviço externo retornou algo que falhou na verificação de autorização. Depois de me intrigar um pouco, me lembrei de ter lido as obras de Scalatra lançando uma exceção sob o capô. (Na verdade, ele lança uma subclasse de , mais sobre isso em breve.) Quando o interno é chamado, o 401 é capturado pelo bloco e convertido em 500.halt()Throwablehalt()catch {...}

Para fazer isso funcionar, eu teria que alterar meu cobertor catchpara procurar o que quer que fosse halt()e deixar que borbulhasse. Mas o que halt()joga? Acontece que halt()lança a Throwable, que é a superclasse de Exception. Como observado no este post , apenas a subclasses de Exceptiondeve ser tratado no catch {...}bloco, que permite que o interior halt()é Throwablea borbulhar.

try {
// call external service
if (!authorized) {
halt
(401, "Authorization required")
}
} catch {
// only handle subclasses of Exception
case e:Exception => halt(500, e.getMessage)
}

Para aqueles de vocês que estão curiosos, halt()realmente lança um HaltExceptionque se estende ControlThrowable.

Esta dica foi republicada do meu blog, jontai.me