3 Replies Latest reply on Feb 23, 2010 3:21 PM by Coos

    How to Gzip the response from a web service

    Coos Level 1

      I have the following code in my OnRequestEnd.cfm file to compress the response of most cfm/cfc requests.

       

      <cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip"
      AND REFindNoCase("MSIE 6", CGI.HTTP_USER_AGENT) eq 0
      AND NOT getPageContext().getResponse().isCommitted()>


          <cfscript>
               pageOut = getPageContext().getCFOutput().getString();
               fileOut = createobject("java", "java.io.ByteArrayOutputStream").init();
               out = createobject("java","java.util.zip.GZIPOutputStream").init(fileOut);
               out.write(variables.pageOut.getBytes(), 0, len(variables.pageOut.getBytes()));
               out.finish();
               out.close();
            </cfscript>


      <cfheader name="Content-Encoding" value="gzip">


      <cfcontent reset="true" variable="#fileOut.toByteArray()#">   
      </cfif>

       

      The first cfif makes sure the browser allows compressed responses.

      The second cfif excludes IE 6 as some earlier versions (which some of our users have) have decompression bugs.

      The third cfif generally prevents pages that have cfflush from being processed. It actually tells me if response headers have already been committed and written to the output stream.

       

      This seems to work fine except for cfcs that have returnType as XML and which are requested from flex applications via SOAP. If I remove the getPageContext().getResponse().isCommitted() I receive this error:

       

      Failed to add  HTML header.

      ColdFusion was unable to add the header you specified to the output stream. This is probably because you have already used a cfflush tag in your template or buffered output is turned off

       

       

      I know I don't have any cfflush tags in these cfcs so I suspect it's because the cfc already adds a "content-type: text/xml" header to the output. The cfc

      is

       

      <cfcomponent>
          <cffunction name="getHierarchyData" returntype="xml" access="remote">
              <cfxml variable="hierXML">
                  <root>
                      <labelAttribute>test</labelAttribute>
                      <data>
                          <moredata>test</moredata>

                      </data>
                  </root>
              </cfxml>

          <cfreturn hierXML>
          </cffunction>
      </cfcomponent>

       

      The response is something like:

      <?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <soapenv:Body>
        <ns1:getHierarchyDataResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://cfc.private">
         <getHierarchyData xsi:type="ns2:Document" xmlns:ns2="http://xml.apache.org/xml-soap">
          <root>
                          <labelAttribute>name</labelAttribute>

       

      How can I gzip the final response before sending it to the client?

       

      The response needs to be returned as as SOAP as these requests are from a Flex app that we cannot change at the moment.

      We're on Windows 2003/CF 8.01. We cannot use the built in IIS compression as it does not have a way to filter our requests from IE 6 as far as I know. Port80's httpzip doesn't work on 64 bit Windows 2003.

       

      Any suggestions? Has anyone used the built in compression in IIS successfully?