I am having trouble getting Imagecache working using Nginx as my server. I have narrowed down my issue to the URL that is being provided for the image. I have added the rewrite rule from this post (http://drupal.org/node/385690#comment-1360524), and it helps if the correct URL is used to access the image.

The non-working URL in the page source for the image is:
http://example.com/system/files/imagecache/product_full/Image.jpg

Working URLs:
http://example.com/sites/default/files/imagecache/product_full/Image.jpg (This URL doesn't work without the Rewrite rule I mentioned.)
http://example.com/index.php?q=system/files/imagecache/product_full/Imag...

Why would my rewrite rule that works for every other page on my site not work for the image cache directory? This is the main rewrite rule:

        location / {
            root   /var/www/html/example.com;
            index  index.php;
        
            if (!-e $request_filename) {
         	rewrite  ^/(.*)$  /index.php?q=$1  last;
                break;
            }
        }

EDIT: I figured out that the rewrite rule to serve images and css directly (http://drupal.org/node/110224#comment-772191) was causing imagecache to be bypassed entirely. Removing this rule allows imagecache to process the images and they also display appropriately. I do not know of any issues this may cause but will keep an eye on it.

Comments

mrfelton’s picture

I think you need something like this... The important bit for you it the bit tagged with the line '# imagecache needs to have php read any files that it's planning to manipulate'. And, if you are not using a multisite set up, as I am, you will need alter some of the urls, including the path to your ImageCache directory.

server {

    listen 80 default;
    server_name drupal-6.x;

    access_log /var/log/nginx/drupal-6.x.access.log;
    error_log /var/log/nginx/drupal-6.x.error.log debug;

    client_max_body_size 6M;

    root /var/www/html/drupal-6.x/;
    index index.php;

    location / {
     error_page 404 index.php;
     error_page 403 /403.html;

      # the main drupal app
      if (!-e $request_filename) {
        rewrite ^/(.*)$ /index.php?q=$1 last;
      }
    }

    # serve static files directly
    location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico)$ {
        rewrite ^/favicon.ico$ /sites/drupal-6.x/themes/mytheme/favicon.ico break;
        access_log        off;
        expires           30d;
    }

    # imagecache needs to have php read any files that it's planning to manipulate
    location ^~ /sites/drupal-6.x/files/imagecache/ {
       index  index.php index.html;
       # assume a clean URL is requested, and rewrite to index.php
        if (!-e $request_filename) {
            rewrite  ^/(.*)$  /index.php?q=$1  last;
            break;
        }
    }

    # serve the app via fastcgi
    location ~ \.php$ {
        #fastcgi_pass 127.0.0.1:9000;
        fastcgi_pass unix:/tmp/php-fastcgi.sock;
        fastcgi_index index.php;
        fastcgi_read_timeout 240;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
         deny  all;
    }
}

--
Tom
www.systemseed.com - drupal development. drupal training. drupal support.

tms8707056’s picture

You are correct. Without that section imagecache does not work.

However, the serve static files directly rule was causing the server to look for the file at the exact URL bypassing Drupal.
www.example.com/system/files/imagecache/preset_name/Image.jpg

My site is setup using the private file system. This means that requests for files must be passed through Drupal. Drupal expects a URL like this for every request:
www.example.com/index.php?q=system/files/imagecache/preset_name/Image.jpg

This would require the Imagecache URL to be rewritten so that index.php?q= can be inserted to pass the request through Drupal. However, the serve static files directly rule was causing nginx to bypass the rewrite and look for the file on the server without going through Drupal.

Removing that rule allows the URL to be rewritten and routes the request for the image through Drupal.

mrfelton’s picture

With the setup I outlined above, you don't need to remove that rule. Because, the location directive I assigned to the ImageCache URL has a higher priority that the one for static files, allowing you to serve static files directly AND send ImageCache URL's through Drupal.

EDIT:
so, for ImageCache on a private filesystem, you could try setting:

    # imagecache needs to have php read any files that it's planning to manipulate
    location ^~ /system/files/imagecache/ {
       index  index.php index.html;
       # assume a clean URL is requested, and rewrite to index.php
        if (!-e $request_filename) {
            rewrite  ^/(.*)$  /index.php?q=$1  last;
            break;
        }
    }

And Nginx should take that location directive over the static one due the the use of ^~

--
Tom
www.systemseed.com - drupal development. drupal training. drupal support.

hedac’s picture

I'm having the same problem... but I get this error if I try to see an imagecache image url.

"Firefox has detected that the server is redirecting the request for this address in a way that will never complete."

server {
      listen       80;
      server_name  website.com;

# serve static files
      location ~* \.(jpg|jpeg|gif|css|png|js|ico|txt|srt|swf|zip|rar|pdf|mp3)$ {
              expires   30d;
              root    /var/www/website/public_html;
      }

location ^~ /sites/website.com/files/imagecache/ {
            index  index.php index.html;
                if (!-e $request_filename) {
                    rewrite  ^/(.*)$  /index.php?q=$1  last;
                    break;
                }
}
# pass requests for dynamic content to apache2
                  location ~ \.php$ {
                        access_log off;
                        proxy_pass http://website.com:8080;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header Host $host;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    }
}
}

hedac’s picture

solved by putting this:

rewrite ^/(.*)$ http://website.com:8080/$1 last;

Also I recommend this
http://www.webinit.org/2009/08/15/nginx-drupal-visited/

chrism2671’s picture

This doesn't really count because you are now passing it onto Apache- so this will work for you, but it won't work for anybody using nginx + php_fastcgi!

cmejo’s picture

This is the right way to do it:

location ~ ^/sites/.*/files/imagecache/ {
                try_files $uri $uri/ @rewrite;

Put in your vhost config.

Hope that helps :)

Peter Bowey’s picture

cmayo, there is a missing '@rewrite' location in your example..