Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have my Nginx server setup allow requests to be served with the X-Accel-Redirect header. This works fine for images, but I'm trying to get it to work for Javascript files that are already gzip'ed on the disk and it appears Nginx is stripping off the Content-Encoding header. This makes the browser not unzip the content when it receives it, which obviously makes it not work.

How can I serve pre-gzipped content through X-Accel-Redirect ?

The headers seen are:

With Accel = doesn't work

Accept-Ranges:bytes
Cache-Control:max-age=1209600, s-maxage=120960
Connection:keep-alive
Content-Length:122871
Content-Type:application/javascript
Date:Mon, 24 Jun 2013 13:44:36 GMT
Expires:Mon, 08 Jul 2013 13:44:36 GMT
Last-Modified:Mon, 24 Jun 2013 13:38:20 GMT
Server:nginx/1.2.8

No accel = works

Cache-Control:max-age=1209600, s-maxage=120960
Connection:keep-alive
Content-Encoding:gzip
Content-Length:122871
Content-Type:application/javascript
Date:Mon, 24 Jun 2013 13:45:08 GMT
Expires:Mon, 08 Jul 2013 13:45:08 GMT
HTTP1/0 200 Ok:
Pragma:cache
Server:nginx/1.2.8
X-Powered-By:PHP/5.4.9

In case it's relevant the code that is serving the content is:

public static function  proxyFile($fileNameToServe, $mimeType, $alreadyGzip = false){
        $seconds_to_cache = 3600 * 24 * 7 * 2; 

        $filesize = filesize($fileNameToServe);
        header('Content-Length: '.$filesize);

        if ($alreadyGzip) {
            header('Content-Encoding: gzip');
        }

        if(defined('X-ACCEL-REDIRECT') == true && constant('X-ACCEL-REDIRECT') == true){
            $filenameToProxy = str_replace(PATH_TO_ROOT."var/cache", '/protected_files', $fileNameToServe );
            sendProxyHeaders($mimeType, $seconds_to_cache);
            header("X-Accel-Redirect: ".$filenameToProxy);
            exit(0);
        }
        else{
            sendProxyHeaders($mimeType, $seconds_to_cache);
            $fileHandle = fopen($fileNameToServe, 'r');

            if($fileHandle == false){
                throw new \Exception("Failed to open file [$fileNameToServe] for serving.");
            }

            while (!feof($fileHandle)) {
                $contents = fread($fileHandle, 8192);
                echo $contents;
            }

            fclose($fileHandle);
        }

        exit(0);
    }

I've tried setting proxy_pass_header Content-Encoding; but apparently it has no effect.

share|improve this question
    
Can't you just use try_files? –  Michael Hampton Jun 24 '13 at 15:28
    
No, the file is actually several Javascript files that are bundled together and then minified on the fly. –  Danack Jun 24 '13 at 15:38
add comment

1 Answer

up vote 0 down vote accepted

It appears there are two solutions:

  1. Tell Nginx to pass the Content-Encoding header by add_header Content-Encoding $upstream_http_content_encoding;, and turn gzip off for the x-accel-redirect location, to prevent the content being gzipped twice.

    location ^~ /protected_files { gzip off; internal; alias /home/intahwebz/var/cache; add_header Content-Encoding $upstream_http_content_encoding; }

  2. Enable the gzip_static module.

Before serving a file from disk to a gzip-enabled client, this module will look for a precompressed file in the same location that ends in ".gz". The purpose is to avoid compressing the same file each time it is requested.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.