我正在尝试使用 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);
}
我相信问题是您映射到
/api/authenticate
的请求要么不期望text/html
,要么您发送了错误类型的请求(即GET
而不是POST
等)
您说过 Angular 正在发送
text/html
,考虑到与身份验证端点相关的通常默认值,它可能需要 application/x-www-form-urlencoded
数据。因此,Spring 正在拦截一个它没有映射的 Content-Type
并进行 406'ing。
我能够通过使用
HttpServletResponse#setStatus
解决这个问题