Я размещаю приложение узла, и моя структура папок выглядит так:
mydomain.com
--index.js
--package.json
--public\test.txt
Я хочу лечить public
в качестве корня моего документа и не разрешать доступ к чему-либо выше, например package.json
.
Я сейчас использую .htaccess
чтобы изменить "корень документа":
RewriteCond %{REQUEST_URI} !public/
RewriteRule (.*) /public/$1 [L]
Это нормально работает, и я могу получить доступ http://example.com/test.txt
, но это также означает, что http://example.com/public/test.txt
тоже работает.
Как я могу предотвратить public
от прямого использования в URL-адресе и использования только за кулисами?
Я пробовал добавить RewriteRule ^public/ - [L,R=404]
до конца, но в итоге возвращаю 404 за все.
Чтобы уточнить, вы на самом деле не меняете корень документа здесь, вы фактически скрываете подкаталог с помощью перезаписи URL. Чтобы действительно изменить корень документа, вам нужно изменить DocumentRoot
директива в конфигурации сервера (как упоминалось в комментариях), что будет иметь другие последствия (ваше приложение узла, вероятно, зависит от DocumentRoot
устанавливается как есть).
RewriteCond %{REQUEST_URI} !public/ RewriteRule (.*) /public/$1 [L]
Это проверяет отсутствие "public /" везде внутри запрошенного URL-пути, что на самом деле не то, что вам нужно. Однако RewriteCond
директива здесь не нужна. Вместо этого вам следует проверять URL-путь в RewriteRule
шаблон. Например:
RewriteRule !^public/ /public%{REQUEST_URI} [L]
Обратите внимание, что REQUEST_URI
Переменная сервера включает префикс косой черты. (Возможно, именно поэтому вы удалили якорь в своем CondPattern для того, чтобы заставить его "работать"?)
Я пробовал добавить
RewriteRule ^public/ - [L,R=404]
до конца, но в итоге возвращаю 404 за все.
Это правильная идея, но это тоже перенаправит переписанный URL-адреса (по другой директиве). Вам нужно только нацелить прямые запросы. Есть несколько способов сделать это. Я предпочитаю проверить REDIRECT_STATUS
переменная окружения, которая пустой изначально и установлено на "200" после первой успешной перезаписи. Например:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^public($|/) - [R=404]
($|/)
- Обратите внимание, что я также сделал конечную косую черту «необязательной», так как она будет соответствовать либо public
или public/
(с помощью чередование) при доступе к пустому каталогу. Это сделано для того, чтобы mod_dir сначала не выполнил перенаправление 301 для добавления завершающей косой черты в каталоге, прежде чем отправлять 404 в ответ на перенаправленный (второй) запрос. Чередование (конец строки или слэш) гарантирует, что public/<foo>
совпадает, но нет public<foo>
, если у вас есть URL-адреса, начинающиеся с "общедоступных" (например, /public-enemy
).
Нет необходимости в L
флаг при использовании кода состояния, отличного от 3xx (или 2xx), как есть подразумевается.
В итоге:
# Block direct requests to the "public" subdirectory
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^public($|/) - [R=404]
# Rewrite all requests that are not already for the "public" subdirectory
RewriteRule !^public/ /public%{REQUEST_URI} [L]
Обратите внимание, что директива блокировки (404) должна быть первой.