Comments 51
UFO landed and left these words here
На днях я закончу работать над fastcgi протоколом в одной програмулине и напишу статью ещё про один велосипед. А знаете почему? Потому что 1) оно заточено под свои нужды 2) чтобы понять материал, надо его самому реализовать.
UFO landed and left these words here
Я в начале написал что решает, описал как решает. Если кому-то понадобится, он воспользуется. Любое решение делается «под свои нужды». Скажите, что вредного вы нашли?
UFO landed and left these words here
ico файлы в самом начале пропускаются. /favicon.ico вернёт файл из корня сайта.
UFO landed and left these words here
Если его нет, то отработает механизм «страницы 404». Миниатюры в каком смысле? Превьюшки картинок или что вы имеете в виду? Favicon?
UFO landed and left these words here
В данном варианте не закрываются все случаи жизни. Не стояла задача повторить Друпал.

Для несуществующих картинок, например, в подпапке /img может лежать другой .htaccess, который запустит скрипт генерации превьюшек. Зачем усложнять? Ну, я не люблю когда все случаи жизни проходят через один «входной» скрипт. Считаю, что для картинок, css/js своя light версия версия должна быть.

Но а загруженный пользователем php файл и так не будет запущен, так как все запросы на php/html имеют одну точку входа.
Выносить логику работы маршрутизатора в htaccess, ИМХО не самый лучший вариант.

А что если часть jpg изображений будет генерироваться на лету?
Маршрутизатор будет работать как ему и положено. Условие написанное вначале обязательно для любого движка, что будет использовать его. Да и я никому не навязываю делать именно так.

Если будут генерироваться jpg, будет другой .htaccess или ещё что-нибудь. Для текущих нужд был сделан этот. Его предостаточно.
Вы аддиктед в нейтральном смысле этого слова.
В 99% случаев достаточно такого .htaccess, например:

Options +FollowSymlinks
RewriteEngine On
RewriteBase /

# Exclude directories from rewrite rules
RewriteRule ^(css|i|js|storages|assets) - [L]

# For Friendly URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 [L,QSA]
Извините, но вы просто кажется не поняли зачем это. Для избежания дублированных адресов в самый раз.
Я здесь вижу прикладной .htaccess с кучей регулярок.
Без каких-либо вменяемых юзкейсов и оправданий.

У поста-предтечи, по крайней мере, хоть юзкейс внятно описан.

А здесь префильтер апача непонятного генеза, который а) собирает строку, которая потом снова будет разбираться маршрутизатором; б) гоняет миллиард регулярок.

Были бы расписаны юзкейсы и логика работы бэкенд-приложения (вдруг там крутится унитарная транзакционная система реального времени, которая долго думает и падает от неверных урлов без .html в конце?) — тогда в посте был бы смысл.
Например, мне не хотелось, чтобы запускался какой-нибудь бэк-энд, да тот же php, лишь для того, чтобы поменять окончание в урле с / на .html.
Опишите юз-кейсы в теле поста, пожалуйста, ну. Например, расскажите, зачем вам пришлось убивать rest-friendly URI's.
Задача стояла иметь все окончания для страниц вида .html. Для страниц с rest-friendly url легко переписывается под это. Вы, наверное, видите идеал в максимальной универсальности? Я вижу это иначе. Можете спорить, сливать мне карму, как уже успешно делают, но я захотел задачу решить так и решил её. А переписав не один десяток раз сам .htaccess, просидев часы в rewrite_log получил хороший опыт.
Чёрт побери, ну вы все и роботы…

Вот вы написали пост. Вложили в него своё время и наработанные знания. Но сделали это так, что человек, который прочитал пост, остаётся в состоянии интеллектуального недоумения.

Зачем была проделана работа? Почему именно таким способом? Какие подводные камни тут были обогнуты?

Дело не в сливе кармы, а в том, что информационная ценность поста в такой конфигурации близка к нулю.
UFO landed and left these words here
Что угодно «детектед».

С такими .htaccess ходят многие проекты, начиная с ModX и заканчивая самописными CMS.

Если понадобится делать такие редиректы — это значит, что выбрано любое количество пунктов из:
1. Неадекватный системный архитектор;
2. Неадекватные инструменты;
3. Неадекватное количество костылей поверх всего.

Такие проблемы решаются на этапе маршрутизации или на этапе генерации статических шаблонов для кэша.
UFO landed and left these words here
Честно говоря, слабо представляю решение лучше вашего.

Видите, в вашем случае как раз та ситуация, когда временный костыль не перерастёт в костыль постоянный, поскольку в пределе ссылочная масса обновится и переходов по старым ссылкам не будет.

Тут всё хорошо.
Я честно пытался дочитать. Клянусь… Но не вышло… Может быть материал и интересен, но подача совсем никакая
Я правильно понял логику?
server {
    listen 80;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    location / {
        root /var/site;
        rewrite ^/index(\.\w+)?$ / permanent; # редирект c index-ов на корень
        rewrite ^/(.+)\.\.html /$1.en.html permanent; # добавляем в ".." дефолтный язык
        rewrite ^/(.+?)/?$(?<!\.html) $1.html permanent; # добавляем .html, заодно убираем слеш
        try_files $uri /test.php?URI=$uri; # если файла нету - нехай его сделает бекенд
    }

    location ~^/([^/]*\.php)$ { # скармливаем пыху скрипты в докруте, включая фронт контроллер
        fastcgi_param SCRIPT_FILENAME /var/site/$fastcgi_script_name;
        fastcgi_param QUERY_STRING $args;
        include fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
    }
}
rewrite ^/(.+?)\.+html /$1.html permanent; примерно так
а правило try_files $uri /test.php?URI=$uri; не нужно. Не важно есть фаил или нет, все запросы страниц дожны идти через /test.php

