Spring WebFlux函数式端点遇无效媒体类型返回404,如何改为415?
如何让Spring Boot 2函数式端点返回415而非404?
你现在用的是Spring Boot 2.0.1.RELEASE的函数式端点,定义了这样的请求匹配谓词:
private RequestPredicate getByIdPredicate() { return RequestPredicates.GET("/*/{id}") .and(RequestPredicates.accept(MediaType.APPLICATION_JSON_UTF8)); }
问题是当用错误的媒体类型(比如application/invalidMediaType)调用API时,端点返回的是404,但你希望返回415 Unsupported Media Type对吧?
问题根源
当前你把路径匹配和Accept头匹配合并成了一个谓词,只有两个条件同时满足时,Spring才会认为这个端点存在。如果Accept头不匹配,Spring就找不到对应的端点,自然返回404。要返回415,得把这两个校验分开,先让路径匹配成功,再单独校验Accept头。
具体实现方案
最简单直接的方式是拆分谓词,在请求处理方法里手动校验Accept头:
- 先定义只匹配路径的谓词:
private RequestPredicate getByIdPathPredicate() { return RequestPredicates.GET("/*/{id}"); }
- 在请求处理方法中添加Accept头校验:
public Mono<ServerResponse> handleGetById(ServerRequest request) { // 检查请求的Accept头是否符合要求 List<MediaType> acceptedTypes = request.headers().accept(); if (!acceptedTypes.contains(MediaType.APPLICATION_JSON_UTF8)) { return ServerResponse.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).build(); } // 正常处理业务逻辑 String id = request.pathVariable("id"); // ... 这里写你的业务代码,比如查询数据等 return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON_UTF8) .bodyValue(yourBusinessData); }
- 注册路由时使用路径匹配谓词:
@Bean public RouterFunction<ServerResponse> routerFunction() { return RouterFunctions.route(getByIdPathPredicate(), this::handleGetById); }
为什么这样能行?
当请求路径匹配成功后,不管Accept头是否符合,都会进入handleGetById方法。这时候我们手动校验Accept头,不符合就直接返回415状态码,这样就不会出现Spring因为找不到端点而返回404的情况了。
内容的提问来源于stack exchange,提问作者Niranjan
相关产品推荐
相关产品推荐

