Перенаправление 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
Другие вопросы по тегам