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

时间:2018-03-22 09:39:18

标签: java

我试图编写一个检查用户凭据的方法,如果这些是正确的解析发送的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 个答案:

答案 0 :(得分:0)

您可以通过在方法上声明参数来获取您的身体内容:

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