.htaccess — это файл для настройки веб-сервера Apache. С его помощью можно ограничить доступ к сайту на основе разных параметров, настроить редиректы, защитить картинки от воровства, ускорить работу сайта при помощи сжатия и кэширования и ещё много чего полезного.

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

Содержание

  1. Что такое .htaccess и зачем он нужен
  2. Где находится .htaccess
  3. Как создать файл .htaccess
  4. Синтаксис .htaccess
  5. Как настроить .htaccess
  6. Если .htaccess не работает

Что такое .htaccess и зачем он нужен

Информация в этом разделе — для общего понимания. Мы специально начнём немного издалека и немного всё упростим, чтобы было понятно начинающим.

Для работы сайтов в интернете используется специальная программа — веб-сервер. Она обрабатывает запросы пользователей и решает, как на них ответить: показать запрашиваемую страницу, совершить редирект или вообще запретить доступ.

Самый популярных веб-сервер называется Apache. Большинство сайтов работают именно с его помощью. Настраивается он при помощи конфигурационных файлов. Это текстовые файлы, где прописывают специальные команды (директивы, правила), которые и указывают веб-серверу, как вести себя при обработке разных запросов.

Главный конфигурационный файл Apache называется httpd.conf или apache.conf (в зависимости от дистрибутива ОС). По возможности команды рекомендуется указывать именно в нём, но к нему не всегда есть доступ. 

Например, доступа к httpd.conf нет на виртуальном хостинге, где на одном сервере обычно работают сотни сайтов. В такой ситуации давать всем пользователям доступ к основному конфигурационному файлу опасно, ведь тогда любой сможет изменить настройки остальных пользователей.

Для таких случаев и придумали файл .htaccess. Директивы в нём распространяются только на тот каталог, в котором он находится, и на все дочерние каталоги. Это даёт возможность устанавливать для отдельных каталогов на сервере свои параметры Apache, которые отличаются от основной конфигурации.

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

.htaccess — дополнительный конфигурационный файл Apache. С его помощью можно устанавливать параметры веб-сервера в отдельных папках без изменений в основном конфигурационном файле.

Где находится .htaccess

Обычно файл .htaccess размещают в корневой папке сайта, чтобы эффект от команд распространялся сразу на весь сайт. Как мы писали в предыдущем разделе, .htaccess действует на папку, в которой находится, а также на все дочерние папки.

Если вы не находите .htaccess в корневой папке, возможно, он просто скрыт и вам нужно включить отображение скрытых файлов.

Как показать скрытые файлы в cPanel

В дочерних папках могут быть дополнительные файлы .htaccess — чтобы у разных разделов сайта были разные параметры веб-сервера. Но в большинстве случаев одного .htaccess вполне достаточно.

Пример ситуации, когда может быть выгодно создать несколько .htaccess файлов — у вас большой проект, где задействовано несколько CMS. Условно говоря, главный сайт сделан на одной CMS, а блог — на WordPress.

Как создать файл .htaccess

На локальном компьютере создать .htaccess можно при помощи любого текстового редактора. Просто создайте новый текстовый документ и сохраните его с правильным именем.

На хостинге .htaccess можно создать при помощи командной строки, FTP-клиента или панели управления хостингом.

Как создать файл в FTP-клиенте FileZilla

Как создать файл в cPanel

Имя файла — .htaccess. Обязательно с точкой в начале и обязательно маленькими буквами. Для Apache .Htaccess и .htaccess это разные файлы. Также у файла не должно быть расширения: .htaccess.txt это уже не то, нужно именно .htaccess.

Синтаксис .htaccess

Каждая директива должна начинаться с новой строки. Между группами несвязанных друг с другом директив обычно оставляют одну пустую строку, чтобы было проще читать файл.

К директивам в .htaccess можно добавлять комментарии при помощи символа #, чтобы ещё больше повысить читабельность файла. Все строки, которые начинаются с этого символа, веб-сервер будет игнорировать.

