角路由的 htaccess 重定向

我有一个有角度的应用程序,有几条路线,例如:

site.com/
site.com/page
site.com/page/4

使用 angle 的 html5路由模式,当您从应用程序中单击指向它们的链接时,可以正确地解决这些问题,但是当您进行硬刷新时,当然会出现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 (使用视图参数) ?

113577 次浏览

Use a snippet like:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]


RewriteRule ^(.*) /index.html [NC,L]

This will skip to the actual resource if there is one, and to index.html for all AngularJS routes.

There is a problem if app requested directive template file, but file is missing. In some case it caused app requested multiple script file in the index.html.

we should send 404 response instead of index.html file if file does not exist. So i add simple regex pattern to identify missing file request.

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

A poor man's solution (not using mod_rewrite):

ErrorDocument 404 /index.html

I will provide another detailed htaccess file in case you need to :

  • Considerate the baseUrl and default index file
  • Remove the leading slash to manage :params

Here is my htaccess, very close, but more specific :

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]

Check out this link : https://stackoverflow.com/a/49455101/5899936 Create .htaccess file in root folder and pase this in the .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>

In my case i create .htaccess file like below

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]


RewriteRule ^(.*) ./index.html [NC,L]

just added . before /index.html and add that file in my domain like https://example.com/subfolder and it's works fine

In my case, we needed a more feature reach .htaccess configuration, like with:

  • Forcing to HTTPS protocol (commented out in below).
  • Translation of Authorization header to HTTP_AUTHORIZATION environment variable.
  • Cross-Origin Resource Sharing (CORS).
  • And disabled caching for specific formats (commented out as well).

# 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)$">
#   # Ensures "Expires" header is not overridden by module.
#   <IfModule mod_expires.c>
#       ExpiresActive Off
#   </IfModule>
#   <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>


Note: We use [L] instead of [L,R=301] as the latter causes Browser to cache redirects permanently (and even if someday that route is a file it will still get redirected).

There is a great "Angular .htaccess generator" available on julianpoemp.github.io/ngx-htaccess-generator/.

The generator is open-source (the source code can be found on github.com/julianpoemp/ngx-htaccess-generator).

The generated .htaccess looks like this by default and works fine for me:

# 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>

Successfully tested with Angular 13.0.3.