【问题标题】:htaccess: add path parameter (country code) to URL & serve index.htmlhtaccess:将路径参数(国家代码)添加到 URL 并提供 index.html
【发布时间】:2021-02-17 23:59:33
【问题描述】:

我想通过 htaccess 向 Angular 应用程序添加国家代码“en-gb”。文件夹“en-gb”不存在。我只希望它显示在 url 中并服务 index.html

我的 .htaccess

<IfModule mod_rewrite.c>
    RewriteEngine On
   
    #does the folder AND file exist? (ie. /index.html & css/style.css)
    #yes - serve it & pop out of htaccess
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
    RewriteRule ^ - [L]

    #does the url already have a country flag set?
    #no - add country flag (ie. http://angular.wlocal/ -> http://angular.wlocal/en-gb)
    RewriteCond %{REQUEST_URI} !/en-gb
    RewriteRule ^(.*)$ en-gb/$1
    
    #if file folder not found, serve index.html (ie. http://angular.wlocal/en-gb/this-does-not-exist -> should serve index.html)
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . index.html [L]

</IfModule>

我的虚拟主机

<VirtualHost 192.168.56.1:80>
    DocumentRoot "C:\Users\Dev\Documents\angular-10\dist"
    ServerName angular.wlocal
    ServerAlias angular.wlocal
    RemoteIPHeader X-Forwarded-For

    <Directory "C:\Users\Dev\Documents\angular-10\dist">
        DirectoryIndex index.html
    AllowOverride ALL
    Require all granted
    </Directory>
</VirtualHost>

如果我删除下面,网址会改变,但我会得到The requested URL /en-gb/ was not found on this server.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.html [L]

目前,该 URL 没有更改为 /en-gb - 我认为这是因为 RewriteRule . index.html [L] 删除了它。

如何在保留此 /en-gb 重写的同时从根目录提供 index.html?

【问题讨论】:

  • "这也应该适用于目录。例如。http://angular.wlocal/css/style.css" - nitpick,但这是一个文件,而不是目录。大概您的内部链接已经包含此en-gb 国家/语言代码?

标签: apache .htaccess mod-rewrite


【解决方案1】:

....保留这个 /en-gb 重写?

如果您希望更改 URL,那么这需要是一个外部“重定向”,而不是“重写”。

#does the folder AND file exist? (ie. /index.html & css/style.css)
#yes - serve it & pop out of htaccess
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

这目前没有做任何事情,因为同一个请求不能映射到一个文件一个目录。这些条件需要进行或运算。在这种情况下测试REQUEST_FILENAME 比连接两个服务器变量更简单。

请尝试以下方法:

RewriteEngine On

#does the folder OR file exist? (ie. /index.html & css/style.css)
#yes - pop out of htaccess and allow Appache to serve it
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

#does the url already have a country flag set?
#no - add country flag (ie. http://angular.wlocal/ -> http://angular.wlocal/en-gb)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule !^en-gb/ /en-gb%{REQUEST_URI} [R=302,L]

#if file folder not found, serve index.html (ie. http://angular.wlocal/en-gb/this-does-not-exist -> should serve index.html)
RewriteRule . index.html [L]

/en-gb添加前缀...您可以通过在RewriteRule中执行此检查来避免条件检查它是否已经以/en-gb为前缀模式 并在 substitution 字符串中使用 REQUEST_URI 服务器变量而不是 $1 反向引用。对REDIRECT_STATUS 环境变量的检查只是确保我们只处理直接请求,而不是重写对index.html 的请求。

在来自客户端的初始请求中,REDIRECT_STATUS env var 为空(未设置)。但是,当请求被重写为index.html(通过以下规则)时,此环境变量将更新为200(如 200 OK HTTP 状态)。因此,通过检查此环境变量是否为空(即^$),我们可以避免为内部重写处理规则(在这种情况下会导致无限循环)。另一种方法是在以下重写中简单地使用END 标志(Apache 2.4+),以防止重写引擎循环,但这可能需要在未来的其他重写中添加,而 Apache 版本实际上并没有在问题中说明。

请注意,这是一个 302(临时)重定向。如果这是永久性的,则将其更改为 301 - 但只有在您确认它可以正常工作后才能使用。否则你可能会遇到缓存问题。

没有必要在最后一条规则中重新检查请求是否映射到文件或目录,因为第一条规则已经执行了此检查。

&lt;IfModule mod_rewrite.c&gt; 包装在这里不是必需的,应该删除

如果我删除下面,网址会改变,但是

如果您删除最后一条规则,那么您的 Angular 应用程序将永远不会被调用,因此您确实会得到 404。而且,简单地删除最后一条规则不应导致 URL 更改,因为之前的规则仍然是重写,这里没有其他“重定向”?

【讨论】:

  • 这是一个很好的解决方案,谢谢分享。关于RewriteCond %{ENV:REDIRECT_STATUS} ^$,如果我没记错的话(我对htaccess知之甚少)这是我们正在检查的环境值吗?如果您能指导更多相同的内容,将不胜感激,谢谢。
  • @RavinderSingh13 谢谢。是的,REDIRECT_STATUS 是一个环境变量(相对于服务器变量)。我已经更新了我的答案以进一步解释这一点。另一种方法是检查THE_REQUEST,但我发现REDIRECT_STATUS 在大多数情况下使用起来更容易/更简单,因为您只需要防止重定向/重写循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
  • 2016-08-14
  • 2011-08-12
  • 2021-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多