Также символ # можно использовать, чтобы отключить директиву, не удаляя её из файла. Просто поставьте этот символ в начале строки. На языке сисадминов это называется «закомментировать».

Вот фрагмент .htaccess для примера, как можно оформить файл:

# 301 редиректы
Redirect 301 /blog/old-article-1/ https://vashdomen.com/blog/new-article-1/
Redirect 301 /blog/old-article-2/ https://vashdomen.com/blog/new-article-2/
Redirect 301 /blog/old-article-3/ https://vashdomen.com/blog/new-article-3/

# Редирект с www на без www
RewriteCond %{HTTP_HOST} ^www.vashdomen\.com$ [NC]
RewriteRule ^(.*)$ http://vashdomen.com/$1 [R=301,L]

# Свои страницы с ошибками
ErrorDocument 403 /errors/403.html
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html
ErrorDocument 504 /errors/504.html

# Максимально допустимое время выполнения скрипта PHP (в секундах)
php_value max_execution_time 60

Правила для .htaccess

В этом разделе рассмотрим несколько популярных возможностей .htaccess, которые помогут улучшить работу вашего сайта. Это не все доступные директивы, а только те, которые по нашему опыту используют чаще всего. Если чего-то важного не хватает, поделитесь своим мнением в комментариях.

Изменения вступают в силу сразу после сохранения файла. Перезагрузка веб-сервера не нужна (в отличие от изменений в httpd.conf). Но кэш браузера никто не отменял, поэтому для проверки директив рекомендуем использовать режим инкогнито в браузере.

Ограничить доступ к сайту

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

Можно указывать IP-адреса по одному, а можно заблокировать сразу целый диапазон. Для этого либо укажите часть IP-адреса в формате 123.45.*.* , либо высчитайте более точный диапазон в формате CIDR при помощи специального калькулятора.

# Запретить доступ к сайту с конкретных IP-адресов
Order Allow,Deny
Allow from all
Deny from 123.45.67.89
Deny from 111.22.33.44

# Запретить доступ для любых IP, которые начинаются с 111.22
Deny from 111.22.*.*

# Запретить доступ для диапазона 111.22.33.0 – 111.22.33.199
Deny from 111.22.33.0/25
Deny from 111.22.33.128/26
Deny from 111.22.33.192/29

Если нужно наоборот — запретить доступ для всех, но разрешить для конкретных IP (например, на время разработки сайта) используйте такую команду:

# Разрешить доступ к сайту только с конкретных IP-адресов
Order Deny,Allow
Deny from all
Allow from 123.45.67.89
Allow from 111.22.33.44

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

Если у вас сайт на WordPress, конфигурационный файл базы данных называется wp-config.php. Закрыть к нему доступ извне можно при помощи такой команды:

# Запретить доступ к wp-config.php
<Files wp-config.php>
Order Allow,Deny
Deny from all
</Files>

Таким же образом можно заблокировать доступ извне к целой группе системных файлов. Для этого используется директива FilesMatch. Она работает так же как и Files, но поддерживает регулярные выражения.

# Запретить доступ к системным файлам
<FilesMatch "\.(htaccess|htpasswd|ini|phps|fla|psd|log|sh)$">
Order Allow,Deny
Deny from all
</FilesMatch>

Ну и последний лайфхак — разрешить доступ к админке сайта только с определённых IP-адресов. Например, с вашего домашнего IP или адреса вашего офисного VPN. 

Для сайта на WordPress для этого достаточно закрыть доступ к файлам wp-login.php и xmlrpc.php. Делается это при помощи такой команды:

# Разрешить доступ к админке WordPress только с конкретных IP-адресов
<FilesMatch "^(wp-login\.php|xmlrpc\.php)$">
Order deny,allow
Deny from all
Allow from 123.45.67.89
Allow from 111.22.33.44
</FilesMatch>

Настроить доступ к сайту по паролю

Ещё один способ ограничить доступ к сайту — сделать так, чтобы он открывался по паролю. 

