Comments 23
if'ы зло.
Рекомендуется использовать if только в случае если вы из него уходите (rewrite last, 30x redirect и т.п.). Это логично и это почти никогда не сломается в случае изменения логики в работе сервера.
Use try_files if it suits your needs. Use the «return ...» or «rewrite… last» in other cases. In some cases it's also possible to move ifs to server level (where it's safe as only other rewrite module directives are allowed within it).


Альтернативный вариант (на мой взгляд лучше читается):
server {
    listen 127.0.0.1:80;
    server_name nocache.domain.tld;
    location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|swf|txt|ico)$ {
        allow 127.0.0.1;
        deny all;
        root /path/to/fuse/filesystem;
    }
}

server {
    listen 80;
    server_name domain.tld
    location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|swf|txt|ico)$ {
        proxy_cache static_cache;
        proxy_cache_valid 200 1y;
        proxy_set_header Host nocache.$host;
        proxy_pass http://127.0.0.1;
    }
}
Да тут даже дело не в элегантности. Практика распределения через location-ы, а не регулярки сложилась не просто так. Так быстрее. Ну и смотрится логичнее.
Вместо
        allow 127.0.0.1;
        deny all;

лучше писать
        internal;


Ну а вообще, конечно, отдавать картинки через X-Accel-Redirect, а потом наворачивать поверх конфиги для нгинкса… Мсье (автор, не вы) знает толк в извращениях.
Так исторически сложилось — мне на вход приходит номер, я его преобразую в имя файла и выплевываю.
Когда я делал похожую систему для gdetotdom.ru — админ меня сразу завернул(«нет, давай лучше так делать не будем»).
И там nginx «канонически» работает через try_files.
Если бы я научился считать md5 в nginxе — смог бы делал тоже самое. Но не научился.

Вы про штуки типа github.com/simpl/ngx_http_set_hash?

Можно даже сделать средствами перла, ничего не добавляя в стандартную сборку:
perl_set $md5 '
    use Digest::MD5 qw(md5_hex);
    sub {
        my $r = shift;
        my $some_var = $r->variable("some_var");
        return md5_hex($some_var);
    }
';

server {
    listen 8081;
    location / {
        set $some_var $arg_text;
        return 200 $md5;
    }
}


Но всё это не отменяет того, что стоит переписать код, который формирует ссылки на картинки.
Я вот все перлом хочу, и все никак не сделаю.
В принципе осталось узнать как substr сделать и можно будет переходить на try_files.
Хотя у wikimapia это, в итоге, не получилось — на их объемах try_files тупит.
Выкрутились хитро, быть может расскажут когда-нибудь.
Здесь нельзя написать internal, потому что это не внутреннее перенаправление и не реврайт. Это прокси само на себя, с точки зрения nginx запрос абсолютно стандартный.
Я стесняюсь спросить, но что побудило вас написать это правило внутри блока server c listen 127.0.0.1:80;? =)
Nginx может слушать и проксировать на unix-сокете.

listen unix:/var/run/nginx.sock;

proxy_pass http://unix:/var/run/nginx.sock;
Ужасная же регулярка: ^.+\.(jpg|jpeg|gif|png|ico|css|js|swf|txt|ico)$, почему бы хотя бы для статьи не поправить очевидные косяки? И так много у вас ico на сервере (аж дважды в регулярке встречается)?

location ~* \.(?:jpe?g|gif|png|ico|css|js|swf|txt)$ { .. }

Но адекватные люди хранят статику отдельно.
Что сказать? — Админа на мыло — в оригинале(я немного укоротил правило для статьи) еще и два png,exe и wav с bmp
(Как хорошо, что этот админ не я)
Вот кстати о ужасах данной регулярки, а почему, к примеру просто не добавить в исключения нужное, к примеру так:
location ~* \.(?!php)

Или даже листом из необходимого: php, html, shtml (для SSI в апаче), и что там ещё м.б.
Наверное потому, что negative look-ahead не самая тривиальная конструкция в PCRE. Вот, в частности, и вы ошиблись, так работать не будет. =)

Правильно:

location ~* ^(?!.*\.php)
Ну т.е. как то совсем сурово — это вот так:
 location ~* \.(?!php|html|shtml) {
       root xxx;
 }
Опять же, правильный вариант:
location ~* ^(?!.*\.(?:php|s?html)) {
    root xxx;
}
Забавно, попробовал сейчас у себя на сервере так, вроде всё хорошо, но перестали работать индексы (index.php и index.shtml), ну точнее именно если так написать, то всё хорошо, а вот если просто косая черта в конце, то не работает, а nginx выдаёт 403 ошибку :) Вот уж точно не тривиальные исключения, и дело наверное даже не в регулярках.

конфиг nginx
    server {
        listen 80;
        server_name xxx;

        charset utf-8;

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        location ~ /\.ht {
            deny  all;
        }
		  
        location ~* ^(?!.*\.(?:php|s?html)) {
            root W:\www;
        }

        location / {
            proxy_pass http://127.0.0.1:8080/;
            proxy_set_header X-REQUEST_URI $request_uri;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-for $remote_addr;
            proxy_set_header Host $host;
            proxy_connect_timeout 10;
            proxy_send_timeout 15;
            proxy_read_timeout 15;
            proxy_redirect off;
            proxy_set_header Connection close;
            proxy_pass_header Content-Type;
            proxy_pass_header Content-Disposition;
            proxy_pass_header Content-Length;
        }
    }



До этого просто из головы написал… то ли лыжи не едут, то ли у меня мозгов не хватает, хотя какие то ли, конечно же второе )))

Точно, руки у меня точно по этому вопросу растут не оттуда откуда следует, ибо я так ни разу и не настроил nginx как кеширующий прокси у себя ^_^'
Эта экономия на редизайне архитектуры может Вам потом вылезти боком. Это уже проявляется, на самом деле, например, в необходимости такого рода хитрозакрученных костылей, что описаны в статье. Дальше поддерживать приемлемый уровень производительности будет ещё сложнее, увы. Вместо «хочется спать» будет противоположное.

Все ИМХО, разумеется ;)
А почему нельзя поставить на сервера, с которых вы монтируете файловые системы, nginx и уже их nginx'ы проксировать?
Именно так и стоит.
На каждом сервере стоит и гластер-мастер и гластер-клиент. Один большой сетевой raid-1.
Но читать из «реальной» папки размещения файлов гластера нельзя — он разваливается. Читать можно только из папки клиента, а это уже FUSE раздел.
И у меня не так много серверов чтобы выстраивать два эшелона фронтов. Сейчас все нгинксы читают данные с себя.
А до конфига с locations я, в свое время, не додумался.
Only those users with full accounts are able to leave comments. Log in, please.