假设我有一个名为example.com
的域,并且我希望使用Apache的.htaccess
文件中的重写规则来重写:
https://office.example.com/index.html
至
https://example.com/office/index.html
。
我该怎么做?我在这里查了很多答案,解决方案似乎是这样的:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^office.example.com$
RewriteRule ^(.*)$ https://example.com/office/$1 [L,NC,QSA]
当我在这里测试它时,这个方法是有效的:
https://htaccess.madewithlove.be?share=b40ca72f-86d3-5452-a04b-ac9f24812c57
遗憾的是,它确实会在我的服务器上生成一个错误500。我启用了日志记录,发现这似乎是一个递归问题:
AH00124: Request exceeded the limit of 10 internal redirects.
在日志中,它似乎不断地将office
添加到office
:/office/office/office/...
。我不知道为什么会这样。重写的URL不符合重写条件,那么为什么要这样做呢?
我找到了一种让它“起作用”的方法。如果我将R=301
添加到RewriteRule属性中,则会进行重定向,并且工作正常,但我更希望原来的URL保留在地址栏中。
下面是前两个重定向的日志:
init rewrite engine with requested uri /
applying pattern '^(.*)$' to uri '/'
applying pattern '^(.*)$' to uri '/'
applying pattern '^(.*)$' to uri '/'
pass through /
[perdir /var/www/vhosts/example.com/httpdocs/] strip per-dir prefix: /var/www/vhosts/example.com/httpdocs/ ->
[perdir /var/www/vhosts/example.com/httpdocs/] applying pattern '^(.*)$' to uri ''
[perdir /var/www/vhosts/example.com/httpdocs/] rewrite '' -> 'https://example.com/office/'
reduce https://example.com/office/ -> /office/
[perdir /var/www/vhosts/example.com/httpdocs/] internal redirect with /office/ [INTERNAL REDIRECT]
#1 init rewrite engine with requested uri /office/
#1 applying pattern '^(.*)$' to uri '/office/'
#1 applying pattern '^(.*)$' to uri '/office/'
#1 applying pattern '^(.*)$' to uri '/office/'
#1 pass through /office/
#1 [perdir /var/www/vhosts/example.com/httpdocs/] strip per-dir prefix: /var/www/vhosts/example.com/httpdocs/office/
#1 [perdir /var/www/vhosts/example.com/httpdocs/] applying pattern '^(.*)$' to uri 'office/'
#1 [perdir /var/www/vhosts/example.com/httpdocs/] rewrite 'office/' -> 'https://example.com/office/office/'
#1 reduce https://example.com/office/office/ -> /office/office/
#1 [perdir /var/www/vhosts/example.com/httpdocs/] internal redirect with /office/office/ [INTERNAL REDIRECT]
#2 init rewrite engine with requested uri /office/office/
#2 applying pattern '^(.*)$' to uri '/office/office/'
#2 applying pattern '^(.*)$' to uri '/office/office/'
#2 applying pattern '^(.*)$' to uri '/office/office/'
#2 pass through /office/office/
#2 [perdir /var/www/vhosts/example.com/httpdocs/] add path info postfix: /var/www/vhosts/example.com/httpdocs/office
#2 [perdir /var/www/vhosts/example.com/httpdocs/] strip per-dir prefix: /var/www/vhosts/example.com/httpdocs/office/
#2 [perdir /var/www/vhosts/example.com/httpdocs/] applying pattern '^(.*)$' to uri 'office/office/'
#2 [perdir /var/www/vhosts/example.com/httpdocs/] rewrite 'office/office/' -> 'https://example.com/office/office/off
#2 reduce https://example.com/office/office/office/ -> /office/office/office/
#2 [perdir /var/www/vhosts/example.com/httpdocs/] internal redirect with /office/office/office/ [INTERNAL REDIRECT]
发布于 2020-08-08 14:50:18
RewriteCond %{HTTP_HOST} ^office.example.com$ RewriteRule ^(.*)$ https://example.com/office/$1 L,NC,QSA
令人费解的是,这应该隐式地触发外部302 (临时)重定向,而不是内部重写--当在替换字符串中指定另一个主机到被请求的主机时。(尽管在我的经验中,替换字符串中的任何绝对URL都会触发外部重定向。)
如果它确实触发了内部重写(如日志所示),那么请求的主机名不会更改(因为这不是一个单独的请求),您确实会得到一个重写循环。
但是,如果“子域是主域的别名”而重写是必需的,那么就不需要在替换字符串中指定主机名,您确实需要进行额外的检查,以防止内部重写循环(500错误)。
相反,请尝试以下几点:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteRule !^office office%{REQUEST_URI} [L]
...to排除任何已经启动/office
的请求(包括重写请求)。
不需要NC
和QSA
标志。
或者,如果只针对直接请求(而不是重写请求),则可以选择REDIRECT_STATUS
环境变量(初始请求为空,在第一次成功重写后设置为" 200 ",如200 OK中所示)。
例如:
RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) office/$1 [L]
这有一个额外的“好处”,您也可以有一个名为/office
的子目录。即。/office/office
。
更新:第三个版本是检查REQUEST_URI
服务器变量。但是,我不认为这与上面的第一个版本有什么不同。
RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteCond %{REQUEST_URI} !^/office
RewriteRule ^ office%{REQUEST_URI} [L]
令人遗憾的是,
和您的建议给出了与以前相同的错误。
有两件事要尝试..。
/office%{REQUEST_URI}
和/office/$1
。这将替换字符串更改为URL路径,而不是相对文件系统路径。不过,我不一定期望这会在这方面有任何不同。(外部重定向需要它。)。
RewriteRule
指令中使用END
标志而不是L
--这是一个Apache2.4添加,应该停止所有处理。L
标志“仅”结束当前传递,然后重新启动重写过程(因此需要进行额外检查以防止重写循环)。,但现在任何其他文件(IMG,CSS)都会提供404。
上面的代码重写了所有的东西,所以如果这些静态资源还没有启动/office
的话,它们自然会重写所有的静态资源。(如果他们已经启动了/office
,那么他们应该已经被上述规则排除在外了。)
要排除公共资源,可以设置一个异常(额外的RewriteCond
指令)以排除特定的文件扩展名。例如:
RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif)$
和/或添加一个额外的RewriteCond
指令,以排除已经映射到物理文件的请求(尽管这“稍微”昂贵)。例如:
RewriteCond %{REQUEST_FILENAME} !-f
摘要:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) office/$1 [END]
https://stackoverflow.com/questions/63315877
复制相似问题