Как и в случае с блокировкой по IP-адресу, можно использовать директиву в обычном виде, чтобы установить пароль на всю папку, где лежит .htaccess. А можно обернуть директиву в тег <Files> или <FilesMatch>, чтобы установить пароль на один или несколько файлов.

В результате при попытке зайти на сайт или получить доступ к файлу посетитель увидит вот такую форму для ввода пароля:

Вход на сайт по паролю — Настройка .htaccess file

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

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

# Доступ к странице входа в админку WordPress по паролю
<FilesMatch "^(wp-login\.php|xmlrpc\.php)$">
AuthType basic
AuthName "Directory Name"
AuthUserFile /home/username/public_html/auth/.htpasswd
Require valid-user
</FilesMatch>

В этой команде:

  • AuthType — тип аутентификации. Рекомендуем использовать значение «basic».
  • AuthName — вообще, это текст, который посетитель должен видеть в окне ввода пароля. Но в реальности я никогда не видел, чтобы он там отображался. Так что можно вписать тут, что угодно. Например, «Доступ к этой странице защищён».
  • AuthUserFile — путь к файлу .htpasswd с логинами и паролями разрешённых пользователей.
  • Require — требование для предоставления доступа к папке. Значение «valid-user» говорит о том, что доступ получат только те пользователи, которые успешно прошли аутентификацию.

После добавления правила в .htaccess нужно также создать файл .htpasswd, где будут логины и пароли пользователей. Лучше создавать его не в корневой папке сайта, а в какой-то вложенной, чтобы до него нельзя было так просто добраться. Например, в папке /auth.

У записей в файле .htpasswd должен быть формат «пользователь:пароль». Но в целях безопасности пароли лучше не хранить в файле в открытом виде, а зашифровать. Для этого зайдите на сайт генератора .htpasswd, введите там логин с паролем и нажмите «Сгенерировать».

Генератор паролей для .htpasswd — Как настроить доступ к сайту по паролю в .htaccess

Скопируйте получившуюся строку и добавьте её в файл .htpasswd. Детали входа для каждого нового пользователя в этом файле должны идти с новой строки. На самом сайте используйте обычную версию пароля, зашифрованная нужна только для того, чтобы не хранить пароль в открытом виде.

Содержимое файла .htpasswd — Как сделать доступ к сайту по паролю в .htaccess

Заблокировать ботов

Если вы заметили, что сайт стал медленнее работать, потому что его сканируют разные боты, запретите им это делать при помощи такой директивы:

# Блокировка ботов
SetEnvIfNoCase User-agent (Abonti|AhrefsBot|Aport|AspiegelBot|asterias|Baiduspider|BDCbot|Birubot|BLEXBot|BUbiNG|BuiltBotTough|Bullseye|BunnySlippers|Butterfly|CamontSpider|CCBot|Cegbfeieh|CheeseBot|CherryPicker|coccoc|CopyRightCheck|cosmos|crawler|Crescent|DeuSu|discobot|DittoSpyder|DnyzBot|DomainCrawler|DotBot|EasouSpider|EmailCollector|EmailSiphon|EmailWolf|EroCrawler|Exabot|ExtractorPro|Ezooms|FairShare|Fasterfox|FeedBooster|Foobot|Genieo|Gigabot|GrapeshotCrawler|Harvest|hloader|HTTrack|humanlinks|HybridBot|Incutio|InfoNaviRobot|InternetSeer|IstellaBot|JamesBOT|JennyBot|k2spider|kmSearchBot|larbin|LexiBot|libWeb|libwww|Linguee|LinkExchanger|LinkextractorPro|linko|LinkWalker|lmspider|LNSpiderguy|magpie|MaxPointCrawler|MegaIndex|memoryBot|MIIxpc|Mippin|MJ12bot|MLBot|moget|MSIECrawler|NetAnts|NetpeakCheckerBot|NICErsPRO|NjuiceBot|NPBot|Nutch|OLEcrawler|Openfind|PostRank|ProWebWalker|Purebot|PycURL|RepoMonkey|Riddler|RMA|Scrapy|SemrushBot|serf|SeznamBot|SISTRIX|SiteBot|SiteSnagger|Serpstat|Slurp|SnapPreviewBot|Sogou|Soup|SpankBot|spanner|spbot|Spinn3r|SpyFu|suggybot|SurveyBot|suzuran|SWeb|Teleport|Telesoft|TheNomad|TightTwatBot|Titan|True_Robot|ttCrawler|turingos|TurnitinBot|UbiCrawler|UnisterBot|Unknown|VCI|Vedma|Voyager|WBSearchBot|WebAuto|WebBandit|WebCopier|WebEnhancer|WebmasterWorldForumBot|WebReaper|WebSauger|WebStripper|Wotbox|Yeti|YottosBot|Zao|Zeus|ZyBORG) not-allowed=1
Order Allow,Deny
Allow from ALL
Deny from env=not-allowed

