如何阻止GET API接收不必要请求体并返回400 Bad Request错误
问题描述
我有一个通过路径参数传递员工ID返回员工详情的GET API,示例URL为http://localhost:8080/employee/155(其中155是员工ID),API会返回对应ID的员工信息。控制器代码如下:
@GET @Produces({MediaType.APPLICATION_JSON}) @Path("/{employee-id}") public Response getEmployeeDetails(@PathParam("employee-id") int empId);
当前存在的问题:即使该API收到不必要的请求体,仍会正常返回员工详情。需要实现拦截此类请求,当发送不必要请求体时返回400 Bad Request错误。例如:
URI -
http://localhost:8080/employee/155
Request -{"name":"hello","position":"tech"}
当前Response - 200 OK 和员工ID 155的详情
期望Response - 400 Bad Request
解决方案
方法1:全局拦截(推荐)
创建一个JAX-RS过滤器,拦截所有带请求体的GET请求,直接返回400错误:
import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.core.Response; import javax.ws.rs.ext.Provider; import java.io.IOException; @Provider public class GetRequestBodyBlocker implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) throws IOException { if ("GET".equalsIgnoreCase(requestContext.getMethod()) && requestContext.hasEntity()) { requestContext.abortWith( Response.status(Response.Status.BAD_REQUEST) .entity("GET请求不允许携带请求体") .build() ); } } }
把这个类放到项目的JAX-RS扫描路径下,就会自动生效,所有带请求体的GET请求都会被拦截。
方法2:针对单个API处理
如果只想限制这个员工详情接口,可以在方法里检查请求体是否存在:
@GET @Produces({MediaType.APPLICATION_JSON}) @Path("/{employee-id}") public Response getEmployeeDetails(@PathParam("employee-id") int empId, @Context HttpServletRequest request) throws IOException { // 检查请求是否有内容 if (request.getContentLength() > 0 || request.getInputStream().available() > 0) { return Response.status(Response.Status.BAD_REQUEST) .entity("GET请求不允许携带请求体") .build(); } // 原有逻辑:查询员工详情并返回 Employee emp = employeeDao.getById(empId); return Response.ok(emp).build(); }
注意:如果请求流已经被其他组件提前读取,available()可能无法准确判断,这种情况下优先用全局过滤器。
方法3:利用@Consumes注解限制
显式声明该GET接口不接受任何媒体类型,当有请求体时框架会自动返回400:
@GET @Produces({MediaType.APPLICATION_JSON}) @Path("/{employee-id}") @Consumes({}) // 空集合表示不接受任何媒体类型 public Response getEmployeeDetails(@PathParam("employee-id") int empId) { // 原有逻辑 }
这种方式简单,但不同JAX-RS实现(如Jersey、RestEasy)的兼容性可能有差异,建议测试后使用。
内容的提问来源于stack exchange,提问作者Vedha
相关产品推荐
相关产品推荐

