1

我们正在使用ETagIf-None-Matchheaders 来提高单页应用程序在初始加载时的性能。我注意到,当服务器发送重定向(303 或 302)时,Internet Explorer 的反应方式与 Firefox 和 Chrome 不同。

观察:

当服务器为给定页面发送 302 代码以指示应重新加载页面时(位置标头指向同一页面)。然后 IE 使用它的缓存版本(它发送If-None-Match并获得 304 答案),Firefox 和 Chrome 认为应该重新加载页面。

使用一个简单的服务器,该服务器始终发送相同的页面(具有弱ETag值),除了将重定向(302 代码)发送到同一页面的每个 fith 响应。

火狐:

Firefox - 网络选项卡

铬合金:

Chrome - 网络标签

互联网浏览器 11:

IE 11 - 网络选项卡

问题:

这是预期的行为吗?是否有可能强制 IE 重新加载页面?

错误的解决方案:

根据我在 StackOverflow 上阅读的答案:

我曾尝试发送ExpiresCache-Control当我发送 302 重定向请求时,IE 会:

  • 用户请求 (F5),响应是带有标头的 302 代码Expires: -1Cache-Control: must-revalidate, private
  • 请求跟随重定向,请求带有 header If-None-Match,响应是一个 304 代码。
  • 用户请求 (F5),没有标头If-None-Match,响应是 200 代码。

IE 11 - 网络选项卡

实验代码:

我改编了Jetty Hello-World示例:

package org.eclipse.jetty.embedded;

import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

public class JettyHelloWorld extends AbstractHandler {
    public static final String IF_NONE_MATCH = "If-None-Match"; //$NON-NLS-1$

    long time = new Date().getTime();
    int counter = 0;

    @Override
    public void handle(String target,
            Request baseRequest,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException,
            ServletException {

        String etag = createEtag();
        String ifNoneMatch = request.getHeader(IF_NONE_MATCH);
        boolean clientSentEtag = (ifNoneMatch != null);

        counter = counter + 1;
        System.out.print("[" + (counter % 5) + "]");
        if (counter % 5 == 0) {
            System.out.println("SEND 302 for " + request.getPathInfo());
            // response.setHeader("Expires", "-1");
            // response.setHeader("Cache-Control", "must-revalidate, private");
            response.setHeader("Location", "/");
            response.setStatus(HttpServletResponse.SC_FOUND);
            // response.sendRedirect("/");
            baseRequest.setHandled(true);
        } else if (clientSentEtag && notModified(ifNoneMatch, etag)) {
            // Check If-None-Match (Etag)
            System.out.println("SEND 304 for " + request.getPathInfo());
            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            baseRequest.setHandled(true);
        } else {
            System.out.println("SEND 200 for " + request.getPathInfo());
            response200(baseRequest, response);
        }

    }

    private void response200(Request baseRequest, HttpServletResponse response) throws IOException {
        // Declare response encoding and types
        response.setContentType("text/html; charset=utf-8");

        response.addHeader("ETag", createEtag());

        // Declare response status code
        response.setStatus(HttpServletResponse.SC_OK);

        // Write back response
        response.getWriter()
                .println("<h1>Hello World:" + time + "</h1>");

        // Inform jetty that this request has now been handled
        baseRequest.setHandled(true);
    }

    private String createEtag() {
        return "W/\"" + time + "\"";
    }

    private boolean notModified(String ifNoneMatch, String etag) {
        return (ifNoneMatch != null && etag != null && ifNoneMatch.indexOf(etag) != -1);
    }

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        server.setHandler(new JettyHelloWorld());

        server.start();
        server.join();
    }
}

依赖:

<dependency>
    <groupId>org.eclipse.jetty.aggregate</groupId>
    <artifactId>jetty-all</artifactId>
    <version>9.3.6.v20151106</version>
    <type>pom</type>
</dependency>

背景:

这个例子真的很简约。在我们的生产环境中,302 重定向是由登录模块生成的。问题是有时,IE 只是显示一个白色窗口而不是页面内容。

4

0 回答 0