тогда будет похоже.
Оно нужно для отдачи статики, если безусловно посылать всё на бекенд — картинки перестанут отдаваться, надо тогда сделать им отдельный location.
Вообще-то W3C еще лет 5 назад рекомендовала не завершать URL-ы на .html, .php, .asp и тому подобные суффиксы, и сама следует своим же рекомендациям на своем сайте.

Откуда упорно идет эту дурацкая мода приписывать .html?
Возможно у меня мало знаний по .htaccess :) Вообщем, я мало что понял. Может стоит дополнить статью реальными примерами и более детальным описанием каждой фишечки?
Поддерживаю, по .htaccess нормальных фишек с детальным разъяснением на русском я не видел. Было бы очень познавательно о них почитать.
Ок, сделаю такую статью (когда карму поднимут:)). Расскажите что знаете, а что не понимаете.
Имхо было бы неплохо, если бы вы разжевали относительно правил более подробно. Например, что делает эта строка и что в ней за что отвечает
RewriteRule ^(.*)$ $1 [L,QSA]
т.е. понятно, что это какое-то правило замены, но не более.
Возможно, есть смысл сделать базовый HOW-TO по .htaccess.
Согласен, стоит написать. Но не в такой форме, в какой заполнен интернет. Там предполагается уже знание синтаксиса без разжевывания правил на предмет «почему так». В основном готовые примеры.
Напишу такую статью. Расскажите что знаете, а что не понимаете.
Лично мне интересны общие знания по формированию URL. В контексте SEO тоже было бы интересно (например удаление дублей URL).

Мне больше нравится адресация вида /about/history/, без .html

Не понятна вот такая конструкция RewriteRule. %1.html [R=301,L,E=NS:1,QSA], что она делает?
Мне кажется RewriteRules — это достаточно легкий предмет для понимания и гугления, и как правильно было замечено, смысл всех преобразований из статьи довольно невелик. Для тех кого забанили в гугле, есть отличный сайт про .htaccess в котором всё разжевано.

При этом в статье упущены возможности .htaccess по управлению кешированием, удобный version`инг для css\js и другие полезные плюшки.

К примеру мой вариант .htaccess — доработанный и сокращенный под необходимости от Boilerplate.

AddDefaultCharset utf8
RewriteEngine on
RewriteBase /

# CSS & JS Versioning Routing
# style.123.css equal to style.css
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)\.(\d+)\.(js|css)$ $1.$3 [L]

# General Routing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L,QSA]

#Expiring
<IfModule mod_expires.c>
  ExpiresActive on
  # Dynamic
  ExpiresByType text/html                 "access plus 0 seconds"
  ExpiresByType text/xml                  "access plus 0 seconds"
  ExpiresByType application/xml           "access plus 0 seconds"
  ExpiresByType application/json          "access plus 0 seconds"
  # Images
  ExpiresByType image/x-icon              "access plus 1 week"
  ExpiresByType image/gif                 "access plus 1 month"
  ExpiresByType image/png                 "access plus 1 month"
  ExpiresByType image/jpg                 "access plus 1 month"
  ExpiresByType image/jpeg                "access plus 1 month"
  # Fonts
  ExpiresByType application/x-font-ttf    "access plus 1 month"
  ExpiresByType font/opentype             "access plus 1 month"
  ExpiresByType application/x-font-woff   "access plus 1 month"
  ExpiresByType image/svg+xml             "access plus 1 month"
  # JS & CSS because of versioning
  ExpiresByType text/css                  "access plus 1 year"
  ExpiresByType application/javascript    "access plus 1 year"
</IfModule>

#Disable ETag because of Expiring
<IfModule mod_headers.c>
  Header unset ETag
</IfModule>
FileETag None

# Disable Indexing of folders
<IfModule mod_autoindex.c>
  Options -Indexes
</IfModule>
Сразу важный момент: выключена автоматическая подстановка слеша в конец и выключен MultiViews (с ним работать не будет).

Так же отключает показ содержимого директории.

Разве это нельзя описать одним выражением: ^/index.*$

RewriteCond %{REQUEST_URI} ^/index$ [OR]
RewriteCond %{REQUEST_URI} ^/index[.]+(\w+)$
RewriteRule . / [R=301,L]


Про некоторые некоторые приемы не знал, значит это уже полезный материал для меня, спасибо.
Я уже и забыл когда последний раз описывал правила url через RewriteRule. Во всех более менее нормальных фреймворках есть свой UrlManager которые делает это все дела куда гибче. Хотя речь не об этом.
Можно одним выражением, но не так, как вы описали: ^/index([.]+\w+|)$
А ^/index.*$ сработает на всё что угодно /indexblablablabla что вполне (хоть и вряд ли) может быть полноценной страницей. Имелось в виду, что исключительно название /\bindex\b/ является индексной страницей.

Многие фреймворки нагромождены ради гибкости, но это такие единичные случаи, чтобы пути отличались от /path/to/file-name или /path/to/file-name.html, что вместо усложнения кода urlmanager'а решил вынести это дело в .htaccess. Ведь я же не прописывал конкретно случаи редиректов, а только общий вид путей.
А я бы убивал тех, кто использует такие огромные .htaccess
Т.к. это не дают возможности перенести приложение на другой веб-сервер, мало читабельно, размазывание логики по всему, чему можно

Видимо работа в хостинге и переносы таких умников, дают о себе знать :)
На lleo.aha.ru/na/ следует отправлять говнокодеров, творения которых требуют подобной строчки.
Большое спасибо.
Понадобилось на одном из сайтов включить перенаправление с */index.php на */ — самостоятельно быстро сделать не получилось, зато легко нагуглилась эта статья. Всё заработало с первого копипэйста.
Only those users with full accounts are able to leave comments. Log in, please.