Spring的HandlerInterceptor发送错误导致406(不可接受)响应

时间:2016-03-28 15:16:51

标签: java spring spring-mvc spring-boot

我正在尝试使用Spring的HandlerInterceptorAdapter来处理为以下休息端点安排应用程序维护的情况:/api/authentication

所以我通过扩展HandlerInterceptorAdapter创建了一个拦截器:

public class MigrationStateInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(someLogic) {
            return true
        }

        response.reset();
        response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value());
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

然后我将其添加到我的InterceptorRegistry

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MigrationStateInterceptor()).addPathPatterns("/api/authentication");
}

问题是,我收到503 (Service Unavailable)

,而不是在客户端收到Failed to load resource: the server responded with a status of 406 (Not Acceptable)错误

正如在代码片段中可以看到的,我尝试重置响应,但没有结果。 我还尝试修改AcceptContent-Type标题,但没有运气:

response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.addHeader("Accept", "text/plain");

知道为什么会这样,以及如何避免这种情况?

注意:我在客户端使用Angular。从我看到的内容HttpServletResponse#sendError将内容类型设置为text/html,不会修改Cookie和其他标头。这可能是个问题吗?

修改: 我甚至尝试抛出异常而不是使用HttpServletResponse#sendError,并单独处理,但最终结果是相同的。

E.g:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if (some logic) {
        return true;
    }
    throw new MigrationStateException("Migration process is disabled");
}

 @ExceptionHandler(MigrationStateException.class)
public ResponseEntity<String> migrationStateError(MigrationStateException e) {
    return new ResponseEntity<>(e.getMessage(), HttpStatus.SERVICE_UNAVAILABLE);
}

1 个答案:

答案 0 :(得分:0)

我认为问题是您要映射到/api/authenticate的请求要么不期望text/html,要么发送错误类型的请求(即GET而不是POST 1}}等等。)

你声明angular发送text/html,给定与验证端点相关的常规默认值,它可能期望application/x-www-form-urlencoded数据。因此,Spring正在拦截它没有映射的Content-Type和406'。