Это только некоторые боты, вообще, их гораздо больше. Если в директиве нет бота, который нагружает ваш сайт, добавьте его самостоятельно.

Запретить индексацию каталогов

По умолчанию, если кто-то напрямую обратится к какому-то каталогу у вас на хостинге, веб-сервер покажет его содержимое. В результате любой сможет покопаться в ваших файлах, скачать их и в худшем случае — найти уязвимости.

Содержимое каталога — Как запретить индексацию каталогов в .htaccess

Такие вещи обязательно нужно запрещать. Не нужно рисковать безопасностью вашего сайта. В .htaccess это делается при помощи директивы Options. Она сделает так, чтобы при прямом обращении к каталогу возникала 403 ошибка:

# Запретить индексацию каталогов
Options -Indexes

Настроить редирект

В этом разделе рассмотрим несколько наиболее популярных ситуаций, когда нужно настроить редирект. Но вообще, это обширная тема с кучей нюансов. Подробно рассматриваем их в отдельной статье:

Как сделать 301 редирект в .htaccess

Редирект с одной страницы на другую (если сменили URL страницы):

Redirect 301 /old-url-1 /new-url-1

Редирект с одного файла в корневой папке сайта на другой (если сменили название файла):

Redirect 301 /contact-us.php /contact.php

Редирект всех страниц сайта на такие же страницы на другом домене:

Redirect 301 / https://vashdomen.ua/

Редирект всех файлов с расширением .html на такие же файлы с расширением .php:

RedirectMatch 301 (.*)\.html /$1.php

Перенаправление домена без www на домен с www:

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\..* [NC]
RewriteRule ^(.*) http://www.%{HTTP_HOST}/$1 [R=301]

И наоборот — перенаправление домена с www на домен без www:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Принудительное перенаправление с HTTP на HTTPs (предварительно нужно установить SSL-сертификат):

RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Защитить картинки от воровства

Другое название такой настройки — защита от хотлинкинга (от англ. hotlinking — использование прямых ссылок). 

Речь о ситуации, когда кто-то разместил у себя на сайте изображения по ссылкам на ваш сервер. В итоге получается так, что изображения загружаются с вашего сервера, но трафик идёт на чужой сайт. То есть кто-то втихаря расходует ресурсы вашего хостинга. Отучить от этого можно при помощи такой директивы:

# Запрет на воровство картинок (hotlinking)
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https://(www\.)?vashdomen\.com/.*$ [NC]
RewriteRule \.(gif|jpg|swf|flv|png)$ https://www.vashdomen.com/feed.gif [R=302,L]

Работает она так: вы размещаете у себя на сервере специальное изображение для таких воришек, и когда они размещают какое угодно ваше изображение у себя на сайте, вместо него отображается именно заготовленная картинка.

Что именно загрузить в качестве заготовленной картинки — дело ваше. Можете нарисовать в фотошопе плакат «Я ворую чужие картинки» или баннер с рекламой собственных услуг. Тут всё зависит от вашей фантазии и желания наказать хитрецов.

Путь к изображению для воришек указывается в директиве RewriteRule.

Назначить свои страницы ошибок

