【问题标题】:Jetty respond with status 200 instead of 304 while using http2使用 http2 时,Jetty 以状态 200 而不是 304 响应
【发布时间】:2016-09-09 18:16:51
【问题描述】:

我只是构建了一个小 PoC,在其中我使用带有 http/2 的 Jetty 9.3.9.M1 嵌入式服务器和 PushBuilder API 以及 Apache Wicket 将资源推送到客户端。

我使用以下服务器设置:

Server server = new Server();

// HTTP Configuration
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);
http_config.setSendXPoweredBy(true);
http_config.setSendServerVersion(true);

// keytool -keystore keystore -alias jetty -genkey -keyalg RSA
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(new File(".","keystore").getCanonicalPath());
sslContextFactory.setKeyStorePassword("123456789");
sslContextFactory.setKeyManagerPassword("123456789");
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
sslContextFactory.setUseCipherSuitesOrder(true);

// HTTPS Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());

// HTTP Connector
ServerConnector http1 = new ServerConnector(server, new HttpConnectionFactory(http_config),
    new HTTP2CServerConnectionFactory(http_config));
http1.setPort(8080);
server.addConnector(http1);

// HTTP/2 Connection Factory
HTTP2ServerConnectionFactory http2 = new HTTP2ServerConnectionFactory(https_config);

NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
alpn.setDefaultProtocol(http1.getDefaultProtocol());

// SSL Connection Factory
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());

// HTTP/2 Connector
ServerConnector http2Connector = new ServerConnector(server, ssl, alpn, http2,
    new HttpConnectionFactory(https_config));
http2Connector.setPort(8443);
server.addConnector(http2Connector);

WebAppContext webAppContext = new WebAppContext();
webAppContext.setServer(server);
webAppContext.setContextPath("/");
webAppContext.setWar("src/main/webapp");
server.setHandler(webAppContext);

ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.addHandler(webAppContext);
server.setHandler(contexts);

ALPN.debug = false;

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

现在我面临的问题是,当我向这样的资源发出 http/1.1 请求时:

http://127.0.0.1:8080/wicket/resource/de.jetty.wicket.http2.example.resources.TestResourceReference/TestResourceReference-ver-1463040221000.css

第二次请求后chrome调试器中显示状态码304

如果我对同一资源发出 http/2.0 请求:

https://127.0.0.1:8443/wicket/resource/de.jetty.wicket.http2.example.resources.TestResourceReference/TestResourceReference-ver-1463040221000.css

每个请求都会显示状态码 200 - 客户端似乎没有缓存它。

这里是 git 项目的链接:https://github.com/klopfdreh/jetty-http2-example

提前致以诚挚的问候和感谢。

【问题讨论】:

  • 尝试使用 HTTPS 和 1.1。
  • 当我将 HTTPS 与 http/1.1 一起使用时,它也可以正常工作。在第二次请求之后,资源被缓存,并且 304 被打印为状态码。我只更改了 SslConnectionFactory 的构造函数,并将 http1.getDefaultProtocol 作为第二个参数。
  • 你是推送css还是直接使用浏览器请求?
  • 我在 html 中使用链接标签,在服务器端我将资源推送到相同的位置(与 href 中相同的上下文相对路径) - 所以 PushBuilder 和 href 的路径是一样的。
  • @sbordet:对这个话题有什么建议吗?这只是一个假设,但可能是服务器发送了 PUSH_PROMISE 而没有监听 RST_STREAM 以跳过即将以正确方式推送的资源?

标签: java wicket embedded-jetty http2


【解决方案1】:

这个问题已经在 github 上作为一个 issue 讨论并解决了。

看看这里:

https://github.com/eclipse/jetty.project/issues/801

获取相关答案。

总结:

问题是对 PushBuilder API 的误解。如果向索引页面发出请求,则有关此页面的缓存信息将用于确定是否要推送更多资源。大多数情况下,标题项“If-Modified-Since”用于检测是否需要进一步的推送操作。

所以应用程序必须提供关于缓存的逻辑。

最简单的实现是查看索引页面请求的“If-Modified-Since”标头是否在索引页面文件本身的最后修改日期之前。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-28
    • 2017-12-01
    • 1970-01-01
    • 2011-08-13
    相关资源
    最近更新 更多