无法从 HttpServletRequest 获取数据

Posted

技术标签:

【中文标题】无法从 HttpServletRequest 获取数据【英文标题】:Not able to get data from HttpServletRequest 【发布时间】:2020-11-04 07:31:03 【问题描述】:

我看过很多关于这个问题的旧帖子,但我没有成功。

我创建了一个带有多个处理程序的码头服务器:https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java。我有一个用于 http 的处理程序和另一个用于 https 的处理程序。处理程序扩展了 AbstractHandler 并且只实现了 handle() 方法。

我能够使用 Postman 访问两个处理程序(我可以通过日志记录看到)发送请求和数据,但我有 2 个问题。

    无论我使用 POST、PUT 还是 GET,HttpServletRequest.getMethod() 总是返回“GET”。 我不知道如何通过 POST 获取数据。即使 HttpServletRequest.getReader() 不为空,我只是没有得到任何数据。 我在这里添加了一堆登录以查看发生了什么。希望这会有所帮助,因为它对我没有帮助。
 public class MyHandler extends AbstractHandler 
    
    private static Logger logger = new L4Logger(MyHandler.class);

    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException 
        logger.info("MyHandler", "handle request " + request.getMethod() + " for path " + request.getContextPath());
        
        logger.info("MyHandler", "content length " + request.getContentLength());
        
        Enumeration<String> e = request.getParameterNames();
        Collections.list(e).forEach(s -> logger.info("MyHandler", "handle e " + s););
        
        Enumeration<String> a = request.getAttributeNames();
        Collections.list(a).forEach(s -> logger.info("MyHandler", "handle a " + s););
        
        if (request.getReader() == null) 
            logger.info("MyHandler", "handle request request.getReader() == null");
         else 
            logger.info("MyHandler", "handle request request.getReader() != null");
        
        
        if (request.getContextPath().equalsIgnoreCase("/run")) 
            logger.info("MyHandler", "handle request run");
            String cmdString = getBody(request);
            logger.info("MyHandler", "handle run data " + cmdString);
        
        
        response.setStatus(HttpServletResponse.SC_OK);
        baseRequest.setHandled(true);
    
    
    private String getBody(HttpServletRequest request) throws IOException 
        StringBuilder buffer = new StringBuilder();
        BufferedReader reader = request.getReader();
        
        String line;
        while ((line = reader.readLine()) != null) 
            buffer.append(line);
        
        return buffer.toString();
    

用一些 json 数据发布我的服务器,日志输出如下所示:

[handle request GET for path /run]
 [content length -1]
 [handle a javax.servlet.request.key_size]
 [handle a org.eclipse.jetty.servlet.request.ssl_session]
 [handle a javax.servlet.request.X509Certificate]
 [handle a javax.servlet.request.cipher_suite]
 [handle a javax.servlet.request.ssl_session_id]
 [handle request request.getReader() != null]
 [handle request run]
 [handle run data ]

最后,这是从 Postman 导出的 cURL 命令:

curl --location --request POST 'https://localhost:7777/run' --header 'Content-Type: application/json' --header 'Cookie: ssoLang=en' --data-raw '["cmd":"ls","args":"/proc"]'

【问题讨论】:

将详细输出添加到 curl 行 curl -vvvv ...,再次运行它,然后使用它产生的输出编辑您的问题。它可以揭示一些有用的东西。 (就像它没有通过 POST 请求正确地跟随重定向)。 经过多次反复试验和挫折后,我放弃了这种方法并使用此处描述的 RESTful 解决方案:***.com/questions/38206312/…。这个解决方案足以满足我的需要,我在几个小时内就完成了工作,因此我放弃了最初的方法。 【参考方案1】:

-1 的Content-Length 是正在发生的事情的潜在迹象。

Content-Type 标头还可以很好地控制此处的行为。

转储/记录所有请求标头,查找Content-LengthTransfer-EncodingContent-Encoding 等...几乎所有控制请求正文内容处置的相关标头。

示例:验证您的请求标头实际上是Content-Type: application/json

您可以使用curl -vvvv 执行此操作,以便在命令行上转储请求/响应标头。

您可以在服务器端使用 ...

logger.info("MyHandler", "request content-type: " + request.getHeader("Content-Type"));

如果不是您所期望的,那么很可能是标准 Servlet 行为。

当您使用以下任何一种方法时...

HttpServletRequest.getParameter(String name) HttpServletRequest.getParameterMap() HttpServletRequest.getParameterNames() HttpServletRequest.getParameterValues(String name) HttpServletRequest.getParts() HttpServletRequest.getPart(String name)

并且请求使用POST 方法和特殊的Content-Type 值...

application/x-www-form-urlencodedmultipart/form-data(以及定义了 javax.servlet.MultipartConfigElement 的端点)。

那么你也在阅读正文内容。

在这些方法调用之后,请求中没有数据可供读取。

【讨论】:

这快把我逼疯了。我使用您建议的调试从 cygwin 运行 curl,现在我看到:~~~ [Content-Type, application/json] [request content-type: application/json length -1] [method POST] [handle run data] ~~~ 虽然我没有得到数据,但方法是POST,内容是JSON。我从邮递员那里重新运行了同样的事情,它又回到了 GET 并且内容类型为空。 ~~~ [请求内容类型:空长度-1] [方法GET] [处理运行数据] ~~~

以上是关于无法从 HttpServletRequest 获取数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从 HttpServletRequest 获取完整的 url? [复制]

从 HttpServletRequest 获取 AsyncContext

从 HttpServletRequest 获取 XML 并用于端点

如何从 HttpServletRequest 获取请求 url [重复]

Java拦截器HandlerInterceptor重写preHandle方法时HttpServletRequest无法获取自定义请求头参数问题

Java拦截器HandlerInterceptor重写preHandle方法时HttpServletRequest无法获取自定义请求头参数问题