Skip to content

Instantly share code, notes, and snippets.

@nraychaudhuri
Created December 13, 2012 17:24
Show Gist options
  • Save nraychaudhuri/4278105 to your computer and use it in GitHub Desktop.
Save nraychaudhuri/4278105 to your computer and use it in GitHub Desktop.
Gzip compression of dynamic response in Play
package plugin
import play.api._
import play.api.mvc._
import play.api.http.Writeable
import play.api.http.HeaderNames._
import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
import java.util.zip.GZIPOutputStream
import play.api.libs.concurrent.Promise
object GZip {
def gzip(input: Array[Byte]): Array[Byte] = {
val inputStream = new ByteArrayInputStream(input)
val byteArrayOut = new ByteArrayOutputStream(input.length)
val gzipper = new GZIPOutputStream(byteArrayOut)
val buf = new Array[Byte](4096)
var numBytesRead = inputStream read buf
while (numBytesRead > 0) {
gzipper.write(buf, 0, numBytesRead)
numBytesRead = inputStream read buf
}
// Clean up.
inputStream.close
gzipper.close
byteArrayOut.toByteArray
}
def gzipped(r: => Result)(implicit req: RequestHeader): Result = {
req.headers.get(ACCEPT_ENCODING).map(_.split(',').exists(_ == "gzip")) match {
case Some(true) => gzipResult(r)
case _ => r
}
}
private def gzipResult(r: => Result)(implicit req: RequestHeader): Result = r match {
case s:SimpleResult[_] =>
SimpleResult(s.header, s.body)(gzippedWritable(s.writeable)).withHeaders(CONTENT_ENCODING -> "gzip")
case AsyncResult(p) => AsyncResult(p.map(r => gzipped(r)))
case _ => r
}
private def gzippedWritable[A](w: Writeable[A]): Writeable[A] = {
Writeable { a =>
gzip(w.transform(a))
}
}
}
//And inside the controller action we could use it like following:
def index = Action { implicit request =>
gzipped {
Ok(views.html.index("hey"))
}
}
//or
def index = Action { implicit request =>
gzipped {
Async {
Promise.pure(Ok(someJsonValue))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment