Мод переписать, чтобы удалить расширение файла, добавить косую черту, удалить www и перенаправить на 404, если файл / каталог не доступен - PullRequest
2 голосов
/ 27 января 2012

Я хотел бы создать правила перезаписи в моем файле .htaccess для выполнения следующих действий:

  • При доступе через domain.com/abc.php: удалите расширение файла, добавьте косую черту и загрузите файл abc.php. URL должен выглядеть следующим образом после перезаписи: domain.com/abc/

  • При доступе через domain.com/abc/: оставьте URL как есть и загрузите abc.php

  • При доступе через domain.com/abc: добавьте косую черту и загрузите abc.php. URL должен выглядеть следующим образом после перезаписи: domain.com/abc/

  • Удалить www

  • Перенаправление на страницу 404 (404.php), когда URL-адрес, к которому осуществляется доступ, не разрешается в папку или файл, например, при доступе к domain.com/nothingthere.php или domain.com/nothingthere/ или domain.com/nothingthere

  • Сделайте несколько постоянных перенаправлений 301 со старых URL-адресов на новые (например, domain.com/abc.html на domain.com/abc/)

Все php-файлы находятся в корневом каталоге документа, но если есть решение, позволяющее работать с URL-адресами, такими как domain.com/abc/def/ (будет загружать domain.com/abc/def.php), оно будет работать будь здоров, но не обязательно

Итак, вот что у меня есть в данный момент (собранные из различных источников и примеров со всего Интернета

<IfModule mod_rewrite.c>
  RewriteCond %{HTTPS} !=on
  # redirect from www to non-www
  RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
  RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]

  # remove php file extension
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
  RewriteRule (.*)\.php$ /$1/ [L,R=301]

  # add trailing slash
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^.*[^/]$ /$0/ [L,R=301]

  # resolve urls to matching php files 
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule (.*)/$ $1.php [L]

При этом, похоже, срабатывают первые четыре требования, независимо от того, введу ли я domain.com/abc.php, domain.com/abc/ или domain.com/abc, окончательный URL всегда будет domain.com/abc/ и домен.com/abc.php загружен.

Когда я ввожу URL, который разрешается в файл, который не существует, я получаю ошибку 310 (цикл перенаправления), когда действительно должна быть загружена страница 404. Кроме того, я не пробовал, работают ли подпапки, но, как я уже сказал, это низкий приоритет. Я почти уверен, что могу просто добавить в список постоянные редиректы 301 устаревшие URL-адреса и без каких-либо проблем, просто хотел упомянуть об этом. Таким образом, настоящая проблема - это действительно нерабочая страница 404.

Ответы [ 4 ]

5 голосов
/ 13 февраля 2012

У меня были проблемы с обеспечением надежной работы ErrorDocument с ошибками перезаписи, поэтому я предпочитаю корректно обрабатывать некорректные страницы в моем каскаде перезаписи. Я попытался охватить весь спектр тестовых векторов этим. Не нашли пробелов.

Некоторые общие моменты:

  • Здесь необходимо использовать переменную окружения DOCUMENT_ROOT . К сожалению, если вы используете службу общего хостинга, то она не будет правильно настроена при выполнении перезаписи, поэтому хостинг-провайдеры устанавливают теневую переменную для выполнения той же работы. Мой использует DOCUMENT_ROOT_REAL , но я также сталкивался с PHP_DOCUMENT_ROOT . Сделайте phpinfo, чтобы узнать, что использовать для вашего сервиса.
  • Существует правило отладочной информации, которое можно обрезать, если заменить DOCROOT соответствующим образом
  • Вы не всегда можете использовать %{REQUEST_FILENAME} там, где вы ожидаете. Это связано с тем, что если URI отображается на DOCROOT/somePathThatExists/name/theRest, тогда %{REQUEST_FILENAME} устанавливается на DOCROOT/somePathThatExists/name, а не на полный шаблон, эквивалентный строке соответствия правила.
  • Это «на каталог», поэтому никаких косых черт нет, и мы должны понимать, что механизм перезаписи будет зацикливаться на файле .htaccess, пока не произойдет остановка без совпадения.
  • Это обрабатывает все действительные комбинации и в самом конце перенаправляет на 404.php, который, как я полагаю, устанавливает статус 404, а также отображает страницу ошибки.
  • В настоящее время он будет декодировать someValidScript.php / otherRubbish в стиле SEO, но дополнительная логика также может его подхватить.

