远期Expires标头为静态内容 [英] far future Expires header for static contents

查看:82
本文介绍了远期Expires标头为静态内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这里如何写 http://developer.yahoo.com/performance/rules.html

对于静态组件:通过设置较远的Expires标头实现永不过期"策略

For static components: implement "Never expire" policy by setting far future Expires header

我可以避免使用http响应为"304"的http请求. 在正式比赛中!文档中,我可以看到如何设置缓存控制指令,但是如何设置远期Expires标头?

最好的问候尼古拉

i can gain performace avoiding http requests with a response as "304".
In official play! documentation i can see how set cache-controll directives, but how i can set far future Expires header?

best regards Nicola


编辑:感谢您的重播,现在它也可以正常工作!这里是类:


edit: thanks for the replay now it work as well! here there are the classes:

conf/routes

  # Static files
  GET /assets/stylesheets/img/:name controllers.StaticFilesController.getBoostrapImg(name)
  GET /assets/images/*name          controllers.StaticFilesController.getImg(name)
  GET /assets/stylesheets/*name     controllers.StaticFilesController.getCss(name)
  GET /assets/javascripts/*name     controllers.StaticFilesController.getJs(name)


controllers/StaticFilesController.java

package controllers;
import org.apache.http.impl.cookie.DateUtils;
import java.util.*;
import play.mvc.*;
import services.FileName;
import play.*;
public class StaticFilesController extends Controller {

private static String nextYearString = StaticFilesController
        .getNextYearAsString();

public static Result getImg(String path) {

    FileName fileName = new FileName(path);
    response().setHeader(EXPIRES, nextYearString);
    response().setContentType("image/" + fileName.extension());
    return ok(Play.application().getFile("/public/images/" + path));
}

public static Result getBoostrapImg(String path) {

    FileName fileName = new FileName(path);
    response().setHeader(EXPIRES, nextYearString);
    response().setContentType("image/" + fileName.extension());
    return ok(Play.application().getFile(
            "/public/images/" + fileName.filename() + "."
                    + fileName.extension()));
}

public static Result getCss(String path) {

    response().setHeader(EXPIRES, nextYearString);
    response().setContentType("text/css");
    return ok(Play.application().getFile("/public/stylesheets/" + path));
}

public static Result getJs(String path) {

    response().setHeader(EXPIRES, nextYearString);
    response().setContentType("application/x-javascript");
    return ok(Play.application().getFile("/public/javascripts/" + path));
}

private static String getNextYearAsString() {
    Calendar calendar = new GregorianCalendar();
    calendar.add(Calendar.YEAR, 1);
    return DateUtils.formatDate(calendar.getTime());
}
}


services/FileName.java

package services;

/**
* This class assumes that the string used to initialize fullPath has a
* directory path, filename, and extension. The methods won't work if it
* doesn't.
*/
public class FileName {
private String fullPath;
private char pathSeparator, extensionSeparator;

public FileName(String str, char sep, char ext) {
 fullPath = str;
 pathSeparator = sep;
 extensionSeparator = ext;
}

public FileName(String str)
{
  fullPath = str;
  pathSeparator = '/';
  extensionSeparator = '.';
}

public String extension() {
  int dot = fullPath.lastIndexOf(extensionSeparator);
  return fullPath.substring(dot + 1);
 }

 public String filename() { // gets filename without extension
 int dot = fullPath.lastIndexOf(extensionSeparator);
 int sep = fullPath.lastIndexOf(pathSeparator);
  return fullPath.substring(sep + 1, dot);
}

 public String path() {
  int sep = fullPath.lastIndexOf(pathSeparator);
   return fullPath.substring(0, sep);
  }
 }


还有 views/main.scala.html

 @(skin: String)(content: Html)

 <!DOCTYPE html>

 <html lang="en">
   <head>
     <meta charset="utf-8"> 
     <title>LibreTitan</title>
      <link rel="stylesheet" media="screen"    href="@routes.StaticFilesController.getCss("bootstrap/bootstrap.min.css")">
    @if(skin != null && !skin.equals("")) {
    <link rel="stylesheet" media="screen" href="@routes.StaticFilesController.getCss(skin+".min.css")">
    }
    <link rel="shortcut icon" type="image/png" href="@routes.StaticFilesController.getImg("favicon.png")">
    <script async src="@routes.StaticFilesController.getJs("jquery-1.9.0.min.js")"></script>
    <script async src="@routes.StaticFilesController.getJs("bootstrap.min.js")"></script>
</head>
<body>
    <div class="container">
        @content
     </div>
    </body>
 </html>

推荐答案

Never expire策略意味着应在响应中添加Expire标头,该标头的日期将是很远的将来,例如距现在已经10年了.您可以按照 Manipulating the response 文档中的说明在Play中轻松完成此操作.例如:

Never expire policy in this context means that should add Expire header to your response which date is in far future, for an example 10 years since now. You can easily do that in Play as described in the Manipulating the response doc. example:

public static Result index() {
    response().setHeader(EXPIRES, "Thu, 16 Feb 2023 20:00:00 GMT");
    return ok("<h1>Hello World!</h1>");
}

当然,您可以使用某种方法来动态地计算失效日期,而不是将失效日期作为String给出,您可以使用org.joda.time.DateTime(在Play中可用)及其方法进行计算,例如:

Of course instead giving expire date as a String you should use some method to calculate it dynamicaly, you can do that with org.joda.time.DateTime (available in Play) and its methods like: plusYears(int years). Most important is that should be formatted finally in RFC 1123 date format.

编辑,您当然可以返回不同类型的结果-也可以返回文档(结果"部分)中,要检查所有可用的选项,请查看以下API:

Edit, of course you can return different kinds of Results - also binary as described in the doc ('Results' section), to check all available options look into API of: play.mvc.Results it can be: ok(Content content) - typical when you render some view, ok(java.io.File content), ok(java.io.InputStream content), etc.

我绝对建议不要使用Play来投放far future static contents(以及任何其他静态的公共内容).如上所述,尽管您可以轻松做到这一点,但是恕我直言,这是对Play资源的多余浪费,因为您需要处理任何单个图像,脚本,样式等的所有请求.

I'd definitely recommend to DO NOT use Play for serving far future static contents (and any other static, public contents as well). Although you can do it easily, as described above, IMHO it's redundant waste of Play's resources as you need to handle all requests for any single image, script, style... whatever.

考虑使用通用的HTTP服务器来完成该工作(nginx,lighthttpd,Apache)或什至更好的分布式CDN.在这种情况下,您的应用程序可能会担心执行其逻辑,而不是在磁盘上搜索样式表.

Consider using common... HTTP server for that job (nginx, lighthttpd, Apache) or even better some distributed CDN. In that case your app can concern on executing its logic instead of searching the stylesheets on the disk.

PS 请记住,如果您使用Play而不是HTTP服务器,要添加从/public文件夹提供的新静态内容,则需要重新启动应用程序,因此至少确保将它们保留在应用程序之外的某个专用文件夹中,以便可以在不停止应用程序的情况下添加/删除/替换它们.

P.S. Remember that if you are using Play instead of HTTP server, for adding new static contents which are served from the /public folder you'll need to restart the application, so at least make sure that you are keeping them in some dedicated folder apart of application, so you can add/remove/replace them without stopping the application.

这篇关于远期Expires标头为静态内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