3

I have these rewrite rules (I tried both with no avail):

location ~* "^/([a-z0-9]{32})\.png$" {
  rewrite ^ /index.php?page=log&id=$1 last;
} 

and

location ~* "/(?<hash>[a-z0-9]{32})\.png" {
  rewrite ^ /index.php?page=log&id=$hash;
}

and

location / {
  try_files $uri $uri/ @rewrites;
}

location @rewrites {
  rewrite "^/([a-zA-Z0-9]{32})\.png$" /index.php?page=log&id=$1 last;
  #...
}

Basically, I want the URL http://example.com/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.png to actually pass the parameters to my index.php script, and in the script, I got:

$db->save_hash($_GET['id']);
header('Content-type: image/png');
readfile('images/beacon.png');
break;

But nginx is giving me a "not found", but other rewrites work fine. What gives?

10
  • i'm using nginx 1.2.1 on ubuntu 12.10
    – pocesar
    Jan 17, 2013 at 4:51
  • I can confirm the first method by unlo works. Could you post your error logs and the context in which you put the rewrite?
    – Sašo
    Jan 17, 2013 at 18:47
  • for example this is a recent one 2013/01/17 15:21:31 [error] 3276#0: *20993 open() "/var/www/site/b14ad9f3b159f58e4f559662c12d9dcd.png" failed (2: No such file or directory), client: x.x.x.x, server: site, request: "GET /b14ad9f3b159f58e4f559662c12d9dcd.png HTTP/1.1", host: "site", referrer: "http://sn132w.snt132.mail.live.com/..." nothing else, no errors. The rewrite is inside /etc/nginx/sites-enabled/site nothing special
    – pocesar
    Jan 17, 2013 at 19:07
  • From seeing that I can only tell that the rewrite is either never reached or is completely ignored. Do you have breaks elsewhere, perhaps in a .png$ location?
    – Sašo
    Jan 17, 2013 at 19:16
  • nope, that's my only rewrite with pngs. every other rewrite, url based, are below this one, so it wouldn't matter, is there any way I debug all the rewrites that happen, in order, and dump to a file?
    – pocesar
    Jan 17, 2013 at 19:19

4 Answers 4

0

As per nginx documentation of how the location directive works:

A location can either be defined by a prefix string, or by a regular expression. ... A search of regular expressions terminates on the first match, and the corresponding configuration is used.

Based on addition information from your own answer to this very question, it would seem like you intend on having several location directives to apply simultaneously right at the very same time, which is explicitly not allowed as per the unambiguous documentation.

Remember, nginx is faster and cleaner by design. So, don't expect the quirks!

1
  • I see, I thought they would 'cascade', so it would work somehow like apache... thanks for clearing that out!
    – pocesar
    Jan 24, 2013 at 16:44
4
+50

this one worked for me:

    location / { 
    rewrite "/([a-z0-9]{32})\.png" /index.php?page=log&id=$1 break;
    }

Or if you want separeted location:

location ~* "/([a-z0-9]{32})\.png" {
rewrite /(.*) /index.php?page=log&id=$1 last;
}
6
  • didn't work, same 404 error
    – pocesar
    Jan 17, 2013 at 4:50
  • could you post all nginx conf? i think you have a more detailed location, which can match request even if its located below rewrite rule...
    – unlo
    Jan 18, 2013 at 12:43
  • i enabled rewrite_log in the config, but the regexp isn't even showing there... it's going directly to error.log, failed (2: No such file or directory)
    – pocesar
    Jan 23, 2013 at 20:28
  • see if you can fix my answer serverfault.com/a/471867/151339
    – pocesar
    Jan 23, 2013 at 21:17
  • So, you have much preferred location in expires.conf: # Media: \.(?:jpg|jpeg|gif|png|ico|gz|svg|svgz|mp4|ogg|ogv|webm)$. And i think, include of h5bp located before redirect rule, am i right? You must place our rule before include or remove png from expires.conf location.
    – unlo
    Jan 24, 2013 at 12:54
0

While @unlo's answer seems correct to me (tried myself on a clean virtualhost), I see one more optimisation. Instead of serving a static file by your script, you may want to use XSendFile feature to make nginx serve these files.

1
  • how could I do that?
    – pocesar
    Jan 23, 2013 at 17:23
0

Mark pointed out so I started removing all the included files, and boiled down to:

/etc/nginx/conf.d/h5bp.conf

that contains

# Basic h5bp rules

include /etc/nginx/conf.d/expires.conf;
include /etc/nginx/conf.d/x-ua-compatible.conf;
include /etc/nginx/conf.d/protect-system-files.conf;

the expires.conf got

# Expire rules for static content

# No default expire rule. This config mirrors that of apache as outlined in the
# html5-boilerplate .htaccess file. However, nginx applies rules by location,
# the apache rules are defined by type. A concequence of this difference is that
# if you use no file extension in the url and serve html, with apache you get an
# expire time of 0s, with nginx you'd get an expire header of one month in the
# future (if the default expire rule is 1 month). Therefore, do not use a
# default expire rule with nginx unless your site is completely static

# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html|xml|json)$ {
  expires -1;
  access_log /var/log/nginx/static.log;
}

# Feed
location ~* \.(?:rss|atom)$ {
  expires 1h;
  add_header Cache-Control "public";
}

# Favicon
location ~* \.ico$ {
  expires 1w;
  access_log off;
  add_header Cache-Control "public";
}

# Media: images, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|gz|svg|svgz|mp4|ogg|ogv|webm)$ {
  expires 1M;
  access_log off;
  add_header Cache-Control "public";
}

# CSS and Javascript
location ~* \.(?:css|js)$ {
  expires 1y;
  access_log off;
  add_header Cache-Control "public";
}

# WebFonts
# If you are NOT using cross-domain-fonts.conf, uncomment the following directive
location ~* \.(ttf|ttc|otf|eot|woff|font.css)$ {
  expires 1M;
  access_log off;
  add_header Cache-Control "public";
}

commenting that expires.conf, then it starts working, how can I fix this?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .