【问题标题】:Jersey and @FormParam not working when charset is specified in the Content-Type在 Content-Type 中指定字符集时,Jersey 和 @FormParam 不起作用
【发布时间】:2013-07-10 06:13:31
【问题描述】:

Content-Type 标头中指定 charset 属性时,Jersey 2.0(使用 servlet 3.1)似乎无法解码参数。

例如考虑以下端点:

@POST
@Path("/hello")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response hello(@FormParam("name") String name) {
    System.out.println(name);
    return ok();
}

此 curl 请求有效:

curl -X POST -H "content-type: application/x-www-form-urlencoded" -d "name=tom" http://localhost:8080/sampleapp/hello

以下请求不起作用name 参数是null

curl -X POST -H "content-type: application/x-www-form-urlencoded; charset=UTF-8" -d "name=tom" http://localhost:8080/sampleapp/hello

我认为内容类型中的 charset=UTF-8 添加会破坏我的代码。

编辑:

我已经打开了官方票,以防这是一个错误:https://java.net/jira/browse/JERSEY-1978

【问题讨论】:

    标签: java servlets http-headers jersey jax-rs


    【解决方案1】:

    这是一个受 Carlo 帖子启发的简单解决方法。唯一的修改是匹配 ';字符集=UTF-8';否则,'multipart/form-data; boundary=...' 内容类型失败。

    // IMPLEMENTATION NOTE: Resolves an issue with FormParam processing
    // @see https://java.net/jira/browse/JERSEY-1978
    
    @Provider
    @PreMatching
    public class ContentTypeFilter implements ContainerRequestFilter {
    
        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
            MultivaluedMap<String,String> headers = requestContext.getHeaders();
            List<String> contentTypes = headers.remove(HttpHeaders.CONTENT_TYPE);
            if (contentTypes != null && !contentTypes.isEmpty()) {
                String contentType = contentTypes.get(0);
                String sanitizedContentType = contentType.replaceFirst("; charset=UTF-8", "");
                headers.add(HttpHeaders.CONTENT_TYPE, sanitizedContentType);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我认为这是一个错误。

      有一个拉取请求开放以支持此用例: https://github.com/jersey/jersey/pull/24/files

      与此同时,我建议使用过滤器来删除有问题的编码。

      编辑根据 OP cmets

      我正在考虑以下几点:

      @Provider
      @PreMatching
      public class ContentTypeFilter implements ContainerRequestFilter{
      
          @Override
          public void filter(ContainerRequestContext requestContext)
                  throws IOException {
              MultivaluedMap<String,String> headers=requestContext.getHeaders();
              List<String> contentTypes=headers.remove(HttpHeaders.CONTENT_TYPE);
              if (contentTypes!=null && !contentTypes.isEmpty()){
                  String contentType= contentTypes.get(0);
                  String sanitizedContentType=contentType.replaceFirst(";.*", "");
                  headers.add(HttpHeaders.CONTENT_TYPE, sanitizedContentType);
              }
          }
      }
      

      【讨论】:

      • 如何使用过滤器修改Content-Type 标头?
      • 我修改了答案。不过,它未经测试。
      • 在 Jersey v2.22 中解决
      猜你喜欢
      • 2011-12-19
      • 2018-02-28
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 2013-10-06
      • 2011-04-24
      相关资源
      最近更新 更多