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

问题描述 投票:0回答:2

我正在尝试使用 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)

从代码片段中可以看出,我尝试重置响应,但没有结果。 我还尝试修改

Accept
Content-Type
标头,但没有成功:

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

知道为什么会发生这种情况以及如何避免吗?

注意:我在客户端使用 Angular。据我所知,

HttpServletResponse#sendError
将内容类型设置为
text/html
,保留 cookie 和其他标头不变。这会是一个问题吗?

编辑: 我什至尝试抛出异常而不是使用

HttpServletResponse#sendError
,并单独处理它,但最终结果是相同的。

例如:

@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);
}
java spring spring-mvc spring-boot
2个回答
0
投票

我相信问题是您映射到

/api/authenticate
的请求要么不期望
text/html
,要么您发送了错误类型的请求(即
GET
而不是
POST
等)

您说过 Angular 正在发送

text/html
,考虑到与身份验证端点相关的通常默认值,它可能需要
application/x-www-form-urlencoded
数据。因此,Spring 正在拦截一个它没有映射的
Content-Type
并进行 406'ing。


0
投票

我能够通过使用

HttpServletResponse#setStatus

解决这个问题
© www.soinside.com 2019 - 2024. All rights reserved.