Если хотите отображать вместо стандартных страниц с ошибками страницы со своим дизайном, используйте такую директиву:

# Свои страницы ошибок
ErrorDocument 403 /errors/403.html
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html
ErrorDocument 504 /errors/504.html

В этой директиве /errors/403.html — это абсолютный путь к файлу страницы (без учёта доменного имени).

Полный список кодов состояния вы найдёте в нашей статье «Коды состояния HTTP». Не обязательно создавать свою страницу для каждого кода, можно только для самых распространенных ошибок: 404 Not Found и 500 Internal Server Error

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

Настроить сжатие файлов

Для этого в Apache используется модуль mod_deflate. В примере перечислены не все типы файлов. Если нужно, добавьте недостающие вручную.

Список MIME-типов файлов

# Сжатие для файлов HTML, CSS, JavaScript, Text, XML и шрифтов
AddOutputFilterByType DEFLATE application/javascript application/x-javascript application/xml application/xhtml+xml image/svg+xml text/css text/html text/javascript text/plain text/xml

Настроить кэширование

Устанавливаем, сколько времени (в секундах) в браузере посетителя должны храниться файлы тех или иных типов. В примере перечислены не все типы файлов. Если нужно, добавьте недостающие вручную.

Список MIME-типов файлов

# Кэширование файлов
ExpiresActive On
ExpiresDefault A300
ExpiresByType image/x-icon A2419200
ExpiresByType application/x-javascript A3600
ExpiresByType text/css A3600
ExpiresByType image/gif A604800
ExpiresByType image/png A604800
ExpiresByType image/jpeg A604800
ExpiresByType text/plain A300
ExpiresByType application/x-shockwave-flash A604800
ExpiresByType video/x-flv A604800
ExpiresByType application/pdf A604800
ExpiresByType text/html A300

Расшифровка временных отрезков (для удобства):

  • 300 — 5 минут;
  • 3600 — 1 час;
  • 86400 — 1 день;
  • 604800 — 7 дней;
  • 2419200 — 4 недели.

Изменить параметры PHP

Увеличить время ожидания веб-сервера при выполнении скрипта. Поможет избежать зависания веб-сервера при обработке тяжёлых скриптов.

# Время ожидания веб-сервера при выполнении скрипта
php_value max_execution_time 60

Определить максимальный размер загружаемого файла (в примере — 128 Мб):

# Максимальный размер загружаемого файла
php_value upload_max_filesize 128M

Вывести ошибки РНР в отдельный файл:

# Вывод ошибок PHP в отдельный файл
php_flag  log_errors on
php_value error_log  /home/username/public_html/php_errors.log

В этой директиве /home/username/public_html/php_errors.log — путь к файлу с логами. Не забудьте его изменить.

Эти директивы не всегда поддерживаются на виртуальном хостинге. Например, у нас на виртуальном хостинге их использовать получится, только на VPS. Причина в том, что веб-сервер, который работает в режиме suPHP, не поддерживает директивы php_flag и php_value

Решением в этой ситуации будет использовать раздел «Select PHP Version» в панели управления cPanel. Там тоже можно изменить эти параметры. Альтернативный вариант — создать локальный файл php.ini и прописать лимиты в нём.

Изменить корневую папку сайта

Обычно на виртуальном хостинге файлы сайта размещают в корневой папке домена. По умолчанию для основного домена эта папка называется public_html, а для дополнительного — так же как и сам домен.

В некоторых фреймворках встречается другая структура, в которой файлы проекта лежат не в корневой папке домена, а в подпапке. Например, Laravel, где файлы проекта лежат в подпапке /public. Из-за этого, после того как вы зальёте проект на хостинг и введёте в браузере ваш домен, вы увидите список всех папок и файлов вместо сайта.

Решение в такой ситуации — добавить в .htaccess такой редирект, который будет перенаправлять все запросы в подпапку:

RewriteEngine On
RewriteCond %{REQUEST_URI} !/public
RewriteRule ^(.*)$ public/$1 [L]

