Перенаправление htaccess для угловых маршрутов
У меня есть угловое приложение с несколькими маршрутами, такими как:
site.com/
site.com/page
site.com/page/4
Используя режим маршрутизации html5 angular, они корректно разрешаются, когда вы щелкаете ссылки на них из приложения, но, конечно, вы получаете 404 ошибки, когда вы выполняете жесткое обновление. Чтобы это исправить, я попытался реализовать базовую переписку htaccess.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_METHOD} !OPTIONS
RewriteRule ^(.*)$ index.html [L]
Это работает для угловых запросов, однако, когда я пытаюсь загрузить сценарии или сделать ajax-вызовы в моем домене, например:
<script src="/app/programs/script.js"></script>
Этот скрипт не загружается - его запрос перенаправляется, и он пытается загрузить страницу index.html, поскольку.htaccess считает, что он должен перенаправить запрос - не зная, что этот файл существует, и он должен загрузить файл вместо перенаправления.
Можно ли как-нибудь разрешить htaccess перенаправить запрос в index.html (с параметрами view) только в том случае, если нет фактического файла, в который он должен разрешить?
11 ответов
Используйте фрагмент как:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) /index.html [NC,L]
Это позволит перейти к фактическому ресурсу, если таковой имеется, и к index.html
для всех маршрутов AngularJS.
Существует проблема, если приложение запрошено directive
файл шаблона, но файл отсутствует. В некоторых случаях это приводило к тому, что приложение запрашивало несколько файлов сценариев в index.html
,
мы должны отправить 404
ответ вместо index.html
файл, если файл не существует. Поэтому я добавляю простой шаблон регулярных выражений для определения отсутствующего запроса файла.
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested pattern is file and file doesn't exist, send 404
RewriteCond %{REQUEST_URI} ^(\/[a-z_\-\s0-9\.]+)+\.[a-zA-Z]{2,4}$
RewriteRule ^ - [L,R=404]
# otherwise use history router
RewriteRule ^ /index.html
В моем случае я создаю.htaccess файл, как показано ниже
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) ./index.html [NC,L]
только что добавлен. перед /index.html и добавьте этот файл в мой домен, например https://example.com/subfolder и он работает нормально
Решение для бедного человека (без использования mod_rewrite):
ErrorDocument 404 /index.html
Проверьте эту ссылку: /questions/38752586/razvernut-angular-2-na-servere-apache/38752609#38752609 Создать .htaccess
файл в корневой папке и поместите его в .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
Я предоставлю другой подробный файл htaccess на тот случай, если вам нужно:
- Рассмотрим baseUrl и индексный файл по умолчанию
- Удалить косую черту для управления:params
Вот мой htaccess, очень близкий, но более конкретный:
DirectoryIndex index.html
RewriteEngine on
RewriteBase /subDir
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) index.html [NC,L]
На есть отличный «генератор Angular» .julianpoemp.github.io/ngx-htaccess-generator/
Генератор с открытым исходным кодом (исходный код можно найти на github.com/julianpoemp/ngx-htaccess-generator ).
Сгенерированный
.htaccess
выглядит так по умолчанию и отлично работает для меня:
# Generated with ngx-htaccess-generator v1.2.0
# Check for updates: https://julianpoemp.github.io/ngx-htaccess-generator/
#
# Transparency notice: Some parts were extracted from
# Apache Server Configs v5.0.0 | MIT License
# https://github.com/h5bp/server-configs-apache
# Extracted parts are wrapped by "START Extract from ASC"
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirection of requests to index.html
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^.*$ - [NC,L]
# Redirect all non-file routes to index.html
RewriteRule ^(?!.*\.).*$ index.html [NC,L]
</IfModule>
Успешно протестировано с Angular
13.0.3
.
В моем случае нам нужно было больше возможностей .htaccess
конфигурация, например:
- Принудительное использование протокола HTTPS (закомментировано ниже).
- Перевод
Authorization
заголовок вHTTP_AUTHORIZATION
переменная окружения. - Совместное использование ресурсов между источниками (CORS).
- И отключил кеширование для определенных форматов (тоже закомментировано).
# If mod_rewrite is not present.
<IfModule !mod_rewrite.c>
FallbackResource /index.html
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
# Prefix for all rewritten routes ("index.html" gets "/index.html").
RewriteBase /
# Redirects to HTTPS protocol (once uncommented).
#
# RewriteCond %{HTTPS} !on
# RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]
# Make sure Authorization HTTP header is available.
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Allows access to existing files or dirs.
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
# Prevents treating the main-script as a route.
RewriteRule ^index\.html$ - [L]
# Redirect anything else to main-script
RewriteRule ^(.*) index.html [NC,L]
</IfModule>
# Enable Cross-Origin Resource Sharing (CORS)
#
<IfModule mod_headers.c>
Header merge Vary Origin
# Allows any origin (just like "*", but works in more cases)
SetEnvIf Origin "^(http(s)?://[^/:]*(?::\d{1,5})?)?" REQUEST_ORIGIN=$1
Header always append Access-Control-Allow-Origin %{REQUEST_ORIGIN}e env=REQUEST_ORIGIN
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
Header always set Access-Control-Allow-Headers "*"
Header always set Access-Control-Expose-Headers "*"
</IfModule>
# Disables Browser caching for production (edit pattern as you wish).
#
#<FilesMatch "\.(html|htm|js|json|css)$">
# <IfModule mod_headers.c>
# FileETag None
# Header unset ETag
# Header unset Pragma
# Header unset Cache-Control
# Header unset Last-Modified
# Header set Pragma "no-cache"
# Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
# Header set Expires "Mon, 10 Apr 1972 00:00:00 GMT"
# </IfModule>
#</FilesMatch>
Примечание: мы используем[L]
вместо того [L,R=301]
поскольку последнее заставляет браузер кешировать перенаправления навсегда (и даже если когда-нибудь этот маршрут является файлом, он все равно будет перенаправлен).
Для Angular 2+ работает следующий файл.
Здесь.htaccess
содержание:
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirection of requests to index.html
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^.*$ - [NC,L]
# Redirect all non-file routes to index.html
RewriteRule ^(?!.*\.).*$ index.html [NC,L]
</IfModule>
Если вы не создали.htacess
файл еще есть, создайте его в/public_html
каталог.
Использование этого фрагмента все еще работает. Я использую cpanel для сайта, который создал для клиента, использующего Angular 13. Я получал ошибку 404, когда обновлял страницу, и ту же ошибку 404, когда пытался перейти на другую страницу из браузера. Я не уверен, когда код htaccess был сгенерирован на хостинг-сайте, был ли он создан с помощью инструмента или был ли он добавлен при создании SSL для этого сайта. Я добавил приведенный выше фрагмент к тому, что уже было, и это сработало!
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?domain name\.com$ [NC]
RewriteRule ^(.*)$ https://domain name.com/$1 [L,R=301]
#Redirection of requests to index.html
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) /index.html [NC,L]
Поскольку angular — это приложение AJAX, html4 не может его реализовать. Все, что вам нужно сделать, это активировать режим html5 в файле .htaccess.
angular.module('main', []).config(['$locationProvider', function($locationProvider) {
...
$locationProvider.html5Mode(true);
...
});
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html