在泽西岛处理不匹配的内容类型
Handling mismatching Content-Type in Jersey
我不断收到以下形式的错误:
java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
所以我尝试防御这个错误,如下:
@Path("auth")
@Produces(MediaType.APPLICATION_JSON)
public class Auth {
@POST
@Path("login")
@Consumes(MediaType.WILDCARD)
public Response create()
{
return Response.status(Status.UNSUPPORTED_MEDIA_TYPE).build();
}
@POST
@Path("login")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response create(@Valid @NotNull @FormParam("username") final String username,
@Valid @NotNull @FormParam("password") final String password)
{
但是,这并不能解决问题。生成的 FINE 日志消息非常垃圾。
我有两个问题:
- 为什么当 Content-Type 为空时不调用更通用的方法?
- 当实际方法与其@Consumes 不匹配时,如何防止调用实际方法以避免日志垃圾邮件?
环境是运行Grizzly 2.3.28,Jersey 2.25.1,MOXy 2.7.1
我认为如果您制作自定义注释来验证内容类型并且只接受 MediaType.APPLICATION_FORM_URLENCODED
,您就可以让它工作
如果 MediaType.APPLICATION_FORM_URLENCODED
内容类型不存在,您可以使用 ContainerRequestFilter
读取 headers 和 return 400 错误请求。
声明注解接口
@NameBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface ContentTypeFilterAnnotation {}
将其实现为 ContainerRequestFilter
@Provider
@ContentTypeFilterAnnotation
public class ContentTypeFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
MultivaluedMap<String,String> headers = requestContext.getHeaders();
List<String> contentType = headers.get(HttpHeaders.CONTENT_TYPE);
// if MediaType.APPLICATION_FORM_URLENCODED is not present in the content type header, return a 400
if(contentType == null || !contentType.contains(MediaType.APPLICATION_FORM_URLENCODED)) {
// build your error as you want it
Response.ResponseBuilder responseBuilder = Response.serverError();
Response response = responseBuilder.status(Response.Status.BAD_REQUEST).build();
requestContext.abortWith(response);
}
}
}
然后将其应用到您的端点
@POST
@Path("login")
@ContentTypeFilterAnnotation
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response create(@Valid @NotNull @FormParam("username") final String username,
@Valid @NotNull @FormParam("password") final String password) {
...
}
如果内容类型不是 MediaType.APPLICATION_FORM_URLENCODED
。
,这应该可以防止 Jersey 尝试获取表单参数
我不断收到以下形式的错误:
java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded
所以我尝试防御这个错误,如下:
@Path("auth")
@Produces(MediaType.APPLICATION_JSON)
public class Auth {
@POST
@Path("login")
@Consumes(MediaType.WILDCARD)
public Response create()
{
return Response.status(Status.UNSUPPORTED_MEDIA_TYPE).build();
}
@POST
@Path("login")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response create(@Valid @NotNull @FormParam("username") final String username,
@Valid @NotNull @FormParam("password") final String password)
{
但是,这并不能解决问题。生成的 FINE 日志消息非常垃圾。
我有两个问题:
- 为什么当 Content-Type 为空时不调用更通用的方法?
- 当实际方法与其@Consumes 不匹配时,如何防止调用实际方法以避免日志垃圾邮件?
环境是运行Grizzly 2.3.28,Jersey 2.25.1,MOXy 2.7.1
我认为如果您制作自定义注释来验证内容类型并且只接受 MediaType.APPLICATION_FORM_URLENCODED
如果 MediaType.APPLICATION_FORM_URLENCODED
内容类型不存在,您可以使用 ContainerRequestFilter
读取 headers 和 return 400 错误请求。
声明注解接口
@NameBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface ContentTypeFilterAnnotation {}
将其实现为 ContainerRequestFilter
@Provider
@ContentTypeFilterAnnotation
public class ContentTypeFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
MultivaluedMap<String,String> headers = requestContext.getHeaders();
List<String> contentType = headers.get(HttpHeaders.CONTENT_TYPE);
// if MediaType.APPLICATION_FORM_URLENCODED is not present in the content type header, return a 400
if(contentType == null || !contentType.contains(MediaType.APPLICATION_FORM_URLENCODED)) {
// build your error as you want it
Response.ResponseBuilder responseBuilder = Response.serverError();
Response response = responseBuilder.status(Response.Status.BAD_REQUEST).build();
requestContext.abortWith(response);
}
}
}
然后将其应用到您的端点
@POST
@Path("login")
@ContentTypeFilterAnnotation
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response create(@Valid @NotNull @FormParam("username") final String username,
@Valid @NotNull @FormParam("password") final String password) {
...
}
如果内容类型不是 MediaType.APPLICATION_FORM_URLENCODED
。