Apache — самый распространённый HTTP-сервер. Распространяется бесплатно, включая исходные тексты. Поддерживаются сценарии на CGI (включая FastCGI), PHP, Perl, Java. Аутентификация — базовая, message-digest, TLS (SSL). С апреля 1996 это самый популярный HTTP-сервер в Интернете, в августе 2007 года он работал на 51% всех веб-серверов.
.htaccess — файл дополнительной конфигурации веб-сервера Apache, а также подобных ему серверов. Позволяет задавать большое количество дополнительных параметров и разрешений для работы веб-сервера у отдельных пользователей (а также на различных папках отдельных пользователей), таких как управляемый доступ к каталогам, переназначение типов файлов и т.д., не предоставляя доступа к главному конфигурационному файлу, т.е. не влияя на работу всего сервиса целиком.
.htaccess является подобием httpd.conf с той разницей, что действует только на каталог, в котором располагается, и на его дочерние каталоги. Возможность использования .htaccess присутствует в любом каталоге пользователя.
Файл .htaccess может быть размещен в любом каталоге сайта. Директивы этого файла действуют на все файлы в текущем каталоге и во всех его подкаталогах (если эти директивы не переопределены директивами нижележащих файлов .htaccess).
Директивы .htaccess предоставляют пользователю широкий выбор возможностей по настройке своего сайта, среди которых:
- Директивы простого перенаправления (редирект);
- Директивы сложного перенаправления (mod_rewrite);
- Индексные страницы;
- Обработка ошибок;
- Кодировка;
- Управление доступом;
- Паролирование директорий;
- Указание опций PHP.
Список всех доступных директив можно посмотреть тут.
Директивы простого перенаправления (редирект)
Наиболее часто используемые и наиболее сложные директивы .htaccess. Предположим, мы хотим при запросе нашего сайта переадресовать пользователя на другой URL. Для этого нам необходимо в корневую директорию сайта добавить файл .htaccess со следующим содержимым:
Redirect / http://www.example.com
# http://www.example.com - URL, на который мы перенаправляем запросы
Более сложный пример — мы хотим определенные страницы нашего сайта переадресовывать на другие сайты:
Redirect /linux http://www.linux.org
Redirect /linux/download.html http://www.linux.org/dist/download_info.html
Redirect 301 /kernel http://www.linux.org
Теперь при обращении к http://mysite.ru/linux будет открываться http://www.linux.org, а при обращении к http://mysite.ru/linux/download.html будет http://www.linux.org/dist/download_info.html . В последнем примере WEB-сервер будет передавать код 301, что означает «документ перемещен постоянно».
Синтаксис команды Redirect выглядит следующим образом:
Redirect [status] URI_LOCAL URL_REDIRECT
status : необязательное поле, определяет код возврата. Допустимые значения:
* permanent (301 — документ перемещен постоянно)
* temp (302 — документ перемещен временно)
* seeother (303 — смотрите другой)
* gone (410 — убран)
URI_LOCAL : локальная часть URL запрашиваемого документа.
URL_REDIRECT : URL, куда должен быть выполнен редирект.
Директива RedirectMatch аналогична директиве Redirect за исключением того, что в RedirectMatch возможно использование регулярных выражений, что, несомненно, может быть удобно в некоторых условиях. Например, для организации передачи параметров скрипту в теле URL:
RedirectMatch /(.*)/(.*)/index.html$ http://mysite.ru/script.php?par1=$1&par2=$2
Хотя данный пример и вызовет перезагрузку страницы, в дальнейшем его можно будет улучшить. Здесь необходимо сделать небольшое лирическое отступление и поговорить о синтаксисе регулярных выражений.
В регулярном выражении можно использовать любые печатные символы и пробел, но часть символов имеет особое значение:
- Круглые скобки () используются для выделения групп символов. В дальнейшем к ним можно обращаться по номеру.
- Символ ^ обозначает начало строки.
- Символ $ обозначает конец строки.
- Символ . обозначает любой символ.
- Символ | обозначает альтернативу. Например, выражения «A|B» означают «A или B».
- Символ ? ставится после символа (группы), который может как присутствовать, так и отсутствовать.
- Символ * ставится после символа (группы), который может отсутствовать или присутствовать неограниченное число раз подряд.
- Символ + действует аналогично символу * с той лишь разницей, что предшествующий ему символ обязательно должен присутствовать хотя бы один раз.
- Квадратные скобки [] используются для перечисления допустимых символов.
- Квадратные скобки [^] используются для перечисления недоступных символов.
- Символ ставится перед спецсимволами, если они нужны в своем первозданном виде.
- Все, что расположено после символа ‘#‘, считается комментарием.
Это все основные примитивы, с помощью которых можно построить любое регулярное выражение.
Директивы сложного перенаправления (mod_rewrite)
Модуль mod_rewrite, имеющийся в составе Apache — это мощнейшее интеллектуальное средство преобразования URL-адресов. С ним возможны почти все типы преобразований, которые могут выполняться или нет в зависимости от разных условий, факторов.
Данный модуль представляет собой основанный на правилах механизм (синтаксический анализатор с применением регулярных выражений), выполняющий URL-преобразования на лету. Модуль поддерживает неограниченное количество правил и связанных с каждым правилом условий, реализуя действительно гибкий и мощный механизм управления URL. URL-преобразования могут использовать разные источники данных, например, переменные сервера, переменные окружения, заголовки HTTP, время и даже запросы к внешним базам данных в разных форматах для получения URL нужного Вам вида.
Директива RewriteCond определяет условие, при котором происходит преобразование. RewriteCond определяет условия для какого-либо правила. Перед директивой RewriteRule располагаются одна или несколько директив RewriteCond. Следующее за ними правило преобразования используется только тогда, когда URI соответствует условиям этой директивы, а также условиям этих дополнительных директив.
Под обратной связью подразумевается использование частей сравниваемых URL для дальнейшего использования, т.е. передачи параметров или для построения нового URL.
- $N — (0 <= N <= 9) предоставляющие доступ к сгруппированным частям (в круглых скобках!) шаблона из соответствующей директивы RewriteRule (единственной, следующей сразу за текущим набором директив RewriteCond).
- %N — (1 <= N <= 9) предоставляющие доступ к сгруппированным частям (в круглых скобках!) шаблона из соответствующей директивы RewriteCond в текущем наборе условий.
- %{NAME_OF_VARIABLE} — где NAME_OF_VARIABLE может быть одной из ниже приведенных переменных
Ниже приводится список всех доступных переменных %{NAME_OF_VARIABLE} с их кратким описанием.
- HTTP_USER_AGENT — Содержит информацию о типе и версии браузера и операционной системы посетителя.
- HTTP_REFERER — Приводится адрес страницы, с которой посетитель пришёл на данную страницу.
- HTTP_COOKIE — Список COOKIE, передаваемых браузером.
- HTTP_FORWARDED — Cодержит IP-адрес прокси-сервера или сервера балансировки нагрузки.
- HTTP_HOST — Адрес сервера, например, beget.com .
- HTTP_ACCEPT — Описываются предпочтения клиента относительно типа документа.
- REMOTE_ADDR — IP-адрес посетителя.
- REMOTE_HOST — Адрес посетителя в нормальной форме — например, rt99.net.ru .
- REMOTE_IDENT — Имя удаленного пользователя. Имеет формат имя.хост, например, kondr.www.rtt99.net.ru
- REMOTE_USER — Тоже, что и REMOTE_IDENT, но содержит только имя. Пример: kondr
- REQUEST_METHOD — Позволяет определить тип запроса (GET или POST). Должен обязательно анализироваться, т.к. определяет дальнейший способ обработки информации.
- SCRIPT_FILENAME — Полный путь к веб-странице на сервере.
- PATH_INFO — Содержит в себе все, что передавалось в скрипт.
- QUERY_STRING — Содержит строчку, переданную в качестве запроса при вызове CGI скрипта.
- AUTH_TYPE — Используется для идентификации пользователя
- DOCUMENT_ROOT — Cодержит путь к корневой директории сервера.
- SERVER_ADMIN — Почтовый адрес владельца сервера, указанный при установке.
- SERVER_NAME — Адрес сервера, например, kondr.beget.com
- SERVER_ADDR — IP-адрес вашего сайта.
- SERVER_PORT — Порт, на котором работает Apache.
- SERVER_PROTOCOL — Версия HTTP протокола.
- SERVER_SOFTWARE — Название сервера, например, Apache/1.3.2 (Unix)
- TIME_YEAR, TIME_MON, TIME_DAY, TIME_HOUR, TIME_MIN, TIME_SEC, TIME_WDAY, TIME — Переменные, предназначенные для работы со временем в разных форматах.
- API_VERSION — Это версия API модуля Apache (внутренний интерфейс между сервером и модулем) в текущей сборке сервера, что определено в include/ap_mmn.h.
- THE_REQUEST — Полная строка HTTP-запроса, отправленная браузером серверу (т.е., «GET /index.html HTTP/1.1»). Она не включает какие-либо дополнительные заголовки отправляемые браузером.
- REQUEST_URI — Ресурс, запрошенный в строке HTTP-запроса.
- REQUEST_FILENAME — Полный путь в файловой системе сервера к файлу или скрипту, соответствующему этому запросу.
- IS_SUBREQ — Будет содержать текст «true», если запрос выполняется в текущий момент как подзапрос, «false» в другом случае. Подзапросы могут быть сгенерированы модулями, которым нужно иметь дело с дополнительными файлами или URI для того, чтобы выполнить собственные задачи.
Условие — это шаблон условия, т.е. какое-либо регулярное выражение, применяемое к текущему экземпляру «Сравниваемая Строка», т.е. «Сравниваемая Строка» просматривается на поиск соответствия Условию.
Помните, что Условие — это perl-совместимое регулярное выражение с некоторыми дополнениями:
- Вы можете предварять строку шаблона префиксом ‘!’ для указания несоответствия шаблону;
- ‘ <Условие’ (лексически меньше);
- ‘>Условие’ (лексически больше);
- ‘=Условие’ (лексически равно);
- ‘-d’ (является ли каталогом);
- ‘-f’ (является ли обычным файлом);
- ‘-s’ (является ли обычным файлом с ненулевым размером);
- ‘-l’ (является ли символической ссылкой);
- ‘-F’ (проверка существования файла через подзапрос);
- ‘-U’ (проверка существования URL через подзапрос).
Все эти проверки также могут быть предварены префиксом восклицательный знак (‘!’) для инвертирования их значения.
RewriteEngine включает или выключает работу механизма преобразования. Если она установлена в положение off, этот модуль совсем не работает. Заметьте, что по умолчанию настройки преобразований не наследуются. Это означает, что вы должны иметь RewriteEngine on директиву для каждого виртуального хоста, в котором вы хотите использовать этот модуль.
Синтаксис RewriteEngine выглядит следующим образом:
RewriteEngine on | off
# По умолчанию RewriteEngine off
Используйте для комбинирования условий в правилах OR вместо AND. Типичный пример — перенаправление запросов на поддомены в отдельные каталоги.
RewriteEngine on
RewriteCond %{REMOTE_HOST} ^mysubdomain1.* [OR]
RewriteCond %{REMOTE_HOST} ^mysubdomain2.* [OR]
RewriteCond %{REMOTE_HOST} ^mysubdomain3.*
RewriteRule ^(.*)$ ^mysubdomain_public_html/$1
RewriteCond %{REMOTE_HOST} ^mysubdomain4.*
RewriteRule ^(.*)$ ^mysubdomain4_public_html/$1
Для выдачи главной страницы какого-либо сайта, согласно «User-Agent:» заголовку запроса, Вы можете использовать следующие директивы:
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*
RewriteRule ^$ /homepage.max.html [L]
RewriteCond %{HTTP_USER_AGENT} ^Lynx.*
RewriteRule ^$ /homepage.min.html [L]
RewriteRule ^$ /homepage.std.html [L]
Для выдачи разных сайтов для разных браузеров, согласно «User-Agent:» заголовку запроса, Вы можете использовать следующие директивы:
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*
RewriteRule ^(.*)$ /mozilla/$1 [L]
RewriteCond %{HTTP_USER_AGENT} ^Lynx.*
RewriteRule ^(.*)$ /lynx/$1 [L]
RewriteRule ^(.*)$ /default/$1 [L]
Общий синтаксис директивы RewriteRule выглядит следующим образом:
RewriteRule Шаблон Подстановка [flag]
# flag - необязательное поле указывающее дополнительные опции
В подстановке вы можете использовать, в том числе, и специальные флаги путем добавления в качестве третьего аргумента директивы RewriteRule. Флаги — это разделённый запятыми следующий список флагов:
'redirect|R [=code]'
(вызывает редирект)
Префикс в Подстановке вида http://thishost[thisport]/ (создающий новый URL из какого-либо URI) запускает внешний редирект (перенаправление). Если нет никакого кода, в подстановке ответ будет со HTTP статусом 302 (ВРЕМЕННО ПЕРЕМЕЩЕН). Для остановки процесса преобразования вам также нужно написать флаг ‘L’.
'forbidden|F [=code]'
(делает URL запрещенным)
Это делает текущий URL запрещённым, например, клиенту немедленно отправляется ответ с HTTP статусом 403 (ЗАПРЕЩЕНО). Используйте этот флаг в сочетании с соответствующими RewriteConds для блокирования URL по некоторым критериям.
'gone|G [=code]'
(делает URL «мёртвым»)
Этот флаг делает текущий URL «мертвым», т.е., немедленно отправляется HTTP ответ со статусом 410 (GONE). Используйте этот флаг для маркировки «мертвыми» несуществующие более страницы.
'proxy|P [=code]'
(вызвает прокси)
Этот флаг помечает подстановочную часть как внутренний запрос прокси и немедленно (т.е. процесс преобразования здесь останавливается) пропускает его через прокси-модуль. Используйте этот флаг для того, чтобы добиться более мощной реализации директивы ProxyPass, интегрирующей некоторое содержимое на удаленных серверах в пространство имён локального сервера.
'last|L [=code]'
(последнее правило)
Остановить процесс преобразования на этом месте и не применять больше никаких правил преобразований. Используйте этот флаг для того, чтобы не преобразовывать текущий URL другими, следующими за этим, правилами преобразований.
'next|N [=code]'
(следуюший раунд)
Перезапустить процесс преобразований (начав с первого правила). В этом случае URL снова сопоставляется неким условиям, но не оригинальный URL, а URL вышедший из последнего правила преобразования. Используйте этот флаг для перезапуска процесса преобразований, т.е. безусловному переходу на начало цикла.
'chain|C [=code]'
(связь со следующим правилом)
Этот флаг связывает текущее правило со следующим (которое, в свою очередь, может быть связано со следующим за ним, и т.д.). Это имеет следующий эффект: если есть соответствие правилу, процесс продолжается как обычно, т.е. флаг не производит никакого эффекта. Если правило не соответствует условию, все следующие, связанные правила, пропускаются.
'type|T=MIME-тип [=code]'
(принудительно установить MIME тип)
Принудительно установить MIME-тип целевого файла в MIME-тип. К примеру, это можно использовать для имитации mod_alias директивы ScriptAlias, которая принудительно устанавливает для всех файлов внутри отображаемого каталога MIME тип равный «application/x-httpd-cgi».
'nosubreq|NS [=code]'
(используется только в случае не внутреннего подзапроса)
Этот флаг дает команду механизму преобразований пропустить директиву, если текущий подзапрос является внутренним подзапросом. К примеру, внутренние подзапросы в Apache происходят тогда, когда mod_include пытается получить информацию о возможных файлах по умолчанию для каталогов (index.xxx). При подзапросах это не всегда полезно и даже иногда вызывает проблему в работе набора директив преобразований. Используйте этот флаг для исключения некоторых правил.
'nocase|NC [=code]'
(не учитывать регистр)
Это делает Шаблон нечувствительным к регистру, т.е. нет различий между ‘A-Z’ и ‘a-z’, когда Шаблон применяется к текущему URL.
'qsappend|QSA [=code]'
(добавлять строку запроса)
Этот флаг указывает механизму преобразований на добавление, а не замену, строки запроса из URL к существующей, в строке подстановки. Используйте это когда вы хотите добавлять дополнительные данные в строку запроса с помощью директив преобразований.
'noescape|NE [=code]'
(не экранировать URI при выводе)
Этот флаг не даёт mod_rewrite применять обычные правила экранирования URI к результату преобразования. Обычно, специальные символы (такие как ‘%’, ‘$’, ‘;’, и так далее) будут экранированы их шестнадцатиричными подстановками (‘%25’, ‘%24’, и ‘%3B’, соответственно); этот флаг не дает это делать.
Если в подкаталогах в .htaccess нет ни одной директивы модуля mod_rewrite, то все правила преобразования наследуются из родительского каталога.
При наличии в файле .htaccess каких-либо директив модуля mod_rewrite не наследуется ничего, а состояние по умолчанию выставляется таким же, как в главном конфигурационном файле веб-сервера (по умолчанию «off»). Поэтому, если нужны правила преобразования для конкретного каталога, то нужно еще раз вставить директиву «RewriteEngine on» в .htaccess для конкретного каталога.
При наследовании правил из верхних каталогов и добавлении к ним новых свойственных только данному каталогу — необходимо выставить в начале следующее: «RewriteEngine on» и «RewriteOptions inherit» — последняя директива сообщает серверу о продолжении.
Примеры использования mod_rewrite можно посмотреть тут.
Индексные страницы
Когда пользователь заходит на хост, например, http://gentoo.org, принято, что открывается индексный файл index.* , а при его отсутствии отображается либо содержимое каталога, либо отдается ошибка 403 FORBIDDEN (если отключена опция «просмотр директорий»).
За листинг файлов отвечает директива Indexes (показывать посетителю список файлов, если в выбранном каталоге нет файла index.html или его аналога).
Иногда нужно сделать так, чтобы в случае отсутствия в каталоге файла, который показывается по умолчанию, листинг, то есть список файлов в каталоге, не выдавался. В этом случае добавим в .htaccess такую строчку:
# Запрет выдачи листинга пустого каталога
Options -Indexes
А чтобы выдавал листинг, нужно:
Если же понадобится разрешить просматривать список файлов, но чтобы при этом чаcть файлов определенного формата не отображалась, то запишем:
Выдает листинг каталога, т.е. его содержание со всем содержанием, за исключением файлов-скриптов PHP и Perl.
Если ваш веб-сайт построен на скриптах, то в качестве индексных часто могут использоваться файлы с другими расширениями. Указать эти файлы можно с помощью директивы DirectoryIndex.
DirectoryIndex index.html index.shtml index.pl index.cgi index.php
Если же вы хотите что бы при обращении к каталогу открывался не index.html, а, например, файл htaccess.php или /cgi-bin/index.pl:
DirectoryIndex htaccess.php /cgi-bin/index.pl
Обработка ошибок
В ходе работы сервера иногда возникают ошибки, однако правильнее называть их не сбоями в работе сервера, а стандартными кодами возврата, оговоренными в стандарте HTTP_RFC2616. Вообще, в RFC ошибки называются «Status Codes», но мы их будем называть именно ошибками — так привычнее.
Код возврата — это трехзначное число, на основании которого можно судить о том, насколько успешно был обработан запрос. Код возврата начинающиеся на 1,2,3 считаются успешными, остальные причисляются к разряду ошибок.
Вот список ошибок 4xx и 5xx:
- 400 — Bad Request
- 401 — Unauthorized
- 402 — Payment Required
- 403 — Forbidden
- 404 — Not Found
- 405 — Method Not Allowed
- 406 — Not Acceptable
- 407 — Proxy Authentication Required
- 408 — Request Time-out
- 409 — Conflict
- 410 — Gone
- 411 — Length Required
- 412 — Precondition Failed
- 413 — Request Entity Too Large
- 414 — Request-URI Too Large
- 415 — Unsupported Media Type
- 500 — Internal Server Error
- 501 — Not Implemented
- 502 — Bad Gateway
- 503 — Service Unavailable
- 504 — Gateway Time-out
- 505 — HTTP Version not supported
При возникновении ошибки 4xx или 5xx посетитель Вашего сайта увидит в браузере сообщение от сервера, которое вряд ли можно назвать предельно понятным рядовому пользователю. Apache предоставляет возможность выдать вместо аскетичного технического текста, не изобилиющего деталями, свою страницу, где Вы можете человеческим языком объяснить пользователю, что произошло и что делать.
Пример переопределения страниц ошибок приведен ниже:
# содержание файла .htaccess:
ErrorDocument 404 http://bg10.ru/error/404.htm
ErrorDocument 403 http://bg10.ru/error/403.htm
ErrorDocument 400 http://bg10.ru/error/400.htm
ErrorDocument 500 http://bg10.ru/error/500.htm
# в случае ошибки "FORBIDDEN" показывается текстовое сообщение, которое
# обязательно должно начинаться с кавычки, кавычка в сообщении не выводится:
ErrorDocument 403 "Sorry can't allow you access today, 403 Status Codes Apache"
Более подробно об обработке ошибок можно прочитать в документации по Apache на странице «Custom error responses».
Кодировка
Иногда браузер пользователя не может корректно определить тип кодировки выдаваемого документа. Для решения этой проблемы используемая кодировка указывается в настройках Web-сервера Apache и заголовке передаваемого документа. Причем для корректного распознания эти кодировки должны совпадать. На наших серверах по умолчанию используется кодировка UTF-8.
В HTML для указания кодировки используется тег:
Наиболее часто встречаются типы кодировки для русского языка передаваемые в заголовке документа:
- Windows-1251 — Кириллица (Windows).
- KOI8-r — Кириллица (КОИ8-Р).
- cp866 — Кириллица (DOS).
- Windows-1252 — Западная Европа (Windows).
- Windows-1250 — Центральная Европа (Windows).
- UTF-8 — двух байтовая кодировка.
Теперь рассмотрим указание кодировки по умолчанию через .htaccess. AddDefaultCharset задает дефолтную таблицу символов (кодировку) для всех выдаваемых страниц на веб-сервере Apache. Указываем кодировку на все файлы, в которой по умолчанию получает документы браузер:
AddDefaultCharset WINDOWS-1251
При загрузке файла на сервер возможна перекодировка. Указываем, что все получаемые файлы будут иметь кодировку windows-1251, для этого напишем:
CharsetSourceEnc WINDOWS-1251
Если необходимо отменить перекодировку сервером файлов:
Управление доступом
Очень часто возникает необходимость запретить доступ к определенным файлам или папкам для определенных групп пользователей. В Web-сервере Apache есть встроенные средства для решения данной проблемы.
Для запрета или разрешения доступа ко всем файлам и папкам в текущей и во всех вложенных директориях используется директива Order, синтаксис ее очень прост:
Order [Deny,Allow] | [Allow,Deny]
# По умолчанию Deny,Allow
В зависимости от того, в каком порядке указаны директивы, меняется логика работы сервера. В случае, если Deny,Allow, то запрещается доступ со всех IP кроме оговоренных, в случае, если Allow,Deny, разрешается доступ со всех IP кроме оговоренных. Далее должны идти секции описания для доступа и запрета. Ключевое слово all означает со всех IP.
Например, мы хотим запретить (блокировать) доступ с IP 81.222.144.12 и 81.222.144.20 и разрешить всем остальным. Нам необходимо добавить в .htaccess следующий код:
Order Allow,Deny
Allow from all
Deny from 81.222.144.12 81.222.144.20
Для обратной ситуации, когда мы хотим запретить доступ со всех IP кроме 81.222.144.12 и 81.222.144.20, нам необходимо добавить в .htaccess следующий код:
Order Deny,Allow
Deny from all
Allow from 81.222.144.12 81.222.144.20
Запрет или разрешение на доступ можно указывать не только на все файлы, но так же можно указывать на отдельный файл или группы файлов. Например, мы хотим запретить доступ всех пользователей, кроме IP 81.222.144.12, к файлу passwd.html, который расположен в текущей директории:
<Files "passwd.html">
Order Deny,Allow
Deny from all
Allow from 81.222.144.12
</Files>
Так же можно запретить или разрешить доступ к определенной группе файлов. Например, к файлам с расширением «.key«:
<Files ".(key)$">
Order Deny,Allow
Deny from all
Allow from 81.222.144.12
</Files>
Паролирование директорий
.htaccess можно также использовать для установки пароля на доступ к определенным папкам, файлам и группам файлов. Приведем рабочий пример, а потом поясним все содержимое:
AuthName "Protected area, need authorization"
AuthType Basic
AuthUserFile /home/t/test/.authfile
require valid-user
Данный файл нужно положить в ту директорию, на которую мы хотим поставить пароль.
Директива AuthName выводит сообщение при запросе пароля, все сообщение необходимо писать в одну строчку, синтаксис директивы тривиален:
Директива AuthType выбирает тип аутентификации. Возможны следующие типы: Basic или Digest. Второй может не поддерживаться некоторыми браузерами, поэтому пользоваться им не рекомендуется.
AuthUserFile указывает имя файла с паролями для аутентификации пользователей (пароли в этом файле будут шифрованными). Путь к файлу с паролями задается относительно корня веб-сервера. Храните файл с паролями в папке, доступ к которой закрыт для пользователей. Желательно поместить этот файл вне иерархии вашего веб-сайта, например, рядом с каталогом public_html. Размещать его выше каталога сайта нецелесообразно. Это не увеличит безопасность, но потребует дополнительной настройки прав доступа в связи с изоляцией сайтов.
Если у Вас установлена операционная система семейства Windows, Вы можете подключится к серверу по SSH (инструкцию по подключению можно найти тут) и воспользоваться утилитой htpasswd.
Запустив htpasswd без параметров мы увидим:
beget@ginger ~ # htpasswd
Usage:
htpasswd [-cmdps] passwordfile username
htpasswd -b[cmdps] passwordfile username password
-c Create a new file.
beget@ginger ~ #
Здесь не будут рассматриваться все параметры этой команды, но вы можете сами прочитать подробности, запустив htpasswd в unix shell, или ознакомившись с соответствующей страницей документации по Apache.
Итак, изначально у нас еще нет файла с паролями и нам нужно его создать:
beget@ginger ~ # htpasswd -c authfile test1
New password:
Re-type new password
Adding password for user test1
beget@ginger ~ #
После выполнения данной операции htpasswd создаст файл passwords, в котором окажется пользователь test1 и его пароль в зашифрованном виде:
beget@ginger ~ $ cat .authfile
test1:zgco1KREjBY8M
beget@ginger ~ $
А теперь мы хотим добавить еще одного пользователя. Так как файл с паролями у нас уже есть, мы просто не будем использовать ключ ‘-c’:
beget@ginger ~ # htpasswd .authfile test2
New password:
Re-type new password:
Adding password for user test2
beget@ginger ~ $ cat .authfile
test1:zgco1KREjBY8M
test2:eN3uA6t0kzV1c
beget@ginger ~ $
Вернемся к описанию директив паролирования директорий. Директива Require определяет пользователей, которые могут получить доступ:
Require USER_NAME | valid-user
Указывая valid-user, Вы разрешаете доступ всем пользователям, перечисленным в файле паролей.
Приведем пример для доступа определенных пользователей из файла с паролями .htpasswd:
AuthName "Protected area, need authorization"
AuthType Basic
AuthUserFile /home/t/test/.authfile
require Alexey Kondr Fenix
Также, как и с запретом доступа по IP, здесь можно использовать расширение <Files> . Ниже приведены два примера: установки пароля на один определенный файл и на группу файлов.
<Files "passwd.html">
AuthName "Protected area, need authorization"
AuthType Basic
AuthUserFile /home/t/test/.authfile
require valid-user
</Files>
<Files ".(key)$">
AuthName "Protected area, need authorization"
AuthType Basic
AuthUserFile /home/t/test/.authfile
require valid-user
</Files>
Следует помнить, что при таком ограничении доступа пароли передаются по каналам связи в открытом виде и при определенных обстоятельствах могут быть перехвачены злоумышленниками. Поэтому в целях безопасности рекомендуется организовывать доступ к закрытым областям веб-сайта через защищенное SSL-соединение.
Указание опций PHP
Директивы для конфигурирования PHP можно размещать не только в файле php.ini, но также и в конфигурационных файлах Apache для вашего сайта – .htaccess. Это позволяет проводить тонкую настройку php для разных директорий.
Для работы с PHP в конфигурационных файлах Apache доступны 4 директивы: php_value, php_flag, php_admin_value, php_admin_flag, которые отличаются значимостью, типом устанавливаемых значений и местом применения.
Директивы php_admin_value, php_admin_flag выставляются только в файле httpd.conf, так что нам они не интересны. По сути, данные директивы переопределяют значение остальных директив.
Директива php_flag служит для установки логических значений директив в php.ini, в то время как директива php_value служит для установки строковых и числовых значений директив php.ini, т.е. любых типов значений, за исключением логических.
Синтаксис директив очень прост:
php_flag имя директивы on | off
php_value имя директивы VALUE
Приведем перечень наиболее часто используемых директив:
- mysql.default_host — Устанавливает имя хоста базы данных.
Пример: php_value mysql.default_host localhost - mysql.default_user — Устанавливает имя пользователя базы данных.
Пример: php_value mysql.default_user alexey - mysql.default_password — Устанавливает пароль пользователя базы данных.
Пример: php_value mysql.default_password Hry5Gw2 - display_errors — Разрешает вывод ошибок и предупреждений в браузер.
Пример: php_flag display_errors 0 - display_startup_errors — Включает отображение ошибок, возникающих при запуске PHP.
Пример: php_flag display_startup_errors 0 - error_reporting — Определяет типы (уровни важности) фиксируемых ошибок.
Пример: php_value error_reporting 32767 - auto_prepend_file — Определение файла, который будет выводится в начале каждого php-скрипта. Путь указывается от корня файловой системы сервера.
Пример: php_value auto_prepend_file /www/server/prepend.php - auto_append_file — Определение файла, который будет выводится в конце каждого php-скрипта.
Пример: php_value auto_append_file /www/server/append.php - sendmail_from — Устанавливает e-mail отправителя, который применяется при отправке почтовых сообщений с помощью PHP.
Пример: php_value sendmail_from root@beget.com - user_agent — Устанавливает строку User-agent, которая используется PHP при обращении к удаленным серверам.
Пример: php_value user_agent “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”
Например, для вывода всех сообщений об ошибках генерируемых php в .htaccess нужно прописать следующие строки:
php_flag display_errors 1
php_flag display_startup_errors 1
php_value error_reporting 2047
Для запрещения выполнения php в текущей директории и во всех вложенных, необходимо в .htaccess прописать следующие строки:
Удачной работы! Если возникнут вопросы — напишите нам, пожалуйста, тикет из Панели управления аккаунта, раздел «Помощь и поддержка».
I am testing a website online.
Right now, the errors are not being displayed (but I know they exist).
I have access to only the .htaccess
file.
How do I make all errors to display using my .htaccess
file?
I added these lines to my .htaccess
file:
php_flag display_startup_errors on
php_flag display_errors on
php_flag html_errors on
And the pages now display:
Internal server error
asked May 25, 2011 at 16:50
Ogugua BelonwuOgugua Belonwu
2,0916 gold badges28 silver badges45 bronze badges
3
.htaccess:
php_flag display_startup_errors on
php_flag display_errors on
php_flag html_errors on
php_flag log_errors on
php_value error_log /home/path/public_html/domain/PHP_errors.log
answered May 25, 2011 at 16:54
9
php_flag display_errors on
To turn the actual display of errors on.
To set the types of errors you are displaying, you will need to use:
php_value error_reporting <integer>
Combined with the integer values from this page: http://php.net/manual/en/errorfunc.constants.php
Note if you use -1 for your integer, it will show all errors, and be future proof when they add in new types of errors.
answered May 25, 2011 at 16:57
UFTimmyUFTimmy
5893 silver badges4 bronze badges
1
I feel like adding more details to the existing answer:
# PHP error handling for development servers
php_flag display_startup_errors on
php_flag display_errors on
php_flag html_errors on
php_flag log_errors on
php_flag ignore_repeated_errors off
php_flag ignore_repeated_source off
php_flag report_memleaks on
php_flag track_errors on
php_value docref_root 0
php_value docref_ext 0
php_value error_log /full/path/to/file/php_errors.log
php_value error_reporting -1
php_value log_errors_max_len 0
Give 777 or 755 permission to the log file and then add the code
<Files php_errors.log>
Order allow,deny
Deny from all
Satisfy All
</Files>
at the end of .htaccess.
This will protect your log file.
These options are suited for a development server. For a production server you should not display any error to the end user. So change the display flags to off.
For more information, follow this link: Advanced PHP Error Handling via htaccess
answered Jan 8, 2016 at 9:56
AshishAshish
6597 silver badges19 bronze badges
1
If you want to see only fatal runtime errors:
php_value display_errors on
php_value error_reporting 4
answered Aug 23, 2017 at 23:28
ZekeZeke
5524 silver badges14 bronze badges
This works for me (reference):
# PHP error handling for production servers
# Disable display of startup errors
php_flag display_startup_errors off
# Disable display of all other errors
php_flag display_errors off
# Disable HTML markup of errors
php_flag html_errors off
# Enable logging of errors
php_flag log_errors on
# Disable ignoring of repeat errors
php_flag ignore_repeated_errors off
# Disable ignoring of unique source errors
php_flag ignore_repeated_source off
# Enable logging of PHP memory leaks
php_flag report_memleaks on
# Preserve most recent error via php_errormsg
php_flag track_errors on
# Disable formatting of error reference links
php_value docref_root 0
# Disable formatting of error reference links
php_value docref_ext 0
# Specify path to PHP error log
php_value error_log /home/path/public_html/domain/PHP_errors.log
# Specify recording of all PHP errors
# [see footnote 3] # php_value error_reporting 999999999
php_value error_reporting -1
# Disable max error string length
php_value log_errors_max_len 0
# Protect error log by preventing public access
<Files PHP_errors.log>
Order allow,deny
Deny from all
Satisfy All
</Files>
answered Aug 15, 2019 at 14:11
DarkcoderDarkcoder
7927 silver badges17 bronze badges
Apache .htaccess files allow users to configure directories of the web server they control without modifying the main configuration file.
While this is useful it’s important to note that using .htaccess
files slows down Apache, so, if you have access to the main server configuration file (which is usually called httpd.conf
), you should add this logic there under a Directory
block.
See .htaccess in the Apache HTTPD documentation site for more details about what .htaccess files can do.
The remainder of this document will discuss different configuration options you can add to .htaccess
and what they do.
Most of the following blocks use the IfModule directive to only execute the instructions inside the block if the corresponding module was properly configured and the server loaded it. This way we save our server from crashing if the module wasn’t loaded.
Redirects
There are times when we need to tell users that a resource has moved, either temporarily or permanently. This is what we use Redirect
and RedirectMatch
for.
<IfModule mod_alias.c> # Redirect to a URL on a different host Redirect "/service" "http://foo2.example.com/service" # Redirect to a URL on the same host Redirect "/one" "/two" # Equivalent redirect to URL on the same host Redirect temp "/one" "/two" # Permanent redirect to a URL on the same host Redirect permanent "/three" "/four" # Redirect to an external URL # Using regular expressions and RedirectMatch RedirectMatch "^/oldfile.html/?$" "http://example.com/newfile.php" </IfModule>
The possible values for the first parameter are listed below. If the first parameter is not included, it defaults to temp
.
- permanent
-
Returns a permanent redirect status (301) indicating that the resource has moved permanently.
- temp
-
Returns a temporary redirect status (302). This is the default.
- seeother
-
Returns a «See Other» status (303) indicating that the resource has been replaced.
- gone
-
Returns a «Gone» status (410) indicating that the resource has been permanently removed. When this status is used the URL argument should be omitted.
Cross-origin resources
The first set of directives control CORS (Cross-Origin Resource Sharing) access to resources from the server. CORS is an HTTP-header based mechanism that allows a server to indicate the external origins (domain, protocol, or port) which a browser should permit loading of resources.
For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. A web application using those APIs can only request resources from the same origin the application was loaded from unless the response from other origins includes the appropriate CORS headers.
General CORS access
This directive will add the CORS header for all resources in the directory from any website.
<IfModule mod_headers.c> Header set Access-Control-Allow-Origin "*" </IfModule>
Unless you override the directive later in the configuration or in the configuration of a directory below where you set this one, every request from external servers will be honored, which is unlikely to be what you want.
One alternative is to explicitly state what domains have access to the content of your site. In the example below, we restrict access to a subdomain of our main site (example.com). This is more secure and, likely, what you intended to do.
<IfModule mod_headers.c> Header set Access-Control-Allow-Origin "subdomain.example.com" </IfModule>
Cross-origin images
As reported in the Chromium Blog and documented in Allowing cross-origin use of images and canvas can lead to fingerprinting attacks.
To mitigate the possibility of these attacks, you should use the crossorigin
attribute in the images you request and the code snippet below in your .htaccess
to set the CORS header from the server.
<IfModule mod_setenvif.c> <IfModule mod_headers.c> <FilesMatch ".(bmp|cur|gif|ico|jpe?g|a?png|svgz?|webp|heic|heif|avif)$"> SetEnvIf Origin ":" IS_CORS Header set Access-Control-Allow-Origin "*" env=*IS_CORS* </FilesMatch> </IfModule> </IfModule>
Google Chrome’s Google Fonts troubleshooting guide tells us that, while Google Fonts may send the CORS header with every response, some proxy servers may strip it before the browser can use it to render the font.
<IfModule mod_headers.c> <FilesMatch ".(eot|otf|tt[cf]|woff2?)$"> Header set Access-Control-Allow-Origin "*" </FilesMatch> </IfModule>
Cross-origin resource timing
The Resource Timing Level 1 specification defines an interface for web applications to access the complete timing information for resources in a document.
The Timing-Allow-Origin response header specifies origins that are allowed to see values of attributes retrieved via features of the Resource Timing API, which would otherwise be reported as zero due to cross-origin restrictions.
If a resource isn’t served with a Timing-Allow-Origin
or if the header does not include the origin, after making the request some attributes of the PerformanceResourceTiming
object will be set to zero.
<IfModule mod_headers.c> Header set Timing-Allow-Origin: "*" </IfModule>
Custom Error Pages/Messages
Apache allows you to provide custom error pages for users depending on the type of error they receive.
The error pages are presented as URLs. These URLs can begin with a slash (/) for local web-paths (relative to the DocumentRoot), or be a full URL which the client can resolve.
See the ErrorDocument Directive documentation on the HTTPD documentation site for more information.
ErrorDocument 500 /errors/500.html ErrorDocument 404 /errors/400.html ErrorDocument 401 https://example.com/subscription_info.html ErrorDocument 403 "Sorry, can't allow you access today"
Error prevention
This setting affects how MultiViews work for the directory the configuration applies to.
The effect of MultiViews
is as follows: if the server receives a request for /some/dir/foo, if /some/dir has MultiViews
enabled, and /some/dir/foo does not exist, then the server reads the directory looking for files named foo.*, and effectively fakes up a type map which names all those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client’s requirements.
The setting disables MultiViews
for the directory this configuration applies to and prevents Apache from returning a 404 error as the result of a rewrite when the directory with the same name does not exist
Apache uses mod_mime to assign content metadata to the content selected for an HTTP response by mapping patterns in the URI or filenames to the metadata values.
For example, the filename extensions of content files often define the content’s Internet media type, language, character set, and content-encoding. This information is sent in HTTP messages containing that content and used in content negotiation when selecting alternatives, such that the user’s preferences are respected when choosing one of several possible contents to serve.
Changing the metadata for a file does not change the value of the Last-Modified header. Thus, previously cached copies may still be used by a client or proxy, with the previous headers. If you change the metadata (language, content type, character set, or encoding) you may need to ‘touch’ affected files (updating their last modified date) to ensure that all visitors receive the corrected content headers.
Serve resources with the proper media types (a.k.a. MIME types)
Associates media types with one or more extensions to make sure the resources will be served appropriately.
Servers should use text/javascript for JavaScript resources as indicated in the HTML specification
<IfModule mod_expires.c> # Data interchange AddType application/atom+xml atom AddType application/json json map topojson AddType application/ld+json jsonld AddType application/rss+xml rss AddType application/geo+json geojson AddType application/rdf+xml rdf AddType application/xml xml # JavaScript AddType text/javascript js mjs # Manifest files AddType application/manifest+json webmanifest AddType application/x-web-app-manifest+json webapp AddType text/cache-manifest appcache # Media files AddType audio/mp4 f4a f4b m4a AddType audio/ogg oga ogg opus AddType image/bmp bmp AddType image/svg+xml svg svgz AddType image/webp webp AddType video/mp4 f4v f4p m4v mp4 AddType video/ogg ogv AddType video/webm webm AddType image/x-icon cur ico # HEIF Images AddType image/heic heic AddType image/heif heif # HEIF Image Sequence AddType image/heics heics AddType image/heifs heifs # AVIF Images AddType image/avif avif # AVIF Image Sequence AddType image/avis avis # WebAssembly AddType application/wasm wasm # Web fonts AddType font/woff woff AddType font/woff2 woff2 AddType application/vnd.ms-fontobject eot AddType font/ttf ttf AddType font/collection ttc AddType font/otf otf # Other AddType application/octet-stream safariextz AddType application/x-bb-appworld bbaw AddType application/x-chrome-extension crx AddType application/x-opera-extension oex AddType application/x-xpinstall xpi AddType text/calendar ics AddType text/markdown markdown md AddType text/vcard vcard vcf AddType text/vnd.rim.location.xloc xloc AddType text/vtt vtt AddType text/x-component htc </IfModule>
Set the default Charset attribute
Every piece of content on the web has a character set. Most, if not all, the content is UTF-8 Unicode.
Use AddDefaultCharset to serve all resources labeled as text/html
or text/plain
with the UTF-8
charset.
<IfModule mod_mime.c> AddDefaultCharset utf-8 </IfModule>
Serve the following file types with the charset
parameter set to UTF-8
using the AddCharset directive available in mod_mime
.
<IfModule mod_mime.c> AddCharset utf-8 .appcache .bbaw .css .htc .ics .js .json .manifest .map .markdown .md .mjs .topojson .vtt .vcard .vcf .webmanifest .xloc </IfModule>
Mod_rewrite and the RewriteEngine directives
mod_rewrite provides a way to modify incoming URL requests, dynamically, based on regular expression rules. This allows you to map arbitrary URLs onto your internal URL structure in any way you like.
It supports an unlimited number of rules and an unlimited number of attached rule conditions for each rule to provide a really flexible and powerful URL manipulation mechanism. The URL manipulations can depend on various tests: server variables, environment variables, HTTP headers, timestamps, external database lookups, and various other external programs or handlers, can be used to achieve granular URL matching.
Enable mod_rewrite
The basic pattern to enable mod_rewrite
is a pre-requisite for all other tasks that use.
The required steps are:
- Turn on the rewrite engine (this is necessary in order for the
RewriteRule
directives to work) as documented in the RewriteEngine documentation - Enable the
FollowSymLinks
option if it isn’t already. See Core Options documentation - If your web host doesn’t allow the
FollowSymlinks
option, you need to comment it out or remove it, and then uncomment theOptions +SymLinksIfOwnerMatch
line, but be aware of the performance impact- Some cloud hosting services will require you set
RewriteBase
- See Rackspace FAQ and the HTTPD documentation
- Depending on how your server is set up, you may also need to use the
RewriteOptions
directive to enable some options for the rewrite engine
- Some cloud hosting services will require you set
<IfModule mod_rewrite.c> RewriteEngine On Options +FollowSymlinks # Options +SymLinksIfOwnerMatch # RewriteBase / # RewriteOptions <options> </IfModule>
Forcing https
These Rewrite rules will redirect from the http://
insecure version to the https://
secure version of the URL as described in the Apache HTTPD wiki.
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] </IfModule>
If you’re using cPanel AutoSSL or the Let’s Encrypt webroot method to create your SSL certificates, it will fail to validate the certificate if validation requests are redirected to HTTPS. Turn on the condition(s) you need.
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} !=on RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/ RewriteCond %{REQUEST_URI} !^/.well-known/cpanel-dcv/[w-]+$ RewriteCond %{REQUEST_URI} !^/.well-known/pki-validation/[A-F0-9]{32}.txt(?: Comodo DCV)?$ RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] </IfModule>
Redirecting from www. URLs
These directives will rewrite www.example.com
to example.com
.
You should not duplicate content in multiple origins (with and without www);This can cause SEO problems (duplicate content), and therefore, you should choose one of the alternatives and redirect the other one. You should also use Canonical URLs to indicate which URL should search engines crawl (if they support the feature).
Set %{ENV:PROTO}
variable, to allow rewrites to redirect with the appropriate schema automatically (http or https).
The rule assumes by default that both HTTP and HTTPS environments are available for redirection.
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} =on RewriteRule ^ - [E=PROTO:https] RewriteCond %{HTTPS} !=on RewriteRule ^ - [E=PROTO:http] RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC] RewriteRule ^ %{ENV:PROTO}://%1%{REQUEST_URI} [R=301,L] </IfModule>
Inserting the www. at the beginning of URLs
These rules will insert www.
at the beginning of a URL. It’s important to note that you should never make the same content available under two different URLs.
This can cause SEO problems (duplicate content), and therefore, you should choose one of the alternatives and redirect the other one. For search engines that support them you should use Canonical URLs to indicate which URL should search engines crawl.
Set %{ENV:PROTO}
variable, to allow rewrites to redirect with the appropriate schema automatically (http or https).
The rule assumes by default that both HTTP and HTTPS environments are available for redirection. If your SSL certificate could not handle one of the domains used during redirection, you should turn the condition on.
The following might not be a good idea if you use «real» subdomains for certain parts of your website.
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} =on RewriteRule ^ - [E=PROTO:https] RewriteCond %{HTTPS} !=on RewriteRule ^ - [E=PROTO:http] RewriteCond %{HTTPS} !=on RewriteCond %{HTTP_HOST} !^www. [NC] RewriteCond %{SERVER_ADDR} !=127.0.0.1 RewriteCond %{SERVER_ADDR} !=::1 RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] </IfModule>
Frame Options
The example below sends the X-Frame-Options
response header with DENY as the value, informing browsers not to display the content of the web page in any frame to protect the website against clickjacking.
This might not be the best setting for everyone. You should read about the other two possible values for the X-Frame-Options
header: SAMEORIGIN
and ALLOW-FROM
.
While you could send the X-Frame-Options
header for all of your website’s pages, this has the potential downside that it forbids even any framing of your content (e.g.: when users visit your website using a Google Image Search results page).
Nonetheless, you should ensure that you send the X-Frame-Options
header for all pages that allow a user to make a state-changing operation (e.g., pages that contain one-click purchase links, checkout, or bank-transfer confirmation pages, pages that make permanent configuration changes, etc.).
<IfModule mod_headers.c> Header always set X-Frame-Options "DENY" "expr=%{CONTENT_TYPE} =~ m#text/html#i" </IfModule>
Content Security Policy (CSP)
CSP (Content Security Policy) mitigates the risk of cross-site scripting and other content-injection attacks by setting a Content Security Policy
which allows trusted sources of content for your website.
There is no policy that fits all websites, the example below is meant as guidelines for you to modify for your site.
The example policy below:
To make your CSP implementation easier, you can use an online CSP header generator. You should also use a validator to make sure your header does what you want it to do.
<IfModule mod_headers.c> Content-Security-Policy "default-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests" "expr=%{CONTENT_TYPE} =~ m#text/(html|javascript)|application/pdf|xml#i" </IfModule>
Directory access
This directive will prevent access to directories that don’t have an index file present in whatever format the server is configured to use, like index.html
, or index.php
.
<IfModule mod_autoindex.c> Options -Indexes </IfModule>
In Macintosh and Linux systems, files that begin with a period are hidden from view but not from access if you know their name and location. These types of files usually contain user preferences or the preserved state of a utility, and can include rather private places like, for example, the .git
or .svn
directories.
The .well-known/
directory represents the standard (RFC 5785) path prefix for «well-known locations» (e.g.: /.well-known/manifest.json
, /.well-known/keybase.txt
), and therefore, access to its visible content should not be blocked.
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_URI} "!(^|/).well-known/([^./]+./?)+$" [NC] RewriteCond %{SCRIPT_FILENAME} -d [OR] RewriteCond %{SCRIPT_FILENAME} -f RewriteRule "(^|/)." - [F] </IfModule>
Block access to files with sensitive information
Block access to backup and source files that may be left by some text editors and can pose a security risk when anyone has access to them.
Update the <FilesMatch>
regular expression in the following example to include any files that might end up on your production server and can expose sensitive information about your website. These files may include: configuration files or files that contain metadata about the project among others.
<IfModule mod_authz_core.c> <FilesMatch "(^#.*#|.(bak|conf|dist|fla|in[ci]|log|orig|psd|sh|sql|sw[op])|~)$"> Require all denied </FilesMatch> </IfModule>
HTTP Strict Transport Security (HSTS)
If a user types example.com
in their browser, even if the server redirects them to the secure version of the website, that still leaves a window of opportunity (the initial HTTP connection) for an attacker to downgrade or redirect the request.
The following header ensures that a browser only connects to your server via HTTPS, regardless of what the users type in the browser’s address bar.
Be aware that Strict Transport Security is not revokable, and you must ensure being able to serve the site over HTTPS for as long as you’ve specified in the max-age
directive. If you don’t have a valid TLS connection anymore (e.g. due to an expired TLS certificate) your visitors will see an error message even when attempting to connect over HTTP.
<IfModule mod_headers.c> # Header always set Strict-Transport-Security "max-age=16070400; includeSubDomains" "expr=%{HTTPS} == 'on'" # (1) Enable your site for HSTS preload inclusion. # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" "expr=%{HTTPS} == 'on'" </IfModule>
Prevent some browsers from MIME-sniffing the response
- Restricts all fetches by default to the origin of the current website by setting the
default-src
directive to'self'
— which acts as a fallback to all Fetch directives.- This is convenient as you do not have to specify all Fetch directives that apply to your site, for example:
connect-src 'self'; font-src 'self'; script-src 'self'; style-src 'self'
, etc - This restriction also means that you must explicitly define from which site(s) your website is allowed to load resources from, otherwise it will be restricted to the same origin as the page making the request
- This is convenient as you do not have to specify all Fetch directives that apply to your site, for example:
- Disallows the
<base>
element on the website. This is to prevent attackers from changing the locations of resources loaded from relative URLs- If you want to use the
<base>
element, then usebase-uri 'self'
instead
- If you want to use the
- Only allows form submissions are from the current origin with:
form-action 'self'
- Prevents all websites (including your own) from embedding your webpages within e.g. the
<iframe>
or<object>
element by setting:frame-ancestors 'none'
.- The
frame-ancestors
directive helps avoid clickjacking attacks and is similar to theX-Frame-Options
header - Browsers that support the CSP header will ignore
X-Frame-Options
ifframe-ancestors
is also specified
- The
- Forces the browser to treat all the resources that are served over HTTP as if they were loaded securely over HTTPS by setting the
upgrade-insecure-requests
directiveupgrade-insecure-requests
does not ensure HTTPS for the top-level navigation. If you want to force the website itself to be loaded over HTTPS you must include theStrict-Transport-Security
header
- Includes the
Content-Security-Policy
header in all responses that are able to execute scripting. This includes the commonly used file types: HTML, XML and PDF documents. Although JavaScript files can not execute scripts in a «browsing context», they are included to target web workers
Some older browsers would try and guess the content type of a resource, even when it isn’t properly set up on the server configuration. This reduces exposure to drive-by download attacks and cross-origin data leaks.
<IfModule mod_headers.c> Header always set X-Content-Type-Options "nosniff" </IfModule>
Referrer Policy
We include the Referrer-Policy
header in responses for resources that are able to request (or navigate to) other resources.
This includes commonly used resource types: HTML, CSS, XML/SVG, PDF documents, scripts, and workers.
To prevent referrer leakage entirely, specify the no-referrer
value instead. Note that the effect could negatively impact analytics tools.
Use services like the ones below to check your Referrer Policy:
- securityheaders.com
- Mozilla Observatory
<IfModule mod_headers.c> Header always set Referrer-Policy "strict-origin-when-cross-origin" "expr=%{CONTENT_TYPE} =~ m#text/(css|html|javascript)|application/pdf|xml#i" </IfModule>
Disable TRACE HTTP Method
The TRACE method, while seemingly harmless, can be successfully leveraged in some scenarios to steal legitimate users’ credentials. See A Cross-Site Tracing (XST) attack and OWASP Web Security Testing Guide
Modern browsers now prevent TRACE requests made via JavaScript, however, other ways of sending TRACE requests with browsers have been discovered, such as using Java.
If you have access to the main server configuration file, use the TraceEnable
directive instead.
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_METHOD} ^TRACE [NC] RewriteRule .* - [R=405,L] </IfModule>
Some frameworks like PHP and ASP.NET set an X-Powered-By
header that contains information about them (e.g.: their name, version number)
This header doesn’t provide any value, and in some cases, the information it provides can expose vulnerabilities
<IfModule mod_headers.c> Header unset X-Powered-By Header always unset X-Powered-By </IfModule>
If you can, you should disable the X-Powered-By
header from the language/framework level (e.g.: for PHP, you can do that by setting the following in php.ini
.
Prevent Apache from adding a trailing footer line containing information about the server to the server-generated documents (e.g.: error messages, directory listings, etc.). See ServerSignature Directive for more information on what the server signature provides and the ServerTokens Directive for information about configuring the information provided in the signature.
Some proxies and security software mangle or strip the Accept-Encoding
HTTP header. See Pushing Beyond Gzipping for a more detailed explanation.
<IfModule mod_deflate.c> <IfModule mod_setenvif.c> <IfModule mod_headers.c> SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)s*,?s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding </IfModule> </IfModule> </IfModule>
Compress all output labeled with one of the following media types using the AddOutputFilterByType Directive.
<IfModule mod_deflate.c> <IfModule mod_filter.c> AddOutputFilterByType DEFLATE "application/atom+xml" "application/javascript" "application/json" "application/ld+json" "application/manifest+json" "application/rdf+xml" "application/rss+xml" "application/schema+json" "application/geo+json" "application/vnd.ms-fontobject" "application/wasm" "application/x-font-ttf" "application/x-javascript" "application/x-web-app-manifest+json" "application/xhtml+xml" "application/xml" "font/eot" "font/opentype" "font/otf" "font/ttf" "image/bmp" "image/svg+xml" "image/vnd.microsoft.icon" "text/cache-manifest" "text/calendar" "text/css" "text/html" "text/javascript" "text/plain" "text/markdown" "text/vcard" "text/vnd.rim.location.xloc" "text/vtt" "text/x-component" "text/x-cross-domain-policy" "text/xml" </IfModule> </IfModule>
Map the following filename extensions to the specified encoding type using AddEncoding so Apache can serve the file types with the appropriate Content-Encoding
response header (this will NOT make Apache compress them!). If these files types were served without an appropriate Content-Encoding
response header, client applications (e.g.: browsers) wouldn’t know that they first need to uncompress the response, and thus, wouldn’t be able to understand the content.
<IfModule mod_deflate.c> <IfModule mod_mime.c> AddEncoding gzip svgz </IfModule> </IfModule>
Cache expiration
Serve resources with a far-future expiration date using the mod_expires module, and Cache-Control and Expires headers.
<IfModule mod_expires.c> ExpiresActive on ExpiresDefault "access plus 1 month" # CSS ExpiresByType text/css "access plus 1 year" # Data interchange ExpiresByType application/atom+xml "access plus 1 hour" ExpiresByType application/rdf+xml "access plus 1 hour" ExpiresByType application/rss+xml "access plus 1 hour" ExpiresByType application/json "access plus 0 seconds" ExpiresByType application/ld+json "access plus 0 seconds" ExpiresByType application/schema+json "access plus 0 seconds" ExpiresByType application/geo+json "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType text/calendar "access plus 0 seconds" ExpiresByType text/xml "access plus 0 seconds" # Favicon (cannot be renamed!) and cursor images ExpiresByType image/vnd.microsoft.icon "access plus 1 week" ExpiresByType image/x-icon "access plus 1 week" # HTML ExpiresByType text/html "access plus 0 seconds" # JavaScript ExpiresByType text/javascript "access plus 1 year" # Manifest files ExpiresByType application/manifest+json "access plus 1 week" ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" ExpiresByType text/cache-manifest "access plus 0 seconds" # Markdown ExpiresByType text/markdown "access plus 0 seconds" # Media files ExpiresByType audio/ogg "access plus 1 month" ExpiresByType image/bmp "access plus 1 month" ExpiresByType image/gif "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" ExpiresByType image/webp "access plus 1 month" # PNG and animated PNG ExpiresByType image/apng "access plus 1 month" ExpiresByType image/png "access plus 1 month" # HEIF Images ExpiresByType image/heic "access plus 1 month" ExpiresByType image/heif "access plus 1 month" # HEIF Image Sequence ExpiresByType image/heics "access plus 1 month" ExpiresByType image/heifs "access plus 1 month" # AVIF Images ExpiresByType image/avif "access plus 1 month" # AVIF Image Sequence ExpiresByType image/avis "access plus 1 month" ExpiresByType video/mp4 "access plus 1 month" ExpiresByType video/ogg "access plus 1 month" ExpiresByType video/webm "access plus 1 month" # WebAssembly ExpiresByType application/wasm "access plus 1 year" # Web fonts # Collection ExpiresByType font/collection "access plus 1 month" # Embedded OpenType (EOT) ExpiresByType application/vnd.ms-fontobject "access plus 1 month" ExpiresByType font/eot "access plus 1 month" # OpenType ExpiresByType font/opentype "access plus 1 month" ExpiresByType font/otf "access plus 1 month" # TrueType ExpiresByType application/x-font-ttf "access plus 1 month" ExpiresByType font/ttf "access plus 1 month" # Web Open Font Format (WOFF) 1.0 ExpiresByType application/font-woff "access plus 1 month" ExpiresByType application/x-font-woff "access plus 1 month" ExpiresByType font/woff "access plus 1 month" # Web Open Font Format (WOFF) 2.0 ExpiresByType application/font-woff2 "access plus 1 month" ExpiresByType font/woff2 "access plus 1 month" # Other ExpiresByType text/x-cross-domain-policy "access plus 1 week" </IfModule>
Содержание:
- Способы вывода ошибок PHP
- Виды ошибок в файле .htaccess
- Как включить вывод ошибок через .htaccess
- Примеры практического применения
- Включение журналирования ошибок PHP в .htaccess
- Дополнительные способы вывода ошибок PHP
Ошибки в коде — неотъемлемая часть любого процесса разработки. Чтобы понять, почему не выполняется скрипт, необходимо вывести error-логи PHP на экран.
Следует помнить, что в публичной версии сайта вывод ошибок на экран должен быть отключён.
- Через файл .htaccess, отвечающий за дополнительные параметры сервера Apache.
- Непосредственно через PHP-скрипт.
- Через файл php.ini, содержащий настройки интерпретатора PHP.
Преимущества вывода ошибок в файле .htaccess
- Широкий охват. Параметры распространяются на все элементы дочерних поддиректорий.
- Быстрота и удобство. Обработка ошибок настраивается в несколько команд и в одном месте.
Вывод ошибок на экран лучше делать через файл .htaccess, особенно когда PHP-файлов несколько. Поэтому далее разберём этот способ подробнее.
Виды ошибок PHP в файле .htaccess
- E_ALL — все виды ошибок, кроме E_STRICT до PHP 5.4.0.
- E_ERROR — фатальные ошибки, прекращающие работу скрипта.
- E_WARNING — ошибки-предупреждения. Не являются фатальными, поэтому не вызывают прекращение работы скрипта.
- E_PARSE — ошибки разбора. Могут возникать только во время компиляции.
- E_NOTICE — уведомления о нарушении времени выполнения скрипта.
- E_CORE_ERROR — фатальная ошибка обработчика. Генерируется ядром во время запуска PHP-скрипта.
- E_CORE_WARNING — предупреждения компиляции, возникающие при запуске PHP-скрипта.
- E_COMPILE_ERROR — фатальные ошибки, возникающие на этапе компиляции.
- E_COMPILE_WARNING — предупреждение компилятора PHP-скриптов.
- E_USER_ERROR — ошибки, сгенерированные пользователями.
- E_USER_WARNING — предупреждения, сгенерированные пользователями.
- E_USER_NOTICE — уведомления, сгенерированные пользователями.
Как включить вывод ошибок через .htaccess
Файл .htaccess должен находиться в корневой директории сайта (например, «public_html»). Отредактировать его можно с помощью проводника, доступного в панели хостинга.
Примечание. Если файла .htaccess нет, то его необходимо создать.
Включить отображение ошибок PHP и настроить фильтрацию их вывода можно двумя директивами: «display_errors» и «error_reporting». Первая отвечает за состояние режима показа ошибок («On» или «Off»), а вторая задаёт глубину отображения.
Показать ошибки PHP на экране можно с помощью следующего кода:
php_flag display_errors on php_value error_reporting -1
После сохранения изменённого файла, следует обновить страницу.
Примеры практического применения
Используя указанный код, можно быстро включить или отключить вывод ошибок, а также настроить различные конфигурации для разных режимов работы.
Следующий код скроет ошибки PHP с экрана:
# скрыть ошибки php php_flag display_startup_errors off php_flag display_errors off php_flag html_errors off php_value docref_root 0 php_value docref_ext 0
Иногда нужно фиксировать сбои, но нет возможности вывести ошибки PHP на экран (например, сайт работает в реальном времени). Для этого можно перенаправить вывод информации в лог-файл с помощью следующего кода:
# включить ведение журнала ошибок PHP php_flag log_errors on # месторасположение журнала ошибок PHP php_value error_log /var/www/имя_пользователя/data/www/ваш_www-домен/
Чтобы обработка ошибок в .htaccess выполнялась безопасно надо обязательно защитить папку с log-файлами от внешнего доступа при помощи следующего кода:
# запретить доступ к журналу ошибок PHP <Files PHP_errors.log> Order allow,deny Deny from all Satisfy All </Files>
Можно также настроить фильтрацию. Флаг «integer» указывает на глубину вывода данных (уровень показа). Значение «0» не выведет никаких ошибок. Комбинация «8191» запишет в log-файл сбои всех уровней.
# общая директива для фильтрации ошибок php php_value error_reporting integer
Чтобы текст ошибок не обрезался, можно установить максимальный размер на строку:
# общая директива для установки максимального размера строки log_errors_max_len integer
Выключение записи повторяющихся ошибок сократит объём поступающих данных и улучшит восприятие информации:
# отключить запись повторяющихся ошибок php_flag ignore_repeated_errors on php_flag ignore_repeated_source on
В результате настройки .htaccess для сайта, находящегося в публичном доступе, должны выглядеть так:
# обработка ошибок PHP для публичного ресурса php_flag display_startup_errors off php_flag display_errors off php_flag html_errors off php_flag log_errors on php_flag ignore_repeated_errors off php_flag ignore_repeated_source off php_flag report_memleaks on php_flag track_errors on php_value docref_root 0 php_value docref_ext 0 php_value error_reporting -1 php_value log_errors_max_len 0 <Files /home/path/public_html/domain/PHP_errors.log> Order allow,deny Deny from all Satisfy All </Files>
Во время разработки или отладки файл .htaccess должен содержать следующий код:
# Обработка ошибок PHP во время разработки php_flag display_startup_errors on php_flag display_errors on php_flag html_errors on php_flag log_errors on php_flag ignore_repeated_errors off php_flag ignore_repeated_source off php_flag report_memleaks on php_flag track_errors on php_value docref_root 0 php_value docref_ext 0 php_value error_log /home/path/public_html/domain/PHP_errors.log # [see footnote 3] # php_value error_reporting 999999999 php_value error_reporting -1 php_value log_errors_max_len 0 <Files /home/path/public_html/domain/PHP_errors.log> Order allow,deny Deny from all Satisfy All </Files>
Включение журналирования ошибок PHP в .htaccess
Когда отображение ошибок на странице выключено, необходимо запустить их журналирование следующим кодом:
# включение записи PHP ошибок
php_flag log_errors onphp_value error_log /home/path/public_html/domain/PHP_errors.log
Примечание. Вместо «/home/path/public_html/domain/PHP_errors.log» нужно подставить собственный путь до директории, в которой будет вестись журнал ошибок.
Чтобы запретить доступ к журналу извне, нужно добавить следующий код:
# предотвращаем доступ к логу PHP ошибок <Files PHP_errors.log> Order allow,deny Deny from all Satisfy All </Files>
Дополнительные способы вывода ошибок PHP
Можно добавить оператор «@», чтобы запретить показ ошибок в конкретной инструкции PHP:
$value = @$var[$key];
Вывод ошибок в PHP-скрипте
Чтобы выводить все ошибки, нужно в начале скрипта прописать:
error_reporting(-1);
Если необходимо отображать ошибки PHP только из определённого места скрипта, то можно использовать следующий код:
ini_set('display_errors', 'On'); // сообщения с ошибками будут показываться error_reporting(E_ALL); // E_ALL - отображаем ВСЕ ошибки $value = $var[$key]; // пример ошибки ini_set('display_errors', 'Off'); // теперь сообщений НЕ будет
Примечание. Если заменить значения «On» и «Off» в первой и последней строках на противоположные, то на конкретном участке кода ошибки выводиться не будут.
Через файл php.ini
Включить или выключить показ ошибок на всём сайте/хостинге также можно с помощью файла «php.ini», в котором нужно изменить два следующих параметра:
error_reporting = E_ALL display_errors On
Первая строка отвечает за фильтрацию ошибок (в данном случае показываться будут все типы сбоев), а вторая активирует их отображение на экране. После изменений этого файла необходимо перезапустить сервер Apache.
Хостинг-провайдеры нередко отключают или блокируют вывод всех ошибок и предупреждений. Такие ограничения вводятся не просто так. Дело в том, что на рабочих серверах крайне не рекомендуется держать ошибки в открытом доступе. Информация о неисправностях может стать «наживкой» для злоумышленников.
При этом в процессе разработки сайтов и скриптов, очень важно отслеживать возникающие предупреждения. Знать о сбоях и неисправностях также важно и системным администраторам — это позволяет предотвратить проблемы на сайте или сервере.
Самый оптимальный вариант — не просто скрыть показ ошибок, но и настроить запись о них в логах. Это позволит отслеживать предупреждения и не подвергать сервер угрозе.
В статье мы расскажем, как включить и отключить через .htaccess вывод ошибок php, а также двумя другими способами — через скрипт PHP и через файл php.ini.
Обратите внимание: в некоторых случаях изменение настроек вывода возможно только через обращение в техническую поддержку хостинга.
Через .htaccess
Перейдите в каталог сайта и откройте файл .htaccess.
Вариант 1. Чтобы включить вывод, добавьте следующие строки:
php_flag display_startup_errors on
php_flag display_errors on
php_flag html_errors on
Чтобы отключить ошибки PHP htaccess, введите команду:
php_flag display_startup_errors off
php_flag display_errors off
php_flag html_errors off
Также выключить .htaccess display errors можно командой:
php_flag display_startup_errors off
php_flag display_errors off
php_flag html_errors off
php_value docref_root 0
php_value docref_ext 0
Через логи PHP
Если вам нужно проверить или выключить ошибки только в определенных файлах, это можно сделать с помощью вызова PHP-функций.
Вариант 1. Чтобы включить вывод, используйте команду error_reporting. В зависимости от типа ошибок, которые вы хотите увидеть, подставьте нужное значение. Например, команда для вывода всех ошибок будет выглядеть так:
А для всех типов, исключая тип Notice, так:
error_reporting(E_ALL & ~E_NOTICE)
Чтобы отключить вывод, введите команду:
Чтобы отключить логирование повторяющихся ошибок, введите:
# disable repeated error logging
php_flag ignore_repeated_errors on
php_flag ignore_repeated_source on
Вариант 2. Чтобы проверить конкретный кусок кода, подойдет команда ниже. В зависимости от типа ошибок, которые вы хотите увидеть, в скобках подставьте нужное значение. Например, команда для вывода всех ошибок будет выглядеть так:
ini_set('display_errors', 'On')
error_reporting(E_ALL)
После этого в консоли введите:
ini_set('display_errors', 'Off')
Вариант 3. Ещё один из вариантов подключения через скрипт:
php_flag display_startup_errors on
php_flag display_errors on
Для отключения укажите:
php_flag display_startup_errors off
php_flag display_errors off
Вариант 4. Чтобы настроить вывод с логированием через конфигурацию веб-сервера, введите:
- для Apache —
ErrorLog «/var/log/apache2/my-website-error.log»
, - для Nginx —
error_log /var/log/nginx/my-website-error.log
.
Подробнее о других аргументах читайте в документации на официальном сайте php.net.
Через файл php.ini
Настроить отслеживание также можно через файл php.ini. Этот вариант подойдет, когда отображение или скрытие ошибок нужно настроить для всего сайта или кода. Обратите внимание: возможность настройки через файл php.ini есть не у всех, поскольку некоторые хостинг-провайдеры частично или полностью закрывают доступ к файлу.
Вариант 1. Если у вас есть доступ, включить вывод можно командой:
После этого нужно перезагрузить сервер:
sudo apachectl -k graceful
Вариант 2. Чтобы включить вывод, используйте команду error_reporting. В зависимости от типа ошибок, которые вы хотите увидеть, после знака = подставьте нужное значение. Например, команда для вывода всех ошибок будет выглядеть так:
error_reporting = E_ALL
display_errors On
После ввода перезагрузите сервер:
sudo apachectl -k graceful
Чтобы скрыть отображение, во второй строке команды укажите Оff вместо On:
Теперь вы знаете, как настроить не только через PHP и php.ini, но и через htaccess отображение ошибок.
An htaccess file allows you to change
the configuration of your server
0:00
at a directory level.
0:05
This is often the best choice
when on a shared server
0:07
where you don’t have access
to the php.ini file.
0:10
This will overwrite what’s in your php.ini
file or other configuration files.
0:14
We can use this to turn on, off, or
change the level of errors to display.
0:19
Keep in mind .htaccess
files are hidden files and
0:25
can sometimes be tricky to work with.
0:29
If you’re not sure how to work with hidden
files, check the teachers’ notes for
0:31
more information.
0:35
If you are using this method,
you should be aware
0:37
that the htaccess file is often used for
other things such as redirection.
0:40
It is also another file used right along
0:45
with the rest of the files
on your application.
0:48
Because of these concerns
you should be careful about
0:51
committing this file to your
version control system.
0:54
Most likely, you do not want the same
settings on dev and production.
0:57
Let’s go into work spaces and
see the htaccess file in action.
1:02
One of the things I have included in
this project are a couple error pages.
1:07
To start with, let’s preview errors1.php.
1:11
Click the preview icon that looks
like an eye in the top right corner.
1:14
Preview always takes us to
the default page of our project.
1:19
If there is no default page,
it gives us a list of pages.
1:24
We can click on errors1.php.
1:28
We’ll see that all we get is a blank
white page, not very helpful.
1:32
And if we go to errors2.php
it gives us a server error.
1:37
Again, no help.
1:41
Let’s go into the htaccess file and
turn on errors.
1:43
In workspaces we can’t edit
an htaccess file directly,
1:49
because it doesn’t understand
the .htaccess as a file extension.
1:53
But if we rename it
briefly to htaccess.txt,
1:58
then we can open the file,
edit it, end then rename it back.
2:01
Because Workspaces is set up
as a development environment,
2:14
it is set to display
all errors by default.
2:17
We’re using the htaccess
file to turn off the errors.
2:20
In the htaccess file that’s included in
Workspace, you’ll see quite a few lines.
2:24
All the lines that start with
a pound sign are just comments
2:29
telling you what’s going on.
2:33
So there are really only
four lines of actual code.
2:34
This is not PHP code.
2:38
The htaccess file is a configuration
file for Apache, our web server.
2:40
We’ll step through each line.
2:45
The first line tells our server,
Apache, to display startup errors.
2:48
Our second line tells our server
to display all other errors.
2:53
The third line specifies
reporting of all PHP errors.
2:58
And the fourth line turns on HTML markup
of errors making them easier to read.
3:03
If you want to go into this in a little
more depth check out the teacher’s notes.
3:10
We’ll change all of the off to on.
3:16
We’ll also change
error_reporting to minus one.
3:25
That means everything.
3:29
If we save this file
we can then rename it.
3:31
Back to .htaccess.
3:40
Now we can refresh our browser
to see our parse error.
3:43
It tells us that there’s an unexpected
closing curly brace at line nine.
3:47
It’s expecting a comma or a semicolon.
3:52
Let’s go check it out.
3:56
Errors two on line nine.
3:59
Because of the way PHP pretty much ignores
whitespace, it doesn’t actually generate
4:03
an error until it encounters
something that is incorrect.
4:08
So we need to look at the line
directly before line nine.
4:11
Since line eight is a blank line,
that means we want line seven.
4:16
We can see that we are indeed
missing a semicolon.
4:21
Let’s fix that.
4:24
Now let’s refresh our browser.
4:29
Awesome.
4:32
No more errors.
4:33
We’ll fix our other
page in the next video.
4:35
If you don’t have access to your
server this is often your best option.
4:38
Just be careful that your development
settings do not get pushed to production.
4:42
This brings us to our third option,
your own PHP code.
4:48
Table of contents
- .htaccess Basics
-
Error Handling
- Client Request Errors
- Server Errors
- Password Protection with .htaccess
- Enabling Server Side Includes (SSI)
- IP Blacklisting and IP Whitelisting
- Block Users by Referrer
- Blocking Bots and Web Scrapers
- Specifying a Default File for a Directory
- URL Redirects and URL Rewriting
- Hiding Your .htaccess File
- Enabling MIME types
- Block Hotlinking
- Disable or Enable Index
- Scripts as Source Code
- Configuring PHP Settings
- When Not to Use .htaccess
-
Troubleshooting
- Bad Filename
- .htaccess Disabled, or Partly Disabled
- Conflicting or Overridden Directives
- My .htaccess configuration
- .htaccess Protection For POST Abuse (WordPress)
This guide was built to serve as a comprehensive resource to using .htaccess.
.htaccess Basics
What is .htaccess
?
The .htaccess
file is a configuration file that affects how a web server responds to various requests. It is supported by several web servers, including the popular Apache software used by most web hosting providers.
.htaccess
files operate at the level of a directory, allowing them to override global configuration settings of .htaccess
directives higher in the directory tree.
Why is it called .htaccess
?
These files were first used to control user access on a per-directory basis. Using a subset of Apache’s http.conf
settings directives, it allowed a system administrator to restrict access to individual directories to users with a name and password specified in an accompanying .htpasswd
file.
While .htaccess
files are still used for this, they are also used for a number of other things which we’ll cover in this guide.
Where is the .htaccess
file?
In theory, every folder (directory) on your server could have one. Generally, though, there is one in your web root folder — that’s the folder that holds all the content of your website, and is usually labeled something like public_html
, www
or httpdocs
.
If you have a single directory that contains multiple website subdirectories, there will usually be an .htaccess
file in the main root directory and also one in each subdirectory (/sitename
).
Why can’t I find my .htaccess
file?
On most file systems, file names that begin with a dot ( .
) are hidden files. This means they are not typically visible by default.
But they aren’t hard to get to. Your FTP client or File Manager should have a setting for “show hidden files”. This will be in different places in different programs, but is usually in “Preferences”, “Settings”, or “Folder Options”. Sometime you’ll find it in the “View” menu.
What if I don’t have an .htaccess
file?
First of all, make sure that you have turned on “show hidden files” (or its equivalent), so that you can be sure you actually don’t have one. Often, .htaccess
files are created automatically, so you will usually have one. But this isn’t always the case.
If you really don’t have one, you can easily create one:
- Start a new file in a plain text editor.
- Save it in
ASCII
format (notUTF-8
or anything else) as.htaccess
.- Make sure that it isn’t
htaccess.txt
or something like that. The file should have only the name.htaccess
with no additional file extension.
- Make sure that it isn’t
- Upload it to the appropriate directory via FTP or your browser-based file manager.
Error Handling
Using .htaccess
files to specify error documents is very simple, one of the simplest things you can do with this feature.
What is an error code?
When a request is made to a web server, it tries to respond to that request, usually by delivering a document (in the case of HTML pages), or by accessing an application and returning the output (in the case of Content Management Systems and other web apps).
If something goes wrong with this, an error is generated. Different types of errors have different error codes. You are probably familiar with the 404
error, which is returned if the document cannot be found on the server.
There are many other error codes that a server can respond with.
Client Request Errors
- 400 — Bad Request
- 401 — Authorization Required
- 402 — Payment Required (not used yet)
- 403 — Forbidden
- 404 — Not Found
- 405 — Method Not Allowed
- 406 — Not Acceptable (encoding)
- 407 — Proxy Authentication Required
- 408 — Request Timed Out
- 409 — Conflicting Request
- 410 — Gone
- 411 — Content Length Required
- 412 — Precondition Failed
- 413 — Request Entity Too Long
- 414 — Request URI Too Long
- 415 — Unsupported Media Type
Server Errors
- 500 — Internal Server Error
- 501 — Not Implemented
- 502 — Bad Gateway
- 503 — Service Unavailable
- 504 — Gateway Timeout
- 505 — HTTP Version Not Supported
What happens by default?
If you don’t specify any type of error handling, the server will simply return the message to the browser, and the browser will display a generic error message to the user. This is usually not ideal.
Specifying Error Documents
Create an HTML document for each error code you want to handle. You can name these whatever you like, but it’s helpful to name them something that will help you remember what they’re for, like not-found.html
or simply 404.html
.
Then, in the .htaccess
file, specify which document to use with each type of error.
ErrorDocument 400 /errors/bad-request.html
ErrorDocument 401 /errors/auth-reqd.html
ErrorDocument 403 /errors/forbid.html
ErrorDocument 404 /errors/not-found.html
ErrorDocument 500 /errors/server-err.html
Notice that each directive is placed on its own line.
And that’s it. Very simple.
Alternatives to .htaccess
for error handling
Most content management systems (CMS) like WordPress, and most web apps, will have their own way of handling most of these errors codes.
Password Protection with .htaccess
The original purpose of .htaccess
files was to restrict access to certain directories on a per-user basis (hence the name, hypertext access). So we’ll look at that first.
.htpasswd
Usernames and passwords for the .htaccess
system are stored in a file name .htpasswd
.
These are stored each on a single line, in the form:
username:encryptedpassword
for example:
johnsmith:F418zSM0k6tGI
It’s important to realize that the password stored in the file isn’t the actual password used to log in. Rather it is a cryptographic hash of the password.
This means that the password has been run through an encryption algorithm, and the result is stored. When a user logs in, the plain-text password is entered and run through the same algorithm. If the input is the same, the passwords match and the user is granted access.
Storing passwords this way makes them more secure — if someone were to gain access to your .htpasswd
file, they would only see the hashed passwords, not the originals. And there is no way to reconstruct the originals from the hash — it is a one way encryption.
Several different hashing algorithms can be used:
- Secure Algorithms — Use one of these
- bcrypt — This is the most secure, but also the slowest to compute. It is supported by Apache and Nginx.
- md5 — This is the default hashing algorithm used by current versions of Apache. It is not supported by Nginx.
- Insecure Algorithms — Do not use these
- crypt() — This used to be the default hashing function, but it is not very secure.
- SHA and Salted SHA
Creating usernames and passwords on the command line
You can create an .htpasswd
file, and add username-password pairs to it, directly from the command line or SSH terminal.
The command for dealing with the .htpasswd
file is simply htpasswd
.
To create a new .htpasswd
file, use the command with the -c
option (for create), then type the path to the directory (not the URL, the actual path on the server). You can also include a user you want to add.
> htpasswd -c /usr/local/etc/.htpasswd johnsmith
This creates a new .htpasswd
file in the /etc/
directory, and adds a record for a user named johnsmith
. You will be prompted for a password, which will also be stored, using the md5 encryption.
If there is already an .htpasswd
file at the specified location, a new one is not created — the new user is simply appended to the existing file.
If you’d prefer to use the bcrypt hashing algorithm, use the -b
option.
Password hashing without the command line
If you don’t feel comfortable using the command line or SSH terminal (or if you don’t have access to it for some reason), you can simply create an .htpasswd
file and populate it using a plain text editor, and upload it via FTP or file manager.
But then you’ll need to encrypt your passwords somehow, since the htpasswd
command was taking care of that for you.
There are many .htpasswd
encryption utilities available online.
This gives you several options for hashing algorithm and password strength. You can simply copy-and-paste the output from there into your .htpasswd
file.
Where to keep your .htpasswd
file
You don’t need to have a separate .htpasswd
file for every .htaccess
file. In fact, you shouldn’t. Under most normal circumstances, you should have one for your entire web hosting account or main server directory.
The .htpasswd
file should not be in a publicly accessible directory — not Public_HTML
or www
or any subdirectory. It should be above those, in a folder that is only accessible from the server itself.
How to use .htpasswd
with .htaccess
Each directory can have its own .htaccess
file, with its own set of users which are allowed to access it.
If you want anyone (including non-logged-in users) to access the directory and its files, simply do nothing — that is the default.
To restrict access you need to add the following to the .htaccess
file:
AuthUserFile /usr/local/etc/.htpasswd
AuthName "Name of Secure Area"
AuthType Basic
<Limit GET POST>
require valid-user
</Limit>
The first line specifies the path and file name to your list of usernames and passwords. The second line specifies a name for the secured area. This can be anything you like. The third line specifies “Basic” authentication, which is what you usually need.
The <Limit>
tag specifies what is being limited (in this case, the ability to GET or POST to any file in the directory). Within the pair of <Limit>
tags is a list of who is allowed to access files.
In the above example, any valid user can access files. If you want to restrict access to a specific user or few users, you can name them.
AuthUserFile /usr/local/etc/.htpasswd
AuthName "Name of Secure Area"
AuthType Basic
<Limit GET POST>
require user johnsmith
require user janedoe
</Limit>
You can also put users into groups and allow access based on group. This is done by adding another file which specifies the groups.
The group file, which could be named (for example) .htgroups
looks like this:
admin: johnsmith janedoe
staff: jackdoe cindysmith
Then you can specify it in your .htaccess
file:
AuthUserFile /usr/local/etc/.htpasswd
AuthGroupFile /usr/local/etc/.htgroup
AuthName "Admin Area"
AuthType Basic
<Limit GET POST>
require group admin
</Limit>
Alternatives to .htpasswd
Using .htaccess
and .htpasswd
to resrict access to certain files on your server only really makes sense if you have a lot of static files. The feature was developed when web sites were usually a collection of HTML documents and related resources.
If you are using a content management system (CMS) like WordPress or Drupal, you can use the built-in user management features to restrict or grant access to content.
Enabling Server Side Includes (SSI)
What are Server Side Includes?
SSI, or Server Side Includes, is a light-weight scripting language used primarily to embed HTML documents into other HTML documents.
This makes it easy to re-use common elements, such as headers, footers, sidebars, and menus. You can think of it as a precursor to today’s templating and content management systems.
<!-- include virtual="header.shtml" -->
SSI also has conditional directives (if
, else
, etc.) and variables, making it a complete, if somewhat hard to use, scripting language. (Typically, any project more complicated than a handful of includes will cause a developer to choose a more robust language like PHP or Perl.)
Enabling SSI
Some web hosting servers will have Server Side Includes enabled by default. If not, you can enable it with your .htaccess
file, like so:
AddType text/html .shtml
AddHandler server-parsed .shtml
Options Indexes FollowSymLinks Includes
This should enable SSI for all files that have the .shtml
extension.
SSI on .html
files
If you want to enable SSI parsing on .html
files, you can add a directive to accomplish that:
AddHandler server-parsed .html
The benefit of doing this is that you can use SSI without letting the world know you are using it. Also, if you change implementations in the future, you can keep your .html
file extensions.
The downside of this is that every .html
file will be parsed with SSI. If you have a lot of .html
files that don’t actually need any SSI parsing, this can introduce a lot of unneeded server overhead, slowing down your page load times and using up CPU resources.
SSI on your Index page
If you don’t want to parse all .html
files, but you do want to use SSI on your index (home) page, you’ll need to specify that in your .htaccess
file.
That’s because when the web server is looking for a directory’s index page, it looks for index.html
, unless you tell it otherwise. If you aren’t parsing .html
files, you’ll need your index page to be named index.shtml
for SSI to work, and your server doesn’t know to look for that by default.
To enable that, simply add:
DirectoryIndex index.shtml index.html
This alerts the web server that the index.shtml
file is the main index file for the directory. The second parameter, index.html
is a backup, in case index.shtml
can’t be found.
IP Blacklisting and IP Whitelisting
You can use .htaccess
to block users from a specific IP address (blacklisting). This is useful if you have identified individual users from specific IP addresses which have caused problems.
You can also do the reverse, blocking everyone except visitors from a specific IP address (whitelisting). This is useful if you need to restrict access to only approved users.
Blacklisting by IP
To block specific IP addresses, simply use the following directive, with the appropriate IP addresses:
order allow,deny
deny from 111.22.3.4
deny from 789.56.4.
allow from all
The first line states that the allow
directives will be evaluated first, before the deny
directives. This means that allow from all
will be the default state, and then only those matching the deny
directives will be denied. If this was reversed to order deny,allow
, then the last thing evaluated would be the allow from all
directive, which would allow everybody, overriding the deny
statements.
Notice the third line, which has deny from 789.56.4.
— that is not a complete IP address. This will deny all IP addresses within that block (any that begin with 789.56.4
).
You can include as many IP addresses as you like, one on each line, with a deny from
directive.
Whitelisting by IP
The reverse of blacklisting is whitelisting — restricting everyone except those you specify.
As you may guess, the order
directive has to be reversed, so that that everyone is first denied
, but then certain addresses are allowed
.
order deny,allow
deny from all
allow from 111.22.3.4
allow from 789.56.4.
Domain names instead of IP addresses
You can also block or allow users based on a domain name. This can be help block people even as they move from IP address to IP address. However, this will not work against people who can control their reverse-DNS IP address mapping.
order allow,deny
deny from example.com
allow from all
This works for subdomains, as well — in the previous example, visitors from xyz.example.com
will also be blocked.
Block Users by Referrer
A referrer is the website that contains a link to your site. When someone follows a link to a page on your site, the site they came from is the referrer.
This doesn’t just work for clickable hyperlinks to your website, though. Pages anywhere on the internet can link directly to your images (“hotlinking”) — using your bandwidth, and possibly infringing on your copyright, without providing any benefit to you in terms of traffic. They can also hotlink to your CSS files, JS scripts, or other resources.
Most website owners are okay with this when happens just a little bit, but sometimes this sort of thing can turn into abuse.
Additionally, sometimes actual in-text clickable hyperlinks are problematic, such as when they come from hostile websites.
For any of these reasons, you might want to block requests that come from specific referrers.
To do this, you need the mod_rewrite
module enabled. This is enabled by default for most web hosts, but if it isn’t (or you aren’t sure) you can usually just ask your hosting company. (If they can’t or won’t enable it, you might want to think about a new host.)
The .htaccess
directives that accomplish referrer-based blocking rely on the mod_rewrite
engine.
The code to block by referrer looks like this:
RewriteEngine on
RewriteCond %{HTTP_REFERER} ^https://.*example.com [NC,OR]
RewriteCond %{HTTP_REFERER} ^https://.*anotherexample.com [NC,OR]
RewriteCond %{HTTP_REFERER} ^https://.*onemoreexample.com [NC]
RewriteRule .* - [F]
This is a little tricky, so lets walk through it.
The first line, RewriteEngine on
, alerts the parser that a series of directives related to rewrite is coming.
The next three lines each block one referring domain. The part you would need to change for your own use is the domain name (example
) and extension (.com
).
The backward-slash before the .com
is an escape character. The pattern matching used in the domain name is a regular expression, and the dot means something in RegEx, so it has to be “escaped” using the back-slash.
The NC
in the brackets specifies that the match should not be case sensitive. The OR
is a literal “or”, and means that there are other rules coming. (That is — if the URL is this one or this one or this one, follow this rewrite rule.)
The last line is the actual rewrite rule. The [F] means “Forbidden.” Any requests with a referrer matching the ones in the list will fail, and deliver a 403 Forbidden
error.
Blocking Bots and Web Scrapers
One of the more annoying aspects of managing a website is discovering that your bandwidth is being eaten up by non-human visitors — bots, crawlers, web scrapers. These are programs that are designed to pull information out of your site, usually for the purpose of republishing it as part of some low-grade SEO operation.
There, of course, legitimate bots — like those from major search engines. But the rest are like pests that just eat away at your resources and deliver no value to you whatsoever.
There are several hundred bots identified. You will never be able to block all of them, but you can keep the activity down to a dull roar by blocking as many as you can.
Here is a good security solution for WordPress websites.
Specifying a Default File for a Directory
When a request is made to a web server for a URL which does not specify a file name, the assumption built into most web servers is that the URL refers to a directory.
So, if you request https://example.com
, Apache (and most other web servers) is going look in the root directory for the domain (usually /Public_HTML
or something similar, but perhaps /example-com
) for the default file.
The default file, by default, is called index.html
. This goes way back to the beginning of the internet when a website was just a collection of documents, and the “home” page was usually an index of those documents.
But you might not want index.html
to be the default page. For example, you might need a different file type, like index.shtml
, index.xml
, or index.php
.
Or you might not think of your home page as an “index”, and want to call it something different, like home.html
or main.html
.
Setting the Default Directory Page
.htaccess
allows you to set the default page for a directory easily:
DirectoryIndex [filename here]
If you want your default to be home.html
it’s as easy as:
DirectoryIndex home.html
Setting Multiple Default Pages
You can also specify more than one DirectoryIndex
:
DirectoryIndex index.php index.shtml index.html
The way this works is that the web server looks for the first one first. If it can’t find that, it looks for the second one, and so on.
Why would you want to do this? Surely you know which file you want to use as your default page, right?
Remember that .htaccess
affects its own directory, and every subdirectory until it is overridden by a more local file. This means that an .htaccess
file in your root directory can provide instructions for many subdirectories, and each one might have its own default page name. Being able to place those rules in a single .htaccess
file in the root means that you don’t have to duplicate all the other directives in the file at every directory level.
URL Redirects and URL Rewriting
One of the most common uses of .htaccess
files is URL redirects.
URL redirects should be used when the URL for a document or resource has changed. This is especially helpful if you have reorganized your website or changed domain names.
301 vs. 302
From a browser standpoint, there are two types of redirects, 301 and 302. (These numbers refer to the error code generated by the web server.)
301 means “Permanently Moved,” while 302 means “Moved Temporarily.” In most cases, you want to use 301. This preserves any SEO equity the original URL had, passing it on to the new page. It also will cause most browsers to update their bookmarks. Most browsers will also cache the old-to-new mapping, so they will simply request the new URL when a link or user attempts to access the original. If the URL has changed permanently, these are all desirable results.
There’s very little reason to use 302 redirects, since there’s usually very little reason to temporarily change a URL. Changing a URL ever is undesirable, but is sometimes necessary. Changing it temporarily, with the plan to change it back later, is a bad idea and is almost always avoidable.
All the examples in this section will use the 301 redirect.
Redirect vs. Rewrite
There are two different ways to “change” a URL with .htaccess
directives — the Redirect
command and the mod_rewrite
engine.
The Redirect
command actually sends a redirect message to the browser, telling it what other URL to look for.
Typically, the mod_rewrite
tool “translates” one URL (the one provided in a request) into something that the file system or CMS will understand, and then handles the request as if the translated URL was the requested URL. When used this way, the web browser doesn’t notice that anything happened — it just receives the content it asked for.
The mod_rewrite
tool can also be used to produce 301 redirects that work the same way as the Redirect
command, but with more options for rules — mod_rewrite
can have complex pattern matching and rewriting instructions, which Redirect
cannot take advantage of.
Basic Page Redirect
To redirect one page to another URL, the code is:
Redirect 301 /relative-url.html https://example.com/full-url.html
This single-line command has four parts, each separated with a single space:
- The
Redirect
command - The type of redirect (
301 - Moved Permanently
) - The relative URL of the original page
- The full and complete URL of the new page
The relative URL is relative to the directory containing the .htaccess
file, which is usually the web root, or the root of the domain.
So if https://example.com/blog.php
had been moved to https://blog.example.com
, the code would be:
Redirect 301 /blog.php https://blog.example.com
Redirecting a large section
If you have moved your directory structure around, but kept your page names the same, you might want to redirect all requests for a certain directory to the new one.
Redirect 301 /old-directory https://example.com/new-directory
Redirecting an entire site
What if you entire site has moved to a new URL? Easy.
Redirect 301 / https://newurl.com
Redirecting www to non-www
Increasingly, websites are moving away from the www
subdomain. It’s never really been necessary, but it was a holdover from the days when you most people who operated a website were using a server to store lots of their own documents, and the www
or “world wide web” directory was used for content they wanted to share with others.
These days, some people use it, and some people don’t. Unfortunately, some users still automatically type www.
in front of every URL out of habit. If you’re not using www
, you want to make sure that these requests land in the right place.
To do this, you’ll need to use the mod_rewrite
module, which is probably already installed on your web host.
Options +FollowSymlinks RewriteEngine on RewriteCond %{http_host} ^www.example.com [NC] RewriteRule ^(.*)$ https://example.org/$1 [R=301,NC]
Be careful!
A lot of other .htaccess
and mod_rewrite
guides offer some variation of the following code to accomplish this:
Options +FollowSymlinks RewriteEngine on RewriteCond %{http_host} !^example.com [NC] RewriteRule ^(.*)$ https://example.org/$1 [R=301,NC]
Do you see the problem with that?
It redirects all subdomains to the primary domain. So not just www.example.com
, but also blog.example.com
and admin.example.com
and anything else. This is probably not the behavior you want.
Redirecting to www
But what if you are using the www
subdomain?
You should probably set up a redirect to make sure people get to where they’re trying to go. Especially now that fewer people are likely to automatically add that www
to the beginning of URLs.
You just reverse the above code.
RewriteEngine On RewriteCond %{http_host} ^example.com [NC RewriteRule ^(.*) https://example.com/$1 [R=301,NC]
Something you shouldn’t do
Several guides on .htaccess
redirects include instructions on how to make 404 errors redirect to the home page.
This is a good example of how just because you can do something, it doesn’t mean you should do something.
Redirecting 404 errors to the site’s homepage is a terrible idea. It confuses visitors, who can’t figure out why they are seeing the front page of a site instead of a proper 404 error page.
All websites should have a decent 404 page which clearly explains to the user that the content couldn’t be found and, ideally, offers some search features to help the user find what they were looking for.
Why use .htaccess
instead of other alternatives?
You can set up redirect in PHP files, or with any other type of server-side scripting. You can also set them up within your Content Management System (which is basically the same thing).
But using .htaccess
is usually the fastest type of redirect. With PHP-based redirects, or other server-side scripting languages, the entire request must be completed, and the script actually interpreted before a redirect message is sent to the browser. With .htaccess
redirects, the server responds directly to the request with the redirect message. This is much faster.
You should note, though — some content management systems actually manage redirects by updating the .htaccess
programatically. WordPress, for example, has redirect plugins that work this way. (And WP’s pretty URL system does this as well.) This gives you the performance of using .htaccess
directly, while also giving you the convenience of management from within your application.
Hiding Your .htaccess File
There is no reason that someone should be able to view your .htaccess
file from the web. It is never a needed document.
Moreover, there are some big reasons you should definitely not want people to see your .htaccess
file. The biggest issue is that if you are using an .htpasswd
file, its location is spelled out in the .htaccess
file. Knowing where to find it makes it easier to find.
Moreover, as a general rule, you don’t want to provide the public with details about your implementation. Rewrite rules, directory settings, security — all of the things that you use .htaccess
for — it is a good security practice to hide all of this behind-the-scenes at your web server. The more a hacker can learn about your system, the easier it is to compromise it.
It is very easy to hide your .htaccess
file from public view. Just add the following code:
<Files .htaccess>
order allow,deny
deny from all
</Files>
Enabling MIME types
MIME types are file types. They’re called MIME types because of their original association with email (MIME stands for “Multipurpose Internet Mail Extensions”). They aren’t just called “file types” because MIME implies a specific format for specifying the file type.
If you’ve ever authored an HTML document, you’ve like specified a MIME type, even if you didn’t know it:
<style type="text/css" src="/style.css" />
The type
attribute refers to a specific MIME type.
MIME types on your server
Sometimes you’ll find that your web server isn’t configured to deliver a particular type of file. It just doesn’t work — requests for the file simply fail.
In most cases, you can fix this problem by adding the MIME type to your .htaccess
file.
AddType text/richtext rtx
This directive has three parts, each separated by a space:
- The
AddType
comman - The MIME type
- The file extension
If you want to associate several different file extensions with the same MIME type, you can do that on a single line.
AddType image/jpeg jpeg jpg jpe JPG
Force Download by MIME Type
If you want all links to specific file types to launch as downloads, instead of being opened in the browser, you do that with the MIME type application/octet-stream
, like this:
AddType application/octet-stream pdf
Again, you can specify multiple file extensions with a single type:
AddType application/octet-stream pdf doc docx rtf
List of File Extensions and MIME Types
Here is a not-quite-complete list of file formats and associated MIME types.
If you are managing your own website, and you know what file types you publish resources in, then there is no need to paste this entire list into your .htaccess
file.
However, if you run a site that many other people are contributing and publishing content to, you may want to simply allow a large number of file types this way to make sure no one has a bad experience. This is especially the case if you run a site where people might be specifically sharing a lot of files, for example a file sharing site, a project management application (where many files will often be attached to project), or a web app that handles email.
AddType application/macbinhex-40 hqx
AddType application/netalive net
AddType application/netalivelink nel
AddType application/octet-stream bin exe
AddType application/oda oda
AddType application/pdf pdf
AddType application/postscript ai eps ps
AddType application/rtf rtf
AddType application/x-bcpio bcpio
AddType application/x-cpio cpio
AddType application/x-csh csh
AddType application/x-director dcr
AddType application/x-director dir
AddType application/x-director dxr
AddType application/x-dvi dvi
AddType application/x-gtar gtar
AddType application/x-hdf hdf
AddType application/x-httpd-cgi cgi
AddType application/x-latex latex
AddType application/x-mif mif
AddType application/x-netcdf nc cdf
AddType application/x-onlive sds
AddType application/x-sh sh
AddType application/x-shar shar
AddType application/x-sv4cpio sv4cpio
AddType application/x-sv4crc sv4crc
AddType application/x-tar tar
AddType application/x-tcl tcl
AddType application/x-tex tex
AddType application/x-texinfo texinfo texi
AddType application/x-troff t tr roff
AddType application/x-troff-man man
AddType application/x-troff-me me
AddType application/x-troff-ms ms
AddType application/x-ustar ustar
AddType application/x-wais-source src
AddType application/zip zip
AddType audio/basic au snd
AddType audio/x-aiff aif aiff aifc
AddType audio/x-midi mid
AddType audio/x-pn-realaudio ram
AddType audio/x-wav wav
AddType image/gif gif GIF
AddType image/ief ief
AddType image/jpeg jpeg jpg jpe JPG
AddType image/tiff tiff tif
AddType image/x-cmu-raster ras
AddType image/x-portable-anymap pnm
AddType image/x-portable-bitmap pbm
AddType image/x-portable-graymap pgm
AddType image/x-portable-pixmap ppm
AddType image/x-rgb rgb
AddType image/x-xbitmap xbm
AddType image/x-xpixmap xpm
AddType image/x-xwindowdump xwd
AddType text/html html htm
AddType text/plain txt
AddType text/richtext rtx
AddType text/tab-separated-values tsv
AddType text/x-server-parsed-html shtml sht
AddType text/x-setext etx
AddType video/mpeg mpeg mpg mpe
AddType video/quicktime qt mov
AddType video/x-msvideo avi
AddType video/x-sgi-movie movie
AddType x-world/x-vrml wrl
Block Hotlinking
Hotlinking is the practice of linking to resources from other domains instead of uploading the content to your own server and serving it yourself.
Say you find an image on a website that you really like, and you want to use it on your site. Ignoring copyright issues for the moment — you could download the image, upload it to your website, and embed it on your page like normal.
<img src="https://yourdomain.com/image.jpg">
But if you were lazy, or trying to save bandwidth, or didn’t know how to upload a file, you could just embed it directly form the original file.
<img src="https://originaldomain.com/image.jpg">
That’s hotlinking. It also happens with CSS and JS files, but images are the most common.
Some websites/hosts don’t mind at all if you do this — you can hotlink images from Wikipedia without anyone being upset. And some websites encourage it in one form or another. For example, JQuery provides their JS libraries via a CDN (Content Delivery Network), so you can hotlink directly to it without having to upload it and serve it from your own server.
But many web host consider hotlinking to be a form of bandwidth and resource stealing. To be sure, if you are running a relatively small site, you can’t afford to have thousands, or tens of thousands, of requests being made every day for resources that have nothing to do with actual visitors to your site.
If you are having a problem with hotlinking, you can disable it with some mod_rewrite
rules added to your .htaccess
file.
RewriteEngine on RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^https://(www.)?example.com/.*$ [NC] RewriteRule .(gif|jpg|jpeg|png|js|css)$ - [F]
Be sure to change example.com
in the third line to your actual domain name. This will catch any requests not coming from your domain, and then check if it matches one of the specified file extensions in the fourth line. If there is a match, the request fails.
If you want to add other file extensions, you can simply edit the last line.
Serving up Alternative Content
If you want to let the world know why their hotlinking has suddenly stopped working, you can replace hotlinked images with a special image with a message like, “We hate hotlinking!” or “Original Content Available at https://example.com”.
Instead of failing the request, you simply redirect it to the “special” image:
RewriteEngine on RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^https://(www.)?example.com/.*$ [NC] RewriteRule .(gif|jpg)$ https://www.example.com/no-hotlinking.jpg [R,L]
Disable or Enable Index
What happens if you have a directory full of documents or other resources, no index.html
file, and no default directory page specified in the .htaccess
file?
In many cases, the result will be a generic directory listing of all the files in the directory.
That’s right. If you have a folder in your hosting directory labeled /images
, and it has no index.html
page, when someone navigates to https://example.com/images
, they will be able to see a list of all the images on your site.
That’s the default behavior of most web servers, and it makes sense from the standpoint of the original conception of a website as simply a place to keep and share documents. But this is not the desired behavior for most sites.
Disabling Indexes
Many web hosting accounts will have disable this already as part of their global configuration. But not all do so.
If you need to disable automatically generated directory listings, doing so is easy:
Options -Indexes
Enabling Indexes
If your web server has disabled indexes as part of global configuration, but you do want them, you can enable them with the reverse of the above command.
Options +Indexes
Hiding some files from the Index
If you want to show directory listings, but you want to hide certain file types from the list, you can do that too.
IndexIgnore *.gif *.jpg
The *
is a wild-card character. The above directive will hide all files that have a .gif
or .jpg
extension. If you wanted to be more specific, you could:
IndexIgnore secret-image.jpg
Enabling CGI Everywhere
CGI, or Common Gateway Interface, is server-side method for including non-HTML scripts (like Perl or SSI) in web pages.
Typically, CGI scripts are stored in a folder labeled /cgi-bin
. The webserver is configured to treat any resource in that directory as a script, rather than a page.
The problem with that is two-fold: – URLs referencing CGI resources need to have /cgi-bin/
in them, which places implementation details into your URL — an anti-pattern to be avoided for a number of reasons. – a complex website may need a better organization structure than simply having a ton of scripts jammed into a single /cgi-bin
folder.
If you want your web server to parse CGI scripts no matter where they are found in your directory structure, just add the following to your .htaccess
file:
AddHandler cgi-script .cgi
Options +ExecCGI
If you have other file extensions you want processed as CGI scripts, you can add them in the first line.
Scripts as Source Code
Most of time, you put scripts in your web directory because, well, you want them to be run as scripts.
But sometimes that isn’t what you want. Sometimes you want to display the source code to public visitors, instead of running the script.
This might be the case if you run a file sharing service or a code repository site, and you want people to see the source code and be able to download it, but the scripts are actually part of your site’s functionality.
This can be done in your .htaccess
file by removing the script handler for certain file types and replacing it with a handler for text.
RemoveHandler cgi-script .pl .cgi .php .py
AddType text/plain .pl .cgi .php .py
Alternatively, as mention previously, you could force files with these extensions to be downloaded automatically, rather than displayed.
RemoveHandler cgi-script .pl .cgi .php .py
AddType application/octet-stream .pl .cgi .php .py
Be careful with either of these, though. If you only want some files to be displayed this way, but are still using these scripts for the rest of your website, your going to have a bad time if you put that directive into your web root’s .htaccess
file.
A better practice would be to place all such “display only” scripts into a single directory, and then place the directive into an .htaccess
file there in that folder.
Configuring PHP Settings
Sometimes you need to tweak PHP’s settings. The right way to do this is in a file called php.ini
.
Unfortunately, not all web hosting companies allow their customers to edit the php.ini
file. This is especially true of shared hosting providers, where a single installation of PHP may be running hundreds of web sites.
Fortunately, there’s a workaround — you can embed php.ini
rules into your .htaccess
file.
The syntax looks like:
php_value [setting name] [value]
So, for example, if you need to increase the max file upload size (a common issue), it is as easy as:
php_value upload_max_filesize 10M
Not all PHP settings can be specified in .htaccess
files. For example you can not disable_classes
this way.
For a complete list of all php.ini
settings, see the official php.ini directives guide.
When Not to Use .htaccess
Editing your .htaccess
file for the first time can give you sudden feeling of immense power over your web hosting environment. You suddenly feel like a sysadmin.
Unfortunately, this power can go to your head, and you may find yourself using the .htaccess
file in ways that aren’t really the best.
When you need to do something that seems like an .htaccess
sort of job, there’s basically two situations where you should put that directive somewhere else.
Further Upstream
Whenever possible, the types of directives you can place in an .htaccess
file are better off being place in the httpd.conf
file, which is a configuration settings file for the entire server.
Similarly, PHP settings more properly belong in the php.ini
file, and most other languages have similar configuration setting files.
Placing directives further upstream, in the httpd.conf
, php.ini
, or other language-specific configuration file allows those settings to be “baked-in” to the web server’s parsing engine. With .htaccess
, the directives have to be checked and interpreted with every single request.
If you have a low traffic site with only a handful of .htaccess
directives, this isn’t a big deal. But if you have a lot of traffic, and a lot of directives, the performance lag can really add up.
Unfortunately, many shared hosting providers do not allow customers to access the httpd.conf
or php.ini
files, forcing users to rely on the slower .htaccess
file. This provides a double-penalty when compared to custom VPS configurations because shared hosting is also generally low-powered. This is one of the reasons that a site with respectable traffic should probably be on a VPS plan instead of shared hosting plan.
Further Downstream
If you are using a good Content Management System (CMS) such as WordPress or Drupal, some of the things you might do in an .htaccess
file — such as redirect URLs or block IP addresses — can be done from inside the application.
Often, this works in conjunction with the .htaccess
file, with the application programmatically adding directives.
When this is available, it is usually best to accomplish these tasks from inside the application, rather than editing the .htaccess
file yourself. You are less likely to introduce bugs and incompatible directives if you use a well-tested, open source plugin, rather than editing it yourself.
Troubleshooting
Messing around with your .htaccess
file can be great — but it can also cause your server to seize up and start delivering 500 Internal Server Error
messages.
Here’s a few ideas to help you through that.
Do one thing at a time
This should go without saying, but — sadly — it’s a lesson many of us have to learn over and over again.
Do one thing. Then test it. Then do another thing. Test that.
If you do several things all at once, and then something fails, you won’t know which directive is causing the problem.
Backup your file before each thing
Along with doing only one thing at a time, you should save your file between each thing you are trying. Your saved archive needs to be restorable. This isn’t Microsoft Word where you can just Undo — you need a saved copy of your file.
You should always have the latest working version available in case you mess something up. Always, always, always have the ability to restore to a working version.
This is easiest if you some kind of source management system like Git. You can commit after each change, and roll back if you run into any problems.
Check the error logs
If you do run into a problem, and you’re having a hard time figuring out why, check your Apache error logs. These often provide valuable information about where to look.
Ask around
Developer forums and Q&A sites like StackOverflow are invaluable tools for even the most seasoned developers and sysadmins. And don’t forget Google. Often, the difference between a bad web master and great one isn’t knowing the answer, its knowing where to find the answer.
Common htaccess problems
Sometimes you made a typo. Sometimes you have an esoteric and confusing problem caused by a confluence of unpredictable factors.
Most problems, and the really frustrating ones, are the ones in the middle — the simple, everyday problems that are easy to fix if you just knew about them.
Here’s a few of those.
Bad Filename
There is only one way to spell .htaccess
— it has to begin with the dot, and it must be in all lowercase letters.
It seems dumb, but if your .htaccess
file isn’t doing what you expect, that should be the first thing you check.
.htaccess Disabled, or Partly Disabled
Some shared hosting providers disable .htaccess
altogether. Others allow it, but restrict certain directives from being used — they’re just ignored if included.
Similarly, even on VPS plans or your own dedicated servers, .htaccess
might be disabled.
If you have access to the httpd.conf
file, or other server settings, you can check this yourself. If you find the directive AllowOverride None
, you found the culprit. Replace it with AllowOverride All
.
If you don’t have access to your httpd.conf
file (because you’re on shared hosting, for example), you may need to contact your hosting company’s tech support and see if they can enable it for you, or offer you suggestions on ow to accomplish what you’re trying to do in a different way.
Conflicting or Overridden Directives
If you have multiple nested directories, it’s possible for each one to have its own .htaccess
file. Every .htaccess
file from the root, through each nested directory, applies — they are read in order, descending down the directory tree.
If you set something in your root directory, and then something in subdirectory overrides it, the directive in the .htaccess
file closest to the requested file will take precedence.
My .htaccess
configuration
Here’s my .htaccess
configuration:
AddDefaultCharset utf-8
DefaultLanguage en-US
# Add Proper MIME-Type for Favicon
AddType image/x-icon .ico
<IfModule mod_deflate.c>
# Compress HTML, CSS, JavaScript, text, XML and fonts
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-woff
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/woff
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE image/vnd.microsoft.icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
# Force compression for mangled `Accept-Encoding` request headers
# https://developer.yahoo.com/blogs/ydn/pushing-beyond-gzipping-25601.html
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)s*,?s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
</IfModule>
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 2 days"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/icon "access plus 1 month"
ExpiresByType image/vnd.microsoft.icon "access plus 1 month"
ExpiresByType application/x-icon "access plus 1 month"
ExpiresByType application/icon "access plus 1 month"
# Web fonts
# Embedded OpenType (EOT)
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType font/eot "access plus 1 month"
# OpenType
ExpiresByType font/opentype "access plus 1 month"
# TrueType
ExpiresByType application/x-font-ttf "access plus 1 month"
# Web Open Font Format (WOFF) 1.0
ExpiresByType application/font-woff "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType font/woff "access plus 1 month"
# Web Open Font Format (WOFF) 2.0
ExpiresByType application/font-woff2 "access plus 1 month"
# Other
ExpiresByType text/x-cross-domain-policy "access plus 1 week"
</IfModule>
## EXPIRES CACHING ##
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=16070400; includeSubDomains"
Header set X-Content-Type-Options "nosniff"
Header set X-XSS-Protection "1; mode=block"
<FilesMatch ".(appcache|atom|bbaw|bmp|crx|css|cur|eot|f4[abpv]|flv|geojson|gif|htc|ico|jpe?g|js|json(ld)?|m4[av]|manifest|map|mp4|oex|og[agv]|opus|otf|pdf|png|rdf|rss|safariextz|svgz?|swf|topojson|tt[cf]|txt|vcard|vcf|vtt|webapp|web[mp]|webmanifest|woff2?|xloc|xml|xpi)$">
Header unset X-XSS-Protection
</FilesMatch>
</IfModule>
ServerSignature Off
.htaccess
Protection For POST Abuse (WordPress)
A good strategy is to use .htaccess
to restrict POST
requests to commonly-abused URLs by referrer. Basically, if the referrer isn’t your own website, you just discard the request with an error.
Try this, in conjunction with hiding the login address:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login).php*
RewriteCond %{HTTP_REFERER} !.*example.com.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule (.*) http://%{REMOTE_ADDR}/$1 [R=301,L]
</IfModule>
Otherwise, the website (CMS) has to fire up to deal with the request, even if it’s a nonsense request. So it’s a redirect, back to the same page, to check for a real browser instead of a bot. It’s a redirect to their IP, which will almost certainly kick out an error message. You basically want to redirect the traffic anywhere but your server.
Related posts
In my previous article on logging PHP errors, How to Enable PHP Error Logging via htaccess, we observed three fundamental aspects of preventing, preserving, and protecting your site’s PHP errors.
Prevent public display of PHP errors via htaccess
# supress php errors
php_flag display_startup_errors off
php_flag display_errors off
php_flag html_errors off
php_value docref_root 0
php_value docref_ext 0
Preserve (log) your site’s PHP errors via htaccess
# enable PHP error logging
php_flag log_errors on
php_value error_log /home/path/public_html/domain/PHP_errors.log
Protect your site’s PHP error log via htaccess
# prevent access to PHP error log
<Files PHP_errors.log>
Order allow,deny
Deny from all
Satisfy All
</Files>
Now, in this article, we will explore these operations1 in greater depth, provide additional functionality, and examine various implications. First we will explore PHP error handling for production environments (i.e., for websites and applications that are online, active, and public), then we will consider error handling for development environments (i.e., for projects that are under development, testing, private, etc.).
Controlling the level of PHP error reporting
Using htaccess, it is possible to set the level of error reporting to suit your particular needs. The general format for controlling the level of PHP errors is as follows:
# general directive for setting php error level
php_value error_reporting integer
There are several common values used for “integer”, including:
- Complete error reporting — for complete PHP error logging, use an error-reporting integer value of “
8191
”, which will enable logging of everything except run-time notices2. - Zend error reporting — to record both fatal and non-fatal compile-time warnings generated by the Zend scripting engine, use an error-reporting integer value of “
128
”. - Basic error reporting — to record run-time notices, compile-time parse errors, as well as run-time errors and warnings, use “
8
” for the error-reporting integer value. - Minimal error reporting — to record only fatal run-time errors, use an error-reporting integer value of “
1
”, which will enable logging of unrecoverable errors.
Of course, there are many more error-reporting values available, depending on your particular error-logging goals. For more information on logging PHP errors, refer to the Error Handling and Logging Functions page at php.net.
Setting the maximum file size for your error strings
Using htaccess, you may specify a maximum size for your PHP errors. This controls the size of each logged error, not the overall file size. Here is the general syntax:
# general directive for setting max error size
log_errors_max_len integer
Here, “integer” represents the maximum size of each recorded error string as measured in bytes. The default value is “1024
” (i.e., 1 kilobyte). To unleash your logging powers to their fullest extent, you may use a zero value, “0
”, to indicate “no maximum” and thus remove all limits. Note that this value is also applied to displayed errors when they are enabled (e.g., during development).
Disable logging of repeated errors
If you remember the last time you examined a healthy (or sick, depending on your point of view) PHP error log, you may recall countless entries of nearly identical errors, where the only difference for each line is the timestamp of the event. If you would like to disable this redundancy, throw down the following code in the htaccess file of your project root:
# disable repeated error logging
php_flag ignore_repeated_errors on
php_flag ignore_repeated_source on
With these lines in place, repeated errors will not be logged, even if they are from different sources or locations. If you only want to disable repeat errors from the same source or file, simply comment out or delete the last line. Conversely, to ensure that your log file includes all repeat errors, change both of the on
values to off
.
Putting it all together — Production Environment
Having discussed a few of the useful ways to customize our PHP error-logging experience, let’s wrap it all up with a solid, htaccess-based error-handling strategy for generalized production environments. Here is the code for your target htaccess file:
# PHP error handling for production servers
php_flag display_startup_errors off
php_flag display_errors off
php_flag html_errors off
php_flag log_errors on
php_flag ignore_repeated_errors off
php_flag ignore_repeated_source off
php_flag report_memleaks on
php_flag track_errors on
php_value docref_root 0
php_value docref_ext 0
php_value error_log /home/path/public_html/domain/PHP_errors.log
# [see footnote 3] # php_value error_reporting 999999999
php_value error_reporting -1
php_value log_errors_max_len 0
<Files PHP_errors.log>
Order allow,deny
Deny from all
Satisfy All
</Files>
Or, if you prefer, an explanatory version of the same code, using comments to explain each line:
# PHP error handling for production servers
# disable display of startup errors
php_flag display_startup_errors off
# disable display of all other errors
php_flag display_errors off
# disable html markup of errors
php_flag html_errors off
# enable logging of errors
php_flag log_errors on
# disable ignoring of repeat errors
php_flag ignore_repeated_errors off
# disable ignoring of unique source errors
php_flag ignore_repeated_source off
# enable logging of php memory leaks
php_flag report_memleaks on
# preserve most recent error via php_errormsg
php_flag track_errors on
# disable formatting of error reference links
php_value docref_root 0
# disable formatting of error reference links
php_value docref_ext 0
# specify path to php error log
php_value error_log /home/path/public_html/domain/PHP_errors.log
# specify recording of all php errors
# [see footnote 3] # php_value error_reporting 999999999
php_value error_reporting -1
# disable max error string length
php_value log_errors_max_len 0
# protect error log by preventing public access
<Files PHP_errors.log>
Order allow,deny
Deny from all
Satisfy All
</Files>
This PHP error-handling strategy is ideal for a generalized production environment. In a nutshell, this code secures your server by disabling public display of error messages, yet also enables complete error transparency for the administrator via private error log. Of course, you may wish to customize this code to suit your specific needs. As always, please share your thoughts, ideas, tips and tricks with our fellow readers. Now, let’s take a look at a generalized error-handling strategy for development environments..
Putting it all together — Development Environment
During project development, when public access to your project is unavailable, you may find it beneficial to catch PHP errors in real time, where moment-by-moment circumstances continue to evolve. Here is a generalized, htaccess-based PHP error-handling strategy for development environments. Place this code in your target htaccess file:
# PHP error handling for development servers
php_flag display_startup_errors on
php_flag display_errors on
php_flag html_errors on
php_flag log_errors on
php_flag ignore_repeated_errors off
php_flag ignore_repeated_source off
php_flag report_memleaks on
php_flag track_errors on
php_value docref_root 0
php_value docref_ext 0
php_value error_log /home/path/public_html/domain/PHP_errors.log
# [see footnote 3] # php_value error_reporting 999999999
php_value error_reporting -1
php_value log_errors_max_len 0
<Files PHP_errors.log>
Order allow,deny
Deny from all
Satisfy All
</Files>
For this code, we will forego the line-by-line explanations, as they may be extrapolated from the previous section. This PHP error-handling strategy is ideal for a generalized development environment. In a nutshell, this code enables real-time error-handling via public display of error messages, while also enabling complete error transparency for the administrator via private error log. Of course, you may wish to customize this code to suit your specific needs. As always, please share your thoughts, ideas, tips and tricks with our fellow readers. That’s all for this article — see you next time!
Useful Links
- https://www.php.net/manual/en/errorfunc.configuration.php
- https://httpd.apache.org/docs/current/mod/core.html#files
Footnotes
- 1 For more information, check out the manual on Error Handling and Logging Functions at php.net
- 2 Due to the bitwise nature of the various error-reporting values, the value for logging all errors continues to increase. For example, in PHP 5.2.x, its value is
6143
, and before that, its value was2047
. Thus, to ensure comprehensive error logging well into the future, it is advisable to set a very large value forerror_reporting
, such as2147483647
. - 3 According to the PHP Manual on error_reporting, “Passing in the value
-1
will show every possible error, even when new levels and constants are added in future PHP versions. TheE_ALL
constant also behaves this way as of PHP 6.” – Thus, the code in this article has been updated accordingly. Simply delete the commented-out line in the code and you’re good to go.
About the Author
Jeff Starr = Web Developer. Security Specialist. WordPress Buff.
.htaccess (с точкой в начале имени) — это файл-конфигуратор Apache-серверов, который дает возможность конфигурировать работу сервера в отдельных директориях (папках), не предоставляя доступа к главному конфигурационному файлу. Например, устанавливать права доступа к файлам в директории, менять названия индексных файлов, самостоятельно обрабатывать ошибки Apache, перенаправляя посетителей на специальные страницы ошибок. .htaccess представляет собой обычный текстовый документ, расширение которого htaccess. Данный файл обычно находится в корне сайта, однако Вы можете создавать и дополнительные .htaccess-файлы для различных директорий Вашего сайта.
Mod_rewrite — модуль, используемый веб-серверами для преобразования URL.
Директивы модуля Mod_rewrite
- RewriteBase
- RewriteCond
- RewriteEngine
- RewriteLock
- RewriteLog
- RewriteLogLevel
- RewriteMap
- RewriteOptions
- RewriteRule
Варианты реализации Редиректа с помощью файла .htaccess
- Простой редирект:
Redirect 301 / http://www.domain.ru/
или
redirect /secret http://www.site.ru/nosecret
Ставится в файле .htaccess или httpd.conf для Apache. Первый «/» означает, что всё с верхнего уровня сайта, включая все подкаталоги, будет переадресовано (не забывайте поставить последний «/»). Если Вы хотите переадресовать только страницу, сохранив PR старой страницы, можно сделать так:
Redirect 301 /old/old.htm http://www.domain.ru/new.htm где:
/old/old.htm — путь и имя старой страницы
http://www.domain.com/new.htm — новый путь и новое имя перемещенной страницы - Редирект на любую страницу по ip пользователя или при запросе конкретной страницы (а также по маске имени).
Если у пользователя ip 192.152.37.125, то он будет перенаправлен на страницу user.php:SetEnvIf REMOTE_ADDR 192.152.37.125 REDIR="redir" RewriteCond %{REDIR} redir RewriteRule ^/$ /user.php
- Редирект при запросе определённых файлов. Если запрашиваются файлы, расширение которых не указано в файле .htaccess (gif и jpg), то следует перенаправление:
RewriteEngine On RewriteRule !.(gif|jpg)$ index.php
- Использование mod_rewrite:
Options +FollowSymLinks RewriteEngine on RewriteCond %{HTTP_HOST} ^domain.ru RewriteRule ^(.*)$ http://www.domain.ru/$1 [R=permanent,L]
- Редирект с регулярным выражением:
RedirectMatch 301 (.*) http://www.domain.ru$1 Прописывается в файле .htaccess.
(.*) RedirectMatch фактически соответствует регулярным образцам выражения после доменного имени. Таким образом, нельзя выполнить соответствие образца на ^/domain.ru. Однако, можно преобразовать страницы с использованием .html расширения к файлам того же самого названия, но с .php расширением:
RedirectMatch 301 (.*).html$ http://www.domain.ru$1.php
Если необходимо сделать различное перенаправление для отдельных страниц, можно использовать следующее:
RedirectMatch Permanent ^/html/resources.html$ http://www.domain.com/resources.php RedirectMatch Permanent ^/html/other_page.html$ http://www.domain.com/other_page.php RedirectMatch Permanent ^/(.*)$ http://www.domain.com/
«RedirectMatch Permanent» — это эквивалент «RedirectMatch 301», строка с «*(Wildcard)» должна быть последней в этом списке.
- Создание удобо читаемых URL
Чтобы преобразовать, например, www.domain.ru/product.php?id=123 в www.domain.ru/product/123 следующим образом:RewriteEngine on RewriteRule ^product/([^/.]+)/?$ product.php?id=$1 [L]
В следующем примере преобразуем www.domain.ru/script.php?product=123 в www.domain.ru/cat/product/123/:
RewriteRule cat/(.*)/(.*)/$ /script.php?$1=$2
- Редирект на PHP:
header("HTTP/1.1 301 Moved Permanently"); header("Location: http://www.domain.ru/newdir/newpage.htm"); exit();
Естественно, надо создать страницу, при обращении к которой и будет происходить Редирект, и разместить её на сервере. И лучше укажите HTTP/1.1 (а не HTTP/1.0 или HTTP/0.9, которые не поддерживают виртуальный хостинг)
- Редирект всех файлов в папке на один файл.
Например вы больше не нуждаетесь в разделе сайта Files и хотите перенаправить все запросы к папке /files на один файл /page.php. Для этого добавляем в .htaccess следующий код.RewriteRule ^files(.*)$ /page.php [L,R=301]
- Редирект всей папки кроме одного файла
В следующем примере все файлы из папки /files будут редиректится на на файл /page.php, кроме файла /files/test.html котоый должен редиректится на /test-1.htmlRewriteRule ^files/test.html /test-1.html [L,R=301] RewriteRule ^files(.*)$ /page.php [L,R=301]
- Редирект динамического URL на новый файл.
Данный вариант пригодится если вы хотите редиректить динамический URL с параметрами на новый статический файл.RewriteRule ^article.jsp?id=(.*)$ /test.htm [L,R=301]
То есть теперь, запрос к файлу вида http://www.domain.ru/article.jsp?id=8547 и/или http://www.domain.ru/article.jsp?id=1234 будет отправлен на файл http://www.domain.ru/test.htm.
- Массовый редирект новых файлов.
Тепепь перейдем к самому сложному моменту, когда вам надо редиректить массу URL-ов, например после смены вашей CMS. Тут сразу возникает ряд проблем. Во-первых, внесение всех изменившихся адресов в .htaccess файл займет очень много времени, да и само по себе занятие малоприятное. Во-вторых, слишком много записей в .htaccess файле будут тормозить Apache сервера. И в третьих, при внесении такого количества информации высока вероятность, что вы где то ошибетесь. По этому, самый лучший выход, это нанять програмиста который вам напишет динамический редирект.
Нижеприведенный пример написан на PHP, но так же может быть выполнен на любом языке. Предположим вы перешли на новую систему ссылок на вашем сайте и все файлы оканчивающиеся на старый id должны быть средирекчены. Сначала создаем в базе таблицу, которая содержит старый id и новый URL для редиректа. old_id INT new_url VARCHAR (255) Далее пишем код который свяжет ваши старые id с новыми URL-ами
После этого, добавляем следующую строчку в .htaccess:RewriteRule ^/product-(.*)_([0-9]+).php /redirectold.php?productid=$2
затем создаем PHP файл redirectold.php, который будет поддерживать 301 редирект:
Теперь все запросы к вашим старым URL-ам будут вызывать redirectold.php, который найдет новый URL и вернет 301 ответ с вашей новой ссылкой.
Редиректы в зависимости от времени
Когда нужно применять уловки типа содержания зависящего от времени масса вебмастеров все ещё используют CGI скрипты которые производят редиректы на специальные страницы. Как это может быть сделано через mod_rewrite?
Есть много переменных названных TIME_xxx для условий редиректа. В связке со специальными лексикографическими образцами для сравнения STRING и =STRING мы можем производить редиректы зависящие от времени:
RewriteEngine on RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700 RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 RewriteRule ^foo.html$ foo.day.html RewriteRule ^foo.html$ foo.night.html
Это выдает содержимое foo.day.html при запросе URL foo.html с 07:00 до 19:00 а в оставшееся время содержимое foo.night.html.
- Убираем у всех запросов вначале «WWW.»
RewriteEngine on # оглашаем, что хотим использовать mod_rewrite RewriteCond %{HTTP_HOST} ^www.(.*) [NC] RewriteRule ^/?(.*) http://%1/$1 [L,R=permanent]
- Меняем расширение .html на .php
Иногда бывает так, что у Вас статичный веб-сайт, а Вам необходимо, чтобы на нем срабатывал какой-нибудь php-скрипт. Для этого Вам необходимо сказать серверу, чтобы он обрабатывал эту страницу как php-файл.AddHandler application/x-httpd-php .html
Этот прием можно использовать и для других расширений файлов:
AddHandler application/x-httpd-php .xml AddHandler application/x-httpd-php .asp
Запрещение доступа в конкретную директорию
- для всех ко всем файлам в директории:
deny from all
- к конкретному файлу:
deny from all
- по ip пользователя:
order deny,allow deny from all allow from 192.152.37.125
Доступ в данную директорию будет разрешён только пользователю с ip 192.152.37.125.
- Директива Options -Indexes — запрет на отображение содержимого каталога при отсутствии индексного файла Иногда нужно сделать так, чтобы в случае отсутствия в каталоге файла, который показывается по умолчанию, не выдавался список файлов в каталоге. Тогда можно добавить в .htaccess такую строчку :
Options -Indexes
В этом случае вместо списка файлов в каталоге посетитель получит HTTP ошибку 403 — access forbidden.
- Запретить доступа к файлам с несколькими типа расширений deny from all Запрещен доступ к файлам с расширением *.inc, *.conf и *.cfg. Хотя директива, по умолчанию, не работает с регулярными выражениями, но их можно включить поставив символ тильды(~) в опциях директивы. Синтаксис следующий: [тильда] [пробел] [далее_все_без_пробелов] Чтобы блокировать этот доступ, запишем следующее:
RewriteRule ^.htaccess$ - [F]
Это правило переводится так:
Если кто-то пробует обращаться к файлу .htaccess, система должна произвести код ошибки ‘HTTP response of 403’ или ‘403 Forbidden — You don’t have permission to access /.htaccess on this server’.Конструкция ^.htaccess$ в этом регулярном выражении означает:
^ — якорь начала строки
$ — якорь конца строки
. — в регулярных выражениях точка ‘.’ обозначает мета-символ и должна быть защищена обратным слэшем (backslash), если Вы все-таки хотите использовать именно фактическую точку.Имя файла должно быть расположено точно между начальным и конечным якорем. Это будет гарантировать то, что только это определенное имя файла и никакое другое, сгенерирует код ошибки.
[F] — специальный ‘запрещающий’ флажок (forbidden).
[NC] — не учитывать регистр букв.
[OR] — означает ‘или следующее условие’.
Определение кодировки
Определение кодировки, в которой сервер «отдает» файлы
AddDefaultCharset windows-1251
варианты: KOI8-R, UTF-8, Windows-1251
Определение кодировки на загружаемые файлы
CharsetSourceEnc windows-1251
Установка пароля на директорию с помощью .htaccess
Для установки пароля на директорию можно воспользоваться системой базовой авторизации, предусмотренной в веб-сервере Apache. Создаем в каталоге, к которому хотим ограничить доступ по паролю, файл .htaccess с такими директивами:
AuthType Basic AuthName "Some Name" AuthUserFile /www/some_login/www/htdocs/some_dir/.htpasswd require valid-user
Путь /www/some_login/www/htdocs/some_dir/.htpasswd обозначает полный путь к файлу паролей на диске нашего сервера. Если, например, вы поместите файл .htpasswd (в нем будут пароли) в домашний каталог, куда вы попадаете, зайдя на сервер по FTP, то путь к этому файлу будет иметь вид /www/some_login/www/htdocs/some_dir/.htpasswd, где some_login — Ваш логин. В директиве AuthUserFile указываем абсолютный путь к файлу с логинами/паролями, который мы создадим чуть позже. Если вы создаете файл .htaccess на своем компьютере, а не сразу на сервере используя текстовый редактор, обратите особое внимание на то, что .htaccess должен передаваться по FTP строго в текстовом (ASCII) режиме.
Создаем файл паролей. Файл с паролями должен содержать строки вида login:password. Пароль должен быть зашифрован с использованием алгоритма MD5. Один из способов создать такой файл — воспользоваться программой, входящей в поставку Apache — htpasswd (на нашем сервере она находится в каталоге /usr/local/apache/bin, полный путь — /usr/local/apache/bin/htpasswd).
Рассмотрим, как создать файл паролей в unix shell прямо на сервере. Зайдем в shell и будем выполнять следующие команды:
htpasswd -mbc .htpasswd user1 7B1safkir
— создаем новый файл .htpasswd, в который добавляем запись для пользователя user1 с паролем, указанным в командной строке.
htpasswd .htpasswd user2
— добавляем в уже существующий файл .htpasswd пользователя user2, а пароль вводим вручную в ответ на соответствующий запрос программы.
После окончания заведения всех логинов файл нужно загрузить на сервер.
Задаем собственные страницы ошибок
Задать собственную страницу ошибок можно следующим образом:
ErrorDocument 404 http://www.domain.ru/404.php
IE игнорирует страницы размером меньше 512 байт.
Индексация директорий и поддиректорий
Чтобы избежать индексации поисковыми системами директорий и поддиректорий, необходимо прописать такую строку, к примеру:
DirectoryIndex index.php
Эта директива задает файл, который будет вызван при обращении к директории без указания имени файла.
Можно указать несколько индексных страниц. При запросе каталога они будут искаться в том порядке, в котором перечислены в директиве DirectoryIndex. Если не будет найден файл index.html, то будет произведен поиск файла index.php и т.д.
DirectoryIndex index.html index.php index.shtml
Лично я предпочитаю переадресовывать с пустых директорий либо на главную страницу сайта, либо на какую-либо другую подходящую страницу. Например, директорию www.domain.ru/pic/ можно переадресовать на www.domain.ru.
Защита изображений от скачивания
Очень часто бывает, что веб-мастера нагло копируют контент с Вашего сайта вместе с рисунками, причем рисунки подгружаются с Вашего же сервера. Это создает лишний трафик, что, зачастую, приводит к ряду проблем. Как же защититься от таких веб-мастеров и не помешать поисковым роботам индексировать изображения? Все просто:
RewriteEngine on RewriteCond %{HTTP_REFERER} . RewriteCond %{HTTP_REFERER} !^http://([^.]+.)?site. [NC] RewriteCond %{HTTP_REFERER} !google. [NC] RewriteCond %{HTTP_REFERER} !search?q=cache [NC] RewriteCond %{HTTP_REFERER} !msn. [NC] RewriteCond %{HTTP_REFERER} !yahoo. [NC] RewriteCond %{REQUEST_URI} !^/image.gif$ RewriteRule .(gif|jpg|png)$ /image.gif [NC,L]
image.gif — изображение, которое будет отображаться, вместо истинных изображений. Рекомендую в этом изображении отобразить Ваш логотип и ссылку на Ваш сайт.
Еще один варинат запрета доступа к картинкам с неразрешенных сайтов:
SetEnvIfNoCase Referer "^$" local_ref=1 SetEnvIfNoCase Referer "^http://(www.)?htmlweb.ru" local_ref=1 SetEnvIfNoCase Referer "^http://(www.)?images.yandex.ru" local_ref=1 SetEnvIfNoCase Referer "^http://(www.)?hghltd.yandex.com" local_ref=1 Order Allow,Deny Allow from env=local_ref
Поисковые машини и разного рода сканеры создают коллосальный трафик на вашем сайте. Нижеприведенный блок кода позволит запретить доступ ботам на сайт.
RewriteCond %{HTTP_USER_AGENT} (Googlebot|Slurp|spider|Twiceler|heritrix| Combine|appie|boitho|e-SocietyRobot|Exabot|Nutch|OmniExplorer| MJ12bot|ZyBorg/1|Ask Jeeves|AskJeeves|ActiveTouristBot| JemmaTheTourist| agadine3|BecomeBot|Clustered-Search-Bot| MSIECrawler|freefind|galaxy|genieknows|INGRID|grub-client| MojeekBot|NaverBot|NetNose-Crawler|OnetSzukaj|PrassoSunner| Asterias Crawler|T-H-U-N-D-E-R-S-T-O-N-E|GeorgeTheTouristBot| VoilaBot|Vagabondo|fantomBro wser|stealthBrowser|cloakBrowser| fantomCrew Browser|Girafabot|Indy Library|Intelliseek|Zealbot| Windows 95|^Mozilla/4.05 [en]$|^Mozilla/4.0$) [NC] RewriteRule ^(.*)$ - [F] # RewriteCond %{HTTP_USER_AGENT} ^Mozilla.* [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^Opera.* [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^Firefox.* [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^Netscape.* [NC] RewriteRule ^(.*)$ - [L] RewriteRule ^(.*)$ - [F]
Отслеживание обращений к файлу robots.txt
Чтобы иметь больше информации о посещении поисковиков, полезно иметь подробную информацио об обращении к файлу robots.txt Для того, чтобы оганизовать это, в ‘.htaccess’ должны быть следующие записи:
RewriteEngine on Options +FollowSymlinks RewriteBase / RewriteRule ^robots.txt$ /robot.php?%{REQUEST_URI}
Теперь при запросе файла ‘robots.txt’ наш RewriteRule переадресует посетителя (робота) к обрабатывающему запросы скрипту robot.php. Кроме того, переменная передается скрипту, которая будет обработана в соответствии с вашими нуждами. ‘REQUEST_URI’ определяет имя запрашиваемого файла. В данном примере это — ‘robots.txt’. Скрипт прочтет содержание ‘robots.txt’ и отправит его web-браузеру или роботу поискового сервера. Таким образом, мы можем считать хиты посетителей и вести лог-файлы.
PHPSESSID
Для отключения добавления PHPSESSID к URL вставьте в начало index.php:
ini_set("session.use_trans_sid", 0);
Либо в .htaccess пропишите:
php_flag session.use_trans_sid Off
Директивы кеширования
Кэширование для всех типов файлов по времени доступа
ExpiresActive on ExpiresDefault "access plus 600 seconds"
Кэширование для всех типов файлов по времени изменения
ExpiresActive on ExpiresDefault "modification plus 600 seconds"
Кэширование для определённых типов файлов
ExpiresByType text/css "modification plus 600 seconds" ExpiresByType image/jpeg "modification plus 600 seconds" ExpiresByType image/gif "modification plus 600 seconds" ExpiresByType image/x-ico "modification plus 600 seconds" ExpiresByType image/png "modification plus 600 seconds"
Запрет кеширования с помощью сервера Apache
Откройте файл конфигурации сервера Apache httpd.conf и раскомментируйте следующие строчки:
LoadModule expires_module modules/mod_expires.so LoadModule headers_module modules/mod_headers.so ... AddModule mod_expires.c AddModule mod_headers.c
Впишите в .htaccess следующее:
# Запрещение кеширования в этой папке # Необходимо включение модулей # mod_headers.c и mod_expires.c # # Заголовок Cache-Control
Header append Cache-Control «no-store, no-cache, must-revalidate»
# Заголовок Expires
ExpiresActive On ExpiresDefault «now»
Необходимые заголовки будут передаваться автоматически, и специально их писать в PHP уже не нужно — кэш уже выключен!
Кеширование с помощью файла .htaccess
# Разрешение кеширования в этой папке # Необходимо включение модулей # mod_headers.c и mod_expires.c # # Заголовок Cache-Control
Header append Cache-Control «public»
# Заголовок Expires
ExpiresActive On ExpiresDefault «access plus 1 hours» #ExpiresDefault «access plus 10 years»
Кеширование javascript файлов с помощью файла .htaccess
ExpiresDefault «access plus 3 days»
Будьте осторожны при кешировании, т.к. при изменении файла, пользователь может получить новый вариант только через 3 дня!
Как заставить html-страницы обрабатывать php-код?
Пропишите в своем файле .htaccess следующие строки:
RemoveHandler .php .htm .html AddHandler application/x-httpd-php .php .htm .html
Как разместить несколько сайтов на одном виртуальном хостинге?
Чтобы разместить два или более сайтов на одном виртуальном хостинге, вопреки отведенному вам тарифным планом количеству доменов необходимо в файле «.htaccess» прописать следующие строки:
RewriteEngine On RewriteRule ^newdirectory/ - [L] RewriteCond %{HTTP_HOST} (www.)?newdomain.ru [NC] RewriteRule (.*) newdirectory/$1 [L]
Где:
newdirectory/ — папка, в которой будет лежать второй сайт
newdomain.ru — домен, для которого мы делаем перенаправление
Обратите внимание, что при этом у Вас будет единый почтовый аккаунт. Т.е. если, у Вас существует ящик admin@domain.ru, то после подключения домена newdomain.ru у ящика admin@domain.ru появляется второе имя — admin@newdomain.ru. А при создании любого нового ящика (например info), ему автоматически присваиваются два имени — info@domain.ru и info@newdomain.ru.
Поиск страниц больше чем в одном каталоге
Иногда необходимо позволить веб-серверу искать страницы больше чем в одном каталоге.
RewriteEngine on # во-первых попытаемся найти это в указанном месте/... # ...и если нашли то заканчиваем поиск: RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f RewriteRule ^(.+) /your/docroot/dir1/$1 [L] # во-вторых - попытаемся найти это в pub/... # ...и если нашли то заканчиваем поиск: RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f RewriteRule ^(.+) /your/docroot/dir2/$1 [L] # иначе продолжаем для других директив RewriteRule ^(.+) - [PT]
Виртуальные хосты пользователей
Если Вы хотите предоставлять адреса www.subdomain.domain.ru для страниц пользователей, Вы можете использовать следующий набор правил для преобразования http://www.subdomain.domain.ru/path во внутренний путь /home/subdomain/path:
RewriteEngine on RewriteCond %{HTTP_HOST} ^www.[^.]+.ru$ RewriteRule ^(.+) %{HTTP_HOST}$1 [C] RewriteRule ^www.([^.]+).ru(.*) /home/$1$2
Повреждаются файлы при загрузке на сервер
Если при передаче файлов через формы (при указанном enctype=»multipart/form-data») бинарные данные повреждаются, пропишите в /cgi-bin/.htaccess директиву:
CharsetRecodeMultipartForms Off.
Ошибка загрузки SWF файлов.
Ошибки при обращении к страницам, содержащим ключевые слова,
типа $_REQUEST
Такое может происходить из-за установленного модуля в Apache. По умолчанию он блокирует в запросах строки с SQL аргументами и другими потенциально опасными командами.
Возможные сообщения об ошибке:
Forbidden
You don’t have permission to access /adm/index.php on this server. Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
или
Запрос небезопасен и был отвергнут.
Добавьте в .htaccess
SecFilterEngine Off SecFilterScanPOST Off
Для сообщения:
«POST /wp-admin/async-upload.php HTTP/1.1» 406 354 «-» «Shockwave Flash»
можно снять защиту только на загрузку файлов на сервер:
SecFilterEngine Off SecFilterScanPOST Off
Оптимально снимать защиту только с той папки, в которой это необходимо, не убирая защиту со всего сайта.
Переменные сервера
Это переменные вида %{NAME_OF_VARIABLE}
где NAME_OF_VARIABLE может быть строкой взятой из следующего списка:
HTTP заголовки: | соединение & запрос: | |
---|---|---|
HTTP_USER_AGENT HTTP_REFERER HTTP_COOKIE HTTP_FORWARDED HTTP_HOST HTTP_PROXY_CONNECTION HTTP_ACCEPT |
REMOTE_ADDR REMOTE_HOST REMOTE_USER REMOTE_IDENT REQUEST_METHOD SCRIPT_FILENAME PATH_INFO QUERY_STRING AUTH_TYPE |
|
внутренние сервера: | системные: | специальные: |
DOCUMENT_ROOT SERVER_ADMIN SERVER_NAME SERVER_ADDR SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE |
TIME_YEAR TIME_MON TIME_DAY TIME_HOUR TIME_MIN TIME_SEC TIME_WDAY TIME |
API_VERSION THE_REQUEST REQUEST_URI REQUEST_FILENAME IS_SUBREQ |
Эти переменные полностью соответствуют названным похожим образом MIME-заголовкам HTTP, и переменным сервера Apache или полям struct tm
систем Unix. Те, что являются для mod_rewrite специальными включают:
IS_SUBREQ — Будет содержать текст «true» если запрос выполняется в текущий момент как подзапрос, «false» в другом случае. Подзапросы могут быть сгенерированны модулями которым нужно иметь дело с дополнительными файлами или URI для того чтобы выполнить собственные задачи.
API_VERSION — Это версия API модуля Apache (внутренний интерфейс между сервером и модулем) в текущей сборке сервера, что определено в include/ap_mmn.h. API версия модуля соответствует используемой версии Apache (для версии Apache 1.3.14, к примеру это 19990320:10), однако это в основном интересно авторам модулей.
THE_REQUEST — Полная строка HTTP запроса отправленная браузером серверу (т.е., «GET /index.html HTTP/1.1
»). Она не включает какие-либо дополнительные заголовки отправляемые браузером.
REQUEST_URI — Ресурс, запрошенный в строке HTTP запроса.
REQUEST_FILENAME — Полный путь в файловой системе сервера к файлу или скрипту соответствующим этому запросу.
Примечания:
- Переменные SCRIPT_FILENAME и REQUEST_FILENAME содержат одинаковые значения, т.е., значение поля
filename
внутренней структурыrequest_rec
сервера Apache. Первое имя это просто широко известное имя переменной CGI в то время как второе это постоянная копия REQUEST_URI (содержащая значение поляuri
структурыrequest_rec
). - Есть специальный формат:
%{ENV:переменная}
где переменная может быть любой переменной окружения. Это ищется во внутренних структурах Apache и (если там нет) с помощью вызоваgetenv()
из процесса Apache сервера. - Есть специальный формат:
%{HTTP:заголовок}
где заголовок может быть любым именем HTTP MIME-заголовка. Это ищется в HTTP запросе. Пример:%{HTTP:Proxy-Connection}
значение HTTP заголовка «Proxy-Connection:
». - Есть специальный формат
%{LA-U:переменная}
опережающих запросов которые производятся внутренним (основанном на URL) подзапросом для определения конечного значения переменной. Используйте это когда вы хотите использовать переменную для преобразований, которая реально определяется позднее, в какой-либо фазе API, и таким образом недоступна на данном этапе. Для примера когда вы хотите преобразовать соответственно переменнойREMOTE_USER
из контекста сервера (файлhttpd.conf
) вы должны использовать%{LA-U:REMOTE_USER}
потому что эта переменная устанавливается в фазах авторизации которые идут после фазы трансляции URL в которой и работает mod_rewrite. С другой стороны, по причине реализации работы mod_rewrite в контексте каталога (файл .htaccess) через Fixup фазу API и из-за того, фазы авторизации идут до этой фазы, вы просто можете там использовать%{REMOTE_USER}
. - Есть специальный формат:
%{LA-F:переменная}
который создает внутренний (основанный на имени файла) подзапрос для определения конечного значения переменной. В основном это то же самое что и формат LA-U приведенный выше.
PHP предлагает гибкие настройки вывода ошибок, среди которых функия error_reporting($level)
– задает, какие ошибки PHP попадут в отчет, могут быть значения:
E_ALL
– все ошибки,E_ERROR
– критические ошибки,E_WARNING
– предупреждения,E_PARSE
– ошибки синтаксиса,E_NOTICE
– замечания,E_CORE_ERROR
– ошибки обработчика,E_CORE_WARNING
– предупреждения обработчика,E_COMPILE_ERROR
– ошибки компилятора,E_COMPILE_WARNING
– предупреждения компилятора,E_USER_ERROR
– ошибки пользователей,E_USER_WARNING
– предупреждения пользователей,E_USER_NOTICE
– уведомления пользователей.
1
Вывод ошибок в браузере
error_reporting(E_ALL);
ini_set('display_errors', 'On');
PHP
В htaccess
php_value error_reporting "E_ALL"
php_flag display_errors On
htaccess
На рабочем проекте вывод ошибок лучше сделать только у авторизированного пользователя или в крайнем случаи по IP.
2
Запись ошибок в лог файл
error_reporting(E_ALL);
ini_set('display_errors', 'Off');
ini_set('log_errors', 'On');
ini_set('error_log', $_SERVER['DOCUMENT_ROOT'] . '/logs/php-errors.log');
PHP
Файлы логов также не должны быть доступны из браузера, храните их в закрытой директории с файлом .htaccess:
Order Allow,Deny
Deny from all
htaccess
Или запретить доступ к файлам по расширению .log (заодно и другие системные файлы и исходники):
<FilesMatch ".(htaccess|htpasswd|bak|ini|log|sh|inc|config|psd|fla|ai)$">
Order Allow,Deny
Deny from all
</FilesMatch>
htaccess
3
Отправка ошибок на e-mail
Ошибки можно отправлять на е-mail разработчика, но приведенные методы не работает при критических ошибках.
Первый – register_shutdown_function()
регистрирует функцию, которая выполнится при завершении работы скрипта, error_get_last()
получает последнюю ошибку.
register_shutdown_function('error_alert');
function error_alert()
{
$error = error_get_last();
if (!empty($error)) {
mail('mail@example.com', 'Ошибка на сайте example.com', print_r($error, true));
}
}
PHP
Стоит учесть что оператор управления ошибками (знак @) работать в данном случаи не будет и письмо будет отправляться при каждой ошибке.
Второй метод использует «пользовательский обработчик ошибок», поэтому в браузер ошибки выводится не будут.
function error_alert($type, $message, $file, $line, $vars)
{
$error = array(
'type' => $type,
'message' => $message,
'file' => $file,
'line' => $line
);
error_log(print_r($error, true), 1, 'mail@example.com', 'From: mail@example.com');
}
set_error_handler('error_alert');
PHP
4
Пользовательские ошибки
PHP позволяет разработчику самому объявлять ошибки, которые выведутся в браузере или в логе. Для создания ошибки используется функция trigger_error()
:
trigger_error('Пользовательская ошибка', E_USER_ERROR);
PHP
Результат:
Fatal error: Пользовательская ошибка in /public_html/script.php on line 2
E_USER_ERROR
– критическая ошибка,E_USER_WARNING
– не критическая,E_USER_NOTICE
– сообщения которые не являются ошибками,E_USER_DEPRECATED
– сообщения о устаревшем коде.
10.10.2019, обновлено 09.10.2021
Другие публикации
Список основных кодов состояния HTTP, без WebDAV.
Изображения нужно сжимать для ускорения скорости загрузки сайта, но как это сделать? На многих хостингах нет…
JSON (JavaScript Object Notation) – текстовый формат обмена данными, основанный на JavaScript, который представляет собой набор пар {ключ: значение}. Значение может быть массивом, числом, строкой и…
phpQuery – это удобный HTML парсер взявший за основу селекторы, фильтры и методы jQuery, которые позволяют…
AJAX позволяет отправить и получить данные без перезагрузки страницы. Например, делать проверку форм, подгружать контент и т.д. А функции JQuery значительно упрощают работу.
После регистрации в системе эквайринга Сбербанка и получив доступ к тестовой среде, можно приступить к интеграции с…