I'm using Zalando's Problem library and am running in the following problem (pun intended):
Everything works fine for problems thrown from normal controllers. In this case I have a custom Spring filter. If I throw a problem from the filter, the response is 500 error (shown using the standard spring error page), and not a 400 error as indicated in the problem. With other words, the exception is thrown like a normal exception, instead of being correctly serialised as a JSON response.
How can I make sure problems thrown from filter's are also correctly handled/serialised?
My code:
@Component
class UserVerifiedFilter : OncePerRequestFilter() {
@Throws(ServletException::class, IOException::class)
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
) {
// ...
throw Problem.builder()
.withType(URI.create("https://example.org/email-unverified"))
.withTitle("Email unverified")
.withStatus(Status.BAD_REQUEST)
.withDetail("Email needs to verified to use this endpoint")
.build()
}
}
@RestControllerAdvice
class ControllerExceptionHandler : ProblemHandling, SecurityAdviceTrait
CodePudding user response:
Managed to solve this by adding another filter, as the first one in the chain.
This filter catches any exception and manually propagates it to the configured exception handlers.
@Component
class FilterExceptionHandler : OncePerRequestFilter() {
@Autowired
private lateinit var resolver: HandlerExceptionResolver
private val logger = LoggerFactory.getLogger(javaClass)
@Throws(ServletException::class, IOException::class)
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
) {
try {
filterChain.doFilter(request, response)
} catch (exception: Exception) {
logger.error("Spring Security filter chain exception : {}", exception)
resolver.resolveException(request, response, null, exception)
}
}
}