Если .htaccess не работает

Когда вы добавляете правило в .htaccess и не наблюдаете ожидаемого эффекта, причина не всегда очевидна. Особенно на виртуальном хостинге, где нет доступа к основным логам веб-сервера. Вот основные причины, почему так может быть.

Причина №1: .htaccess отключён в httpd.conf

Возможность использовать .htaccess прописывается в главном конфигурационном файле Apache при помощи директивы AllowOverride. Если она указана со значением None, веб-сервер будет игнорировать .htaccess.

Такая проблема может быть только на VPS или выделенном сервере. Если у вас виртуальный хостинг, дело 100% в чём-то другом.

Причина №2: Директиву нельзя использовать в .htaccess

Ещё одна особенность директивы AllowOverride — с её помощью можно разрешить в .htaccess все директивы, а можно только отдельные группы директив. Подробнее об этой директиве читайте в официальной документации Apache.

# Разрешить в .htaccess все директивы
AllowOverride All

# Разрешить в .htaccess только директивы групп «Limit» и «FileInfo»
AllowOverride Limit FileInfo

Ещё есть директива AllowOverrideList, при помощи которой можно перечислить конкретные директивы, которые разрешены в .htaccess (а не группы директив, как в случае с AllowOverride). Подробнее об этой директиве читайте в официальной документации Apache.

# Запретить все директивы, кроме директив Redirect и RedirectMatch
AllowOverride None
AllowOverrideList Redirect RedirectMatch

# Разрешить группу директив «AuthConfig» 
# Разрешить директивы CookieTracking и CookieName из группы «FileInfo»
AllowOverride AuthConfig
AllowOverrideList CookieTracking CookieName

Может быть так, что при попытке использовать запрещённую директиву в .htaccess возникнет ошибка 500 Internal Server Error. Но это не обязательно: у AllowOverride есть также параметр Nonfatal, благодаря которому можно не выводить ошибку, а просто делать запись в логах.

Проверить логи ошибок получится только у пользователей VPS или выделенного сервера. На виртуальном хостинге к этим логам доступа нет.

Причина №3: Неправильный синтаксис директивы

В случае с опечаткой результат может быть такой же, как если бы директива была запрещена — ошибка 500 Internal Server Error. Если администратор сервера не отключил такое поведение при помощи параметра Nonfatal в главном конфигурационном файле.

Если хотите, можете проверить содержимое файла на опечатки при помощи специального сервиса — валидатора .htaccess.

Причина №4: Неправильное название файла

Имя файла должно начинаться с точки, в нём должны быть только маленькие буквы и не должно быть расширения. Файл буквально называется .htaccess. Не htaccess, не .htaccess.txt и не .Htaccess.

Теоретически, дело может также быть в том, что стандартное имя .htaccess изменили в главном конфигурационном файле веб-сервера. Это делается при помощи директивы AccessFileName. Например, вот так:

# Изменить имя файла .htaccess
AccessFileName .config

Причина №5: На сервере несколько файлов .htaccess

Правила .htaccess выполняются в том порядке, в котором их нашёл Apache. То есть сначала директивы из .htaccess в корневой папке, затем директивы из .htaccess в дочерних папках. Из-за этого может случиться так, что директивы в файле, который расположен глубже в дереве каталогов, перезапишут директивы из расположенных ваше файлов.

Причина №6: Неправильный порядок директив

Чаще всего такое бывает с директивами для редиректа — RewriteRule. Какая-то вышестоящая директива может преобразовать запрос таким образом, что он больше не будет подходить под условия в следующих директивах. При этом сама по себе неработающая директива может быть составлена правильно.

Чтобы проверить этот сценарий, попробуйте переставить неработающую директиву в самое начало .htaccess и пересохранить файл.

Что дальше

Надеемся, статья оказалась для вас полезной. Если вы нашли ошибку или в статье не хватает какой-то важной информации, поделитесь своими мыслями в комментариях.

Была ли статья полезной?

Спасибо за отзыв!