-
-
Save danielalexiuc/2882360 to your computer and use it in GitHub Desktop.
1003:util.StaticGzipPlugin |
package util; | |
import com.google.common.io.Files; | |
import play.Logger; | |
import play.Play; | |
import play.PlayPlugin; | |
import play.libs.MimeTypes; | |
import play.mvc.Http; | |
import play.utils.Utils; | |
import play.vfs.VirtualFile; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.io.IOException; | |
import java.nio.charset.Charset; | |
import java.util.Date; | |
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*; | |
import static util.Compression.*; | |
public class StaticGzipPlugin extends PlayPlugin { | |
@Override | |
public boolean serveStatic(VirtualFile file, Http.Request request, Http.Response response) { | |
try { | |
final File localFile = file.getRealFile(); | |
String contentType = MimeTypes.getContentType(localFile.getName(), "text/plain"); | |
// ignore images, I was having trouble when gzipping them. They probably don't need it anyway. | |
if (contentType.contains("image")) return false; | |
response.setContentTypeIfNotSet(contentType); | |
response = addEtag(request, response, localFile); | |
// minify | |
String content = minify(request, response, localFile); | |
// gzip only if supported and not excluded | |
if (isGzipSupported(request) && !isExcludedAction(request)) { | |
final ByteArrayOutputStream gzip = getGzipStream(content); | |
// set response header | |
response.setHeader("Content-Encoding", "gzip"); | |
response.setHeader("Content-Length", gzip.size() + ""); | |
response.out = gzip; | |
return true; | |
} else { | |
response.out = new ByteArrayOutputStream(content.length()); | |
response.out.write(content.getBytes()); | |
return true; | |
} | |
} catch (Exception e) { | |
Logger.error(e, "Error when Gzipping response: %s", e.getMessage()); | |
} | |
return false; | |
} | |
private String minify(Http.Request request, Http.Response response, File file) throws IOException { | |
String content = Files.toString(file, Charset.defaultCharset()); | |
if (!isExcludedAction(request)) { | |
// select compression method by contentType | |
if (response.contentType.contains("text/html")) { // could be "text/html; charset=utf-8" | |
return Compression.compressHTML(content); | |
} else if (response.contentType.contains("text/xml")) { | |
return Compression.compressXML(content); | |
} else if (response.contentType.contains("text/css")) { | |
return Compression.compressCSS(content); | |
} else if (response.contentType.contains("text/javascript") | |
|| response.contentType.contains("application/javascript")) { | |
return Compression.compressJS(content); | |
} | |
} | |
return content; | |
} | |
private static Http.Response addEtag(Http.Request request, Http.Response response, File file) { | |
if (Play.mode == Play.Mode.DEV) { | |
response.setHeader(CACHE_CONTROL, "no-cache"); | |
} else { | |
String maxAge = Play.configuration.getProperty("http.cacheControl", "3600"); | |
if (maxAge.equals("0")) { | |
response.setHeader(CACHE_CONTROL, "no-cache"); | |
} else { | |
response.setHeader(CACHE_CONTROL, "max-age=" + maxAge); | |
} | |
} | |
boolean useEtag = Play.configuration.getProperty("http.useETag", "true").equals("true"); | |
last = (file.lastModified() / 1000) * 1000 | |
final String etag = "\"" + last + "-" + file.hashCode() + "\""; | |
if (!request.isModified(etag, last)) { | |
if (request.method.equals("GET")) { | |
response.status = Http.StatusCode.NOT_MODIFIED; | |
} | |
if (useEtag) { | |
response.setHeader(ETAG, etag); | |
} | |
} else { | |
response.setHeader(LAST_MODIFIED, Utils.getHttpDateFormatter().format(new Date(last))); | |
if (useEtag) { | |
response.setHeader(ETAG, etag); | |
} | |
} | |
return response; | |
} | |
} |
Hey, there's a little bug in there: last can give you an accuracy of miliseconds, which gets truncated to seconds when passed into header. When comparing it with request.isModified(etag, last), these additional miliseconds make the file seem newer. This means that the application virtually never returns "NOT MODIFIED". Using this fixed it for me:
last = (file.lastModified() / 1000) * 1000
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
Sorry guys I didn't get any notification of your comments - do I have to star my own gist to get notifications of comments?
Thanks for the bugfix - please do whatever you like with this code.
GITHUB COMMENTING SYSTEM
ლ(ಠ益ಠლ)
Y U NO WORK CORRECTLY?
this doesn't compile
"this doesn't compile"
It has dependencies. Look at the play-minifymod. You should find everything you need to compile this.
what the heck! with Play 2.0....
response.setHeader .... should be " response().setHeader ... " I spent 15 minutes trying to debug that bad compile!
On other thoughts was that on purpose??????
@manish333999 you spent 15 minutes debugging something that wouldn't compile?
This was written for Play 1.2.4 - I haven't tried it with Play 2.
Looks like the addEtag() method causes problems with Safari. Be careful with it, or disable it until I can figure out a fix: http://stackoverflow.com/questions/16824862/heroku-hosted-html-times-out-after-1-minute-on-safari-only-every-second-time
Nice work!
I should have found this earlier.
Any license for this? I want to include it in minifymod
greets,
maklemenz