Monday, July 30, 2007

How to GZIP compress ColdFusion 8 Javascript in pure CF!

This was going to be a comment on rob gonda's blog about compressing the ajax javascript includes that ColdFusion 8 uses, but it became to long so im posting it here:

There is CF only solution to this that works on IIS and probably apache.
Heres the setup:

1. make a folder under your webroot /CFIDE/Scripts/
2. put 1 file in this folder index.cfm
3. set the default document on this folder to be index.cfm
4. set the 404 for this folder to redirect to /cfide/scripts/index.cfm

5. The code of index.cfm uses the CGI.query_string, since web server passes the attempted URL to the 404 page as a parameter, to work out the URL or the JS file under CFIDE thats required. eg.

[cfset fileName = mid(cgi.QUERY_STRING,find("/CFIDE",cgi.QUERY_STRING), len(cgi.QUERY_STRING) - find("/CFIDE",cgi.QUERY_STRING)+1 )]

6. then include the content


[cfsavecontent variable="rawJS"]
[cfoutput][cfinclude template="#fileName#"][/cfoutput]
[/cfsavecontent]

This relies on the fact that CFINCLUDE uses CF Mappings. So even tho IIS has /CFIDE/scripts/ mapped somewhere else, the CFMapping takes over on the include to get you the JS file you need.

7. GZIP the result and output if the browser supports it.

[cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip" AND not showRaw]

[cfheader name="Content-Encoding" value="gzip" ]

[cfset bos = createObject("java","java.io.ByteArrayOutputStream") ]
[cfset bos.init()]
[cfset gzipStream = createObject("java","java.util.zip.GZIPOutputStream")]
[cfset gzipStream.init(bos) ]
[cfset gzipStream.write(rawJS.getBytes("utf-8")) ]
[cfset gzipStream.close()]
[cfset bos.flush()]
[cfset bos.close()]

[cfset encoder = createObject("java","sun.misc.BASE64Encoder")]
[cfset outStr= encoder.encode(bos.toByteArray())]
[cfoutput]#toString(bos.toByteArray())#[/cfoutput]
[cfelse]
[cfoutput]#rawJS#[/cfoutput]
[/cfif]

using Rob's CFWindow example i got the request down to 116K with CF debugging turned on.