代码之家  ›  专栏  ›  技术社区  ›  menteith

作为主体,HttpServletRequest总是返回CoyoteInputStream,而不是实际的主体

  •  0
  • menteith  · 技术社区  · 8 年前

    我正在尝试编写一个方法来检查用户凭据以及这些凭据是否正确,并解析发送的JSON。它工作正常,但我无法访问JSON。在我的代码中有一个命令 InputStream inputStream = request.getInputStream(); 应该读取JSON,但每次返回时 org.apache.catalina.connector.CoyoteInputStream@3f1e9348 。请查看我的代码:

    @POST
    @Path("auth")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_HTML)
    public String controller(@Context HttpServletRequest request) {
    
    
        String authorization = request.getHeader("Authorization");
        if (authorization == null) {
            authorization = request.getHeader("authorization");
        }
    
        String basicHeader = "basic";
        if (authorization != null && authorization.toLowerCase().startsWith(basicHeader)) {
            String base64Credentials = authorization.substring(basicHeader.length()).trim();
            String credentials = new String(Base64.getDecoder().decode(base64Credentials),
                    Charset.forName("UTF-8"));
            String[] values = credentials.split(":", 2);
        }
    
        try {
            InputStream inputStream = request.getInputStream();
            System.out.println(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    当我尝试使用 request.getReader() 我得到了臭名昭著的 IllegalStateException: getInputStream() has already been called for this request 例外请参阅相关代码:

    if ("POST".equalsIgnoreCase(request.getMethod()))
            {
                try {
                    String req = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    

    我使用curl发送 POST :

    curl -u myusername:mypasswor -H "Content-Type: application/json"
    -X POST -d '{"username":"xyz","password":"xyz"}' localhost
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   ernest_k Petronella    8 年前

    可以通过在方法上声明参数来获取正文内容:

    public String controller(String body, @Context HttpServletRequest request) 
    

    但您也可以让JAX-RS实现将JSON反序列化为您想要的类型:

    public String controller(MyExpectedType body, @Context HttpServletRequest request) 
    

    这应该是可行的,因为您已经声明了预期的内容类型,假设您有一个适用的提供者(如jackson jaxrs…)。

    关于输入流错误:这可能是因为容器JAXRS实现已经解析了请求。

    但是,如果要在普通场景中处理它,例如在servlet中,您仍然需要纠正读取它的方式:

    的文档 getInputStream 国家:

    使用ServletInputStream以二进制数据的形式检索请求正文。可以调用此方法或getReader()来读取正文,但不能同时调用两者。

    这意味着要获取客户端在正文中发送的内容,您需要读取流:

    String body = request.getReader().lines()
                          .collect(Collectors.joining("\n"));
    

    您还可以使用 Stream -基于API:

    byte[] bytes = new byte[request.getContentLength()];
    request.getInputStream().read(bytes);
    String body = new String(bytes); //you may need to specify the character set
    

    实际的输入流类是基于实现的(由容器提供),因此您不必担心 CoyoteInputStream