Итак, вот фрагмент .htaccess:

Options -Indexes -MultiViews
AcceptPathInfo Off

RewriteEngine On
RewriteBase   /

## Looping stop.  Not needed in Apache 2.3 as this introduces the [END] flag
RewriteCond %{ENV:REDIRECT_END}  =1
RewriteRule ^                    -                       [L,NS]

## 302 redirections ##

RewriteRule ^ - [E=DOCROOT:%{ENV:DOCUMENT_ROOT_REAL},E=URI:%{REQUEST_URI},E=REQFN:%{REQUEST_FILENAME},E=FILENAME:%{SCRIPT_FILENAME}]

# redirect from HTTP://www to non-www
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST}        ^www\.(.+)$ [NC]
RewriteRule ^                   http://%1%{REQUEST_URI}  [R=301,L]

# remove php file extension on GETs (no point in /[^?\s]+\.php as rule pattern requires this)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_METHOD}   =GET
RewriteRule (.*)\.php$          $1/                      [L,R=301]

# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*[^/]$            $0/                      [L,R=301]

# terminate if file exists.  Note this match may be after internal redirect.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^                   -                        [L,E=END:1]

# terminate if directory index.php exists.  Note this match may be after internal redirect.
RewriteCond %{REQUEST_FILENAME}    -d
RewriteCond %{ENV:DOCROOT}/$1/index.php    -f
RewriteRule ^(.*)(/?)$             $1/index.php          [L,NS,E=END:1]

# resolve urls to matching php files 
RewriteCond %{ENV:DOCROOT}/$1.php  -f
RewriteRule ^(.*?)/?$              $1.php                [L,NS,E=END:1]

# Anything else redirect to the 404 script.  This one does have the leading /

RewriteRule ^                      /404.php              [L,NS,E=END:1]

Наслаждайтесь: -)

0 голосов
/ 14 февраля 2012
  1. Создать папку в корневом каталоге домена
  2. Поместить .htaccess в указанную выше папку как RewriteRule ^ $ index.php
  3. Разобрать URL
  4. С помощью PHP-кода вы теперь можете удалить URL-адрес или расширение файла при необходимости
0 голосов
/ 10 февраля 2012

Я придумал это:

DirectorySlash Off
RewriteEngine on
Options +FollowSymlinks

ErrorDocument 404 /404.php

#if it's www
#  redirect to non-www.
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
   RewriteRule ^ http://%1%{REQUEST_URI} [L,R=301,QSA]

#else if it has slash at the end, and it's not a directory
#  serve the appropriate php
RewriteCond %{ENV:REDIRECT_STATUS} ^$ 
RewriteCond %{REQUEST_FILENAME} !-d
   RewriteRule ^(.*)/$ /$1.php [L,QSA]

#else if it's an existing file, and it's not php or html
#   serve the content without rewrite
RewriteCond %{ENV:REDIRECT_STATUS} ^$ 
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} !(\.php)|(\.html?)$
   RewriteRule ^ - [L,QSA]

#else
#  strip php/html extension, force slash
RewriteCond %{ENV:REDIRECT_STATUS} ^$ 
   RewriteRule ^(.*?)((\.php)|(\.html?))?/?$ /$1/ [L,NC,R=301,QSA]

Конечно, не очень элегантно (env: redirect_status - довольно хак), но оно проходит мои скромные тесты.К сожалению, я не могу проверить перенаправление www, поскольку я нахожусь на локальном хосте и не имею реального доступа к серверу, но эта часть тоже должна работать.

Видите ли, я использовал директиву ErrorDocument, чтобы указатьстраницу ошибки и использовал запрос DirectorySlash Off, чтобы убедиться, что Apache не мешает добавлению косой черты.Я также использовал флаг QSA (Query String Append), который, ну, в общем, добавляет строку запроса к запросу, чтобы она не терялась.Это выглядит глупо после косой черты, но в любом случае.

В остальном это довольно просто, и я думаю, что комментарии объясняют это довольно хорошо.Дайте мне знать, если у вас возникнут какие-либо проблемы.

0 голосов
/ 27 января 2012

Возможно, вы захотите проверить, существует ли php-файл перед добавлением косой черты.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*[^/]$ /$0/ [L,R=301]

или действительно ли вы хотите косую черту для всех 404 страниц (поэтому /image/error.jpg станет /images/error.jpg/, что мне кажется странным):

RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*[^/]$ /$0/ [L,R=301]
...