Skip to content

Instantly share code, notes, and snippets.

@jimschubert
Last active December 21, 2015 16:09
Show Gist options
  • Save jimschubert/6331438 to your computer and use it in GitHub Desktop.
Save jimschubert/6331438 to your computer and use it in GitHub Desktop.
A take a gzip compression for JavaScript and CSS in Finatra
package com.ipreferjim.resume
import com.twitter.finagle.{Service, SimpleFilter}
import com.twitter.finagle.http.{Method, Response, Request}
import com.twitter.util.Future
import com.twitter.finagle.http.MediaType
import java.util.zip.GZIPOutputStream
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.handler.codec.http.HttpHeaders
import org.apache.commons.io.output.ByteArrayOutputStream
class GzipFilter()
extends SimpleFilter[Request, Response] {
def apply(request: Request, service: Service[Request, Response]): Future[Response] = {
getFileExtension(request) match {
// gzip requested with some file extension
case Some(file) =>
// on successful requests...
service(request) onSuccess { response =>
// if the request is js/css
if(response.mediaType == Some(MediaType.Javascript) || response.contentType == Some("text/css"))
{
// get the contents that would have been sent and compress
val contents = gzipCompress(response.getContentString())
// replace the response's contents
response.setContent(ChannelBuffers.copiedBuffer(contents))
// update header so client knows to decompress
response.setHeader(HttpHeaders.Names.CONTENT_ENCODING, "gzip")
// update header with correct modified content length
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, contents.length.toString)
response.setHeader("X-Processed-By", "GzipFilter")
}
response
}
case None =>
service(request)
}
}
def gzipCompress(str:String) : Array[Byte] = {
// Create an in-memory stream
val os = new ByteArrayOutputStream(str.length())
// Decorate with gzip
val gos = new GZIPOutputStream(os)
// Write in the bytes
gos.write(str.getBytes())
gos.close()
// pull out the compressed bytes
val compressed = os.toByteArray()
os.close()
compressed
}
def getFileExtension(request: Request): Option[String] = {
// Only handle GET request filenames
if (request.method == Method.Get)
{
// And only handle files if gzip encoding is specified as acceptable
if( request.getHeader(HttpHeaders.Names.ACCEPT_ENCODING).contains("gzip") )
{
Some(request.fileExtension)
}
else
None
}
else
None
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment