【问题标题】:Appengine not encoding request body in UTF-8Appengine 未以 UTF-8 编码请求正文
【发布时间】:2015-11-20 09:26:26
【问题描述】:

Appengine 在读取请求正文时不尊重req.setCharacterEncoding('UTF-8')

这就是我阅读请求正文的方式

StringBuilder sb = new StringBuilder();
BufferedReader reader;

req.setCharacterEncoding("UTF-8");
reader = req.getReader();

String line;
while ((line = reader.readLine()) != null) {
    sb.append(line).append('\n');
}
reader.close();

// parse body as JSON
data = new JSONObject(sb.toString());

运行本地测试服务器(mvn appengine:devserver)时正确解析非英文字符的请求,但推送到生产的版本不解析非英文字符(mvn appengine:update);它们被读作?。这种差异是我真正感到困惑的地方。

我也尝试过设置环境变量,比如

<env-variables>
    <env-var name="DEFAULT_ENCODING" value="UTF-8" />
</env-variables> 

appengine-web.xml,但这不会改变任何事情。

什么可能导致 prod 服务器无法解析非英文字符?

【问题讨论】:

  • 您是否在 req.setCharacterEncoding 调用之前执行了对 req.getParameter...() 的任何调用?众所周知,这会导致 req 正文被完全解析,并且是导致 setCharacterEncoding 非常脆弱的因素之一。

标签: google-app-engine


【解决方案1】:

我真的不知道为什么它不能正确解析身体。在将其传递到我的后端进行进一步处理之前,我需要解析主体以对其进行验证。因此,我没有在 GAE 中解析它,而是将正文作为字节数组转发到后端,并让我的后端处理验证。这是我能找到的唯一可行的解​​决方案。

【讨论】:

  • 这似乎是一个更强大的解决方案,因为 setCharacterEncoding 具有众所周知的限制(例如,请参阅stackoverflow.com/questions/3278900/… 进行深入讨论和仅限 Tomcat 的破解方法,遗憾的是后者无济于事,除非您'正在使用 Tomcat,而在 GAE 上,你不是)。
  • 对你来说可能有点晚了,Tony,但我遇到了完全相同的问题,并发布了一个对我有用的解决方案。
【解决方案2】:

确保您在请求中正确设置了 content-type 标头 - 在客户端,如下所示:

requestBuilder.setHeader("Content-type", "application/json; charset=utf-8");

【讨论】:

    【解决方案3】:

    我遇到了类似的问题,这是对我有用的解决方案。我学到的是,当字符串完全构建(或附加到字符串构建器)时,为时已晚,因为您需要在读取字节和构建字符串时指定字符集。

    request.setCharacterEncoding 在这方面效果不佳,原因我不确定。

    我使用的替代方法是:

        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        String body = stringBuilder.toString();
    

    我直接从请求中获取字节输入流,并使用 BufferedReader 从该流中读取字符。我在这里指定了字符集,这使我可以构建字符串,同时在各自的字符集中进行解码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 1970-01-01
      • 2015-07-09
      • 2014-08-02
      • 1970-01-01
      • 2014-10-18
      相关资源
      最近更新 更多