Nginx, Piwik, and Content Type Headers

Note this Update: read update

I decided to give Piwik a try as my web analytics tool. I’ve used Mint in the past and am mostly happy with it, but I sometimes feel Shaun Inman has no sense of urgency to make improvements to catch up to the big guys. I also considered Google Analytics and GetClicky but can’t get over the idea of someone else owning my analytics data. Sure, that’s fine for my blog or other smaller sites, but for something “important”, I’d rather hold onto it myself.

Piwik installation was pretty straightforward, typical fare these days. First thing I noticed was that the site was completely broken in FireFox, but seemed to work fine in IE. Firing up Charles I saw 2 things that smelled wrong:

  1. Requests for JavaScript and CSS files had a cache-busting query parameters stuck on the end of it, e.g. /piwik/themes/default/common.css?piwik=0.4.2. The idea here is that they can set a far-futures expires header on that file and let the browser cache it forever. When they release a new version of the site, they increment the version number on the request parameter and the browser goes and fetches the new styles or scripts. I thought this was an interesting technique, but possibly confusing nginx because….
  2. The “Content-Type” header was coming back as “text/html” for both JavaScript and CSS files.

IE doesn’t seem to mind that the content type was set incorrectly but Firefox refused to apply the styles because of it. So I started tinkering to see what I could do. Worst case scenario I would just have to use piwik only in IE, but that seemed kind of defeatist. Strangely, no one else on the interwebs seemed to be having the same issue, which lead me to think it was something specific to my environment.

The first thing I tried was to remove the cache busting request parameter by commenting out this line of code in the piwik source code:

$this->smarty->load_filter(‘output’, ‘cachebuster’);

I found that line in the file core/View.php on line 54 in version 0.4.2. That got rid of the cache busting query parameter, but didn’t fix the content type issue, so I ended up putting that line back in. I tried dropping one of the CSS files I was testing on another server and requesting that to see the headers. They turned out to be fine, at which point I decided it had to be an nginx issue. A couple of hacky attempts later I came up with the idea of just adding another header to JavaScript or CSS files as such:

   if ( $request_filename ~* (\.css) ){
      add_header Content-Type "text/css; charset=UTF-8";
      break;
   }

   if ( $request_filename ~* (\.js) ){
      add_header Content-Type "application/x-javascript; charset=UTF-8";
      break;
   }

That seems to work. Not entirely thrilled about it since I still don’t fully understand why it’s happening. Two Content-Type headers are getting set, but Firefox is ok with that for now. Oh well.

Note this Update: read update

Be Sociable, Share!
3 comments

3 Comments so far

  1. […] Nginx, Piwik, and Content Type Headers […]

  2. yang on December 16th, 2010

    A better solution (which I’m using) is to just forward the PHP requests to the backend and have nginx handle the static files.

    # Only push Piwik PHP to FPM backend
    location ~* ^/piwik.*\.php$ {
    root /home/yang/piwik; # Set $document_root for FCGI params
    rewrite ^/piwik(.*) $1 break; # Trim off the /piwik prefix
    fastcgi_index index.php;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    include /etc/nginx/fastcgi_params; # Default FCGI params
    }

    # Serve static files for Piwik
    location /piwik {
    alias /home/yang/piwik;
    index index.php; # Redirect / to the PHP
    }

  3. yang on December 16th, 2010

    I see you already figured it out – never mind!

Leave a Reply