AppEngine:将请求转发到 static-content

AppEngine: forwarding request to static-content

为了优化缓存,我将时间戳添加到图像的 src 值等,例如<img src="/static/img/foo.1456871418309.png"/>.

然后我创建了一个 servlet 过滤器,它再次删除了时间戳,然后将请求转发到资源。 request.getRequestDispatcher (urlWithoutTimestamp).forward(request, response).

并且在 appengine-web.xml 中我指定缓存文件一年。

<static-files>
    <include path="/static/**" expiration="365d" />
</static-files>

我认为,这样一来,用户将始终获得最新版本,并且可以将其缓存直到存在更新版本,而无需通过 HTTP 对其进行测试。

在本地主机上(运行 作为 Web 应用程序)这工作正常,HTTP 响应具有预期的缓存 headers:

Cache-Control:"public, max-age=31536000"
Expires:"Wed, 01 Mar 2017 22:54:32 GMT"

然而,当我在 App Engine 服务器上部署整个东西时,响应具有此缓存 header(并且没有“过期”):

Cache-Control:"private"

我没有转发请求,而是尝试在 HttpServletRequestWrapper 上调用 FilterChain 来修改 getRequestURI、getRequestURL、getServletPath。这导致了同样糟糕的结果。

我该如何做对?

更新:

再想一想,我想转发到 static-content 可能是不可能的,因为转发总是在本地服务器上完成,而 static-content 很可能在另一台机器上提供服务。

但至少我能够用我的过滤器解决我的 HTTP header 问题:

  1. 我没有转发请求,而是使用 HttpServletRequestWrapper(见上文)从请求中删除时间戳。
  2. 然后我根据修改后的请求调用 chain.doFilter。
  3. 最后我在响应上设置了缓存 headers。

在生产环境中,您将无法拦截静态文件流量。 Google App Engine 为您处理静态文件,基本上提供了一种 CDN。

我引用 https://cloud.google.com/appengine/docs/java/config/webxml#Filters

上的注释

Filters are not invoked on static assets, even if the path matches a filter-mapping pattern. Static files are served directly to the browser.

除了更改文件名和使用过滤器之外,您还可以引用添加了时间戳作为请求参数的实际静态文件。

而不是:

<img src="/static/img/foo.1456871418309.png"/>

使用以下架构:

<img src="/static/img/foo.png?r=1456871418309"/>

对于静态文件,此类参数将被忽略。但是对于浏览器来说,每次都是一个新的URL,因此会从服务器请求它。