gzip 编码响应的奇怪问题
Weird issues with gzip encoded responses
好的,所以我是 运行 我自己的 NanoHttpd 分支(一个极简主义的 java 网络服务器,尽管这个分支相当复杂),我不得不在上面实现 gzip 压缩它。
它运行良好,但结果是 Linux mint 17.1 上的 firefox 33.0 根本不会执行 gzip 压缩的 js 文件,尽管它们加载得很好而且 header 看起来不错等等. 这不会发生在与 chrome 相同的电脑上,也不会发生在我尝试过的任何其他浏览器上,但仍然是我必须修复的问题。
此外,如果我禁用 gzipping,js 资源执行得很好。我也尝试删除连接:keep-alive,但没有任何效果。
这是负责压缩的代码:
private void sendAsFixedLength(OutputStream outputStream) throws IOException {
int pending = data != null ? data.available() : 0; // This is to support partial sends, see serveFile()
headerLines.add("Content-Length: "+pending+"\r\n");
boolean acceptEncoding = shouldAcceptEnc();
if(acceptEncoding){
headerLines.add("Content-Encoding: gzip\r\n");
}
headerLines.add("\r\n");
dumpHeaderLines(outputStream);//writes header to outputStream
if(acceptEncoding)
outputStream = new java.util.zip.GZIPOutputStream(outputStream);
if (requestMethod != Method.HEAD && data != null) {
int BUFFER_SIZE = 16 * 1024;
byte[] buff = new byte[BUFFER_SIZE];
while (pending > 0) {
int read = data.read(buff, 0, ((pending > BUFFER_SIZE) ? BUFFER_SIZE : pending));
if (read <= 0) {
break;
}
outputStream.write(buff, 0, read);
pending -= read;
}
}
outputStream.flush();
outputStream.close();
}
Fwiw,我从中复制的示例没有关闭 outputStream,但是没有关闭 gzip 资源根本没有加载,而 non-gzipped 资源仍然加载正常。所以我猜这部分以某种方式关闭了。
编辑:firefox 不会给出任何错误,它只是不执行脚本,例如:
index.html:
<html><head><script src="foo.js"></script></head></html>
foo.js:
alert("foo");
不执行任何操作,尽管资源加载正常。控制台中没有警告,什么都没有。当 gzip 被禁用时和在其他浏览器上工作正常。
编辑 2:
如果我直接请求 foo.js,它加载得很好。
编辑 3:
尝试在进行 gzip 压缩 on/off 时使用 TemperData 检查响应 & headers。
唯一不同的是,当 gzipping 开启时,响应 header 中有 Content-Encoding: gzip,这并不奇怪。除此之外,100% 平等回应。
编辑 4:
事实证明,从 header 中删除 content-length 使它再次工作......不确定副作用,但至少这更好地指出了它。
我认为你的问题的原因是你正在写 Content-Length
header before 压缩数据,结果是一个不连贯的信息到浏览器。我想这取决于浏览器的实现,它以一种或另一种方式处理这种情况,而且 Firefox 似乎以严格的方式处理。
如果不知道压缩数据的大小(可以理解),最好不要写Content-Length
header,这不是必须的
好的,所以我是 运行 我自己的 NanoHttpd 分支(一个极简主义的 java 网络服务器,尽管这个分支相当复杂),我不得不在上面实现 gzip 压缩它。
它运行良好,但结果是 Linux mint 17.1 上的 firefox 33.0 根本不会执行 gzip 压缩的 js 文件,尽管它们加载得很好而且 header 看起来不错等等. 这不会发生在与 chrome 相同的电脑上,也不会发生在我尝试过的任何其他浏览器上,但仍然是我必须修复的问题。
此外,如果我禁用 gzipping,js 资源执行得很好。我也尝试删除连接:keep-alive,但没有任何效果。
这是负责压缩的代码:
private void sendAsFixedLength(OutputStream outputStream) throws IOException {
int pending = data != null ? data.available() : 0; // This is to support partial sends, see serveFile()
headerLines.add("Content-Length: "+pending+"\r\n");
boolean acceptEncoding = shouldAcceptEnc();
if(acceptEncoding){
headerLines.add("Content-Encoding: gzip\r\n");
}
headerLines.add("\r\n");
dumpHeaderLines(outputStream);//writes header to outputStream
if(acceptEncoding)
outputStream = new java.util.zip.GZIPOutputStream(outputStream);
if (requestMethod != Method.HEAD && data != null) {
int BUFFER_SIZE = 16 * 1024;
byte[] buff = new byte[BUFFER_SIZE];
while (pending > 0) {
int read = data.read(buff, 0, ((pending > BUFFER_SIZE) ? BUFFER_SIZE : pending));
if (read <= 0) {
break;
}
outputStream.write(buff, 0, read);
pending -= read;
}
}
outputStream.flush();
outputStream.close();
}
Fwiw,我从中复制的示例没有关闭 outputStream,但是没有关闭 gzip 资源根本没有加载,而 non-gzipped 资源仍然加载正常。所以我猜这部分以某种方式关闭了。
编辑:firefox 不会给出任何错误,它只是不执行脚本,例如:
index.html:
<html><head><script src="foo.js"></script></head></html>
foo.js:
alert("foo");
不执行任何操作,尽管资源加载正常。控制台中没有警告,什么都没有。当 gzip 被禁用时和在其他浏览器上工作正常。
编辑 2: 如果我直接请求 foo.js,它加载得很好。
编辑 3: 尝试在进行 gzip 压缩 on/off 时使用 TemperData 检查响应 & headers。 唯一不同的是,当 gzipping 开启时,响应 header 中有 Content-Encoding: gzip,这并不奇怪。除此之外,100% 平等回应。
编辑 4: 事实证明,从 header 中删除 content-length 使它再次工作......不确定副作用,但至少这更好地指出了它。
我认为你的问题的原因是你正在写 Content-Length
header before 压缩数据,结果是一个不连贯的信息到浏览器。我想这取决于浏览器的实现,它以一种或另一种方式处理这种情况,而且 Firefox 似乎以严格的方式处理。
如果不知道压缩数据的大小(可以理解),最好不要写Content-Length
header,这不是必须的