Apache 2.4.6 - 发送 GZIP 内容有时会导致 "read more bytes of request body than expected"
Apache 2.4.6 - Sending GZIP content SOMETIMES results in "read more bytes of request body than expected"
我们正在尝试通过 mod_proxy 的 ProxyPass 和 ProxyPassReverse 指令将 GZIP 内容发送给您托管在 Apache 2 后面的 Tomcat 上的 Web 应用程序。大多数情况下这是可行的,但有时 Apache 拒绝这些包,我们在 Apache 错误日志中收到以下错误:
[proxy_http:error] ... AH01086: read more bytes of request body than expected (got 16384, expected 1562)
[proxy_http:error] ... AH01097: pass request body failed to x.x.x.x:8080 (x.x.x.x) from x (x.x.x.x)
发送数据的代码基于 HttpsURLConnection 并从 Android 设备执行。它看起来像这样:
URL url = new URL(Constants.URL);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setUseCaches(false);
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestProperty("Content-Encoding", "gzip");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("User-Agent", "MyApp 1.0");
OutputStream outputStream = con.getOutputStream();
outputStream.write( zipStringToBytes("Some possibly long content.") );
outputStream.flush();
outputStream.close();
int responseCode = con.getResponseCode();
这是创建 GZIP 字符串的函数:
private static byte[] zipStringToBytes(String input) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//use PrintStream to avod converting a String into byte array, that can cause out of memory error
final PrintStream printStream = new PrintStream(new GZIPOutputStream(bos));
printStream.print(input);
printStream.close();
byte[] retval = bos.toByteArray();
bos.close();
return retval;
}
我们还不能找出原因。特别是因为它似乎偶尔发生。这让我们认为这可能是 Content-Length 的问题,或者我们的代码一般发送数据,但我们不知道也找不到相关问题。如果您对此有任何建议,我们将不胜感激。
如果您需要更多信息,请告诉我。
更新:
我们发现,预期大小始终相同:16384 但预期大小有所不同。也许这有帮助。
更新二:
我们目前禁用了分块模式:
con.setChunkedStreamingMode ( 0 )
这似乎有帮助。任何人都可以解释这是否是一个解决方案以及为什么它是一个。谢谢
好的,现在我们可以通过禁用以分块模式发送数据来解决问题。
con.setChunkedStreamingMode ( 0 )
虽然我们对这解决问题的原因有一些想法,但我们还没有提出深入的解释。
只要没有人有更好的解决方案或解释,我接受这个解决方案
我们正在尝试通过 mod_proxy 的 ProxyPass 和 ProxyPassReverse 指令将 GZIP 内容发送给您托管在 Apache 2 后面的 Tomcat 上的 Web 应用程序。大多数情况下这是可行的,但有时 Apache 拒绝这些包,我们在 Apache 错误日志中收到以下错误:
[proxy_http:error] ... AH01086: read more bytes of request body than expected (got 16384, expected 1562)
[proxy_http:error] ... AH01097: pass request body failed to x.x.x.x:8080 (x.x.x.x) from x (x.x.x.x)
发送数据的代码基于 HttpsURLConnection 并从 Android 设备执行。它看起来像这样:
URL url = new URL(Constants.URL);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setUseCaches(false);
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestProperty("Content-Encoding", "gzip");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("User-Agent", "MyApp 1.0");
OutputStream outputStream = con.getOutputStream();
outputStream.write( zipStringToBytes("Some possibly long content.") );
outputStream.flush();
outputStream.close();
int responseCode = con.getResponseCode();
这是创建 GZIP 字符串的函数:
private static byte[] zipStringToBytes(String input) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//use PrintStream to avod converting a String into byte array, that can cause out of memory error
final PrintStream printStream = new PrintStream(new GZIPOutputStream(bos));
printStream.print(input);
printStream.close();
byte[] retval = bos.toByteArray();
bos.close();
return retval;
}
我们还不能找出原因。特别是因为它似乎偶尔发生。这让我们认为这可能是 Content-Length 的问题,或者我们的代码一般发送数据,但我们不知道也找不到相关问题。如果您对此有任何建议,我们将不胜感激。
如果您需要更多信息,请告诉我。
更新: 我们发现,预期大小始终相同:16384 但预期大小有所不同。也许这有帮助。
更新二: 我们目前禁用了分块模式: con.setChunkedStreamingMode ( 0 ) 这似乎有帮助。任何人都可以解释这是否是一个解决方案以及为什么它是一个。谢谢
好的,现在我们可以通过禁用以分块模式发送数据来解决问题。
con.setChunkedStreamingMode ( 0 )
虽然我们对这解决问题的原因有一些想法,但我们还没有提出深入的解释。
只要没有人有更好的解决方案或解释,我接受这个解决方案