首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Apache .htaccess文件中将子域重写到子目录

在Apache .htaccess文件中将子域重写到子目录
EN

Stack Overflow用户
提问于 2020-08-08 13:23:00
回答 1查看 838关注 0票数 0

假设我有一个名为example.com的域,并且我希望使用Apache的.htaccess文件中的重写规则来重写:

https://office.example.com/index.html

https://example.com/office/index.html

我该怎么做?我在这里查了很多答案,解决方案似乎是这样的:

代码语言:javascript
运行
复制
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。我启用了日志记录,发现这似乎是一个递归问题:

代码语言:javascript
运行
复制
AH00124: Request exceeded the limit of 10 internal redirects. 

在日志中,它似乎不断地将office添加到office/office/office/office/...。我不知道为什么会这样。重写的URL不符合重写条件,那么为什么要这样做呢?

我找到了一种让它“起作用”的方法。如果我将R=301添加到RewriteRule属性中,则会进行重定向,并且工作正常,但我更希望原来的URL保留在地址栏中。

下面是前两个重定向的日志:

代码语言:javascript
运行
复制
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]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-08 14:50:18

RewriteCond %{HTTP_HOST} ^office.example.com$ RewriteRule ^(.*)$ https://example.com/office/$1 L,NC,QSA

令人费解的是,这应该隐式地触发外部302 (临时)重定向,而不是内部重写--当在替换字符串中指定另一个主机到被请求的主机时。(尽管在我的经验中,替换字符串中的任何绝对URL都会触发外部重定向。)

如果它确实触发了内部重写(如日志所示),那么请求的主机名不会更改(因为这不是一个单独的请求),您确实会得到一个重写循环。

但是,如果“子域是主域的别名”而重写是必需的,那么就不需要在替换字符串中指定主机名,您确实需要进行额外的检查,以防止内部重写循环(500错误)。

相反,请尝试以下几点:

代码语言:javascript
运行
复制
RewriteEngine on

RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteRule !^office office%{REQUEST_URI} [L]

...to排除任何已经启动/office的请求(包括重写请求)。

不需要NCQSA标志。

或者,如果只针对直接请求(而不是重写请求),则可以选择REDIRECT_STATUS环境变量(初始请求为空,在第一次成功重写后设置为" 200 ",如200 OK中所示)。

例如:

代码语言:javascript
运行
复制
RewriteCond %{HTTP_HOST} ^office\.example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) office/$1 [L]

这有一个额外的“好处”,您也可以有一个名为/office的子目录。即。/office/office

更新:第三个版本是检查REQUEST_URI服务器变量。但是,我不认为这与上面的第一个版本有什么不同。

代码语言:javascript
运行
复制
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指令)以排除特定的文件扩展名。例如:

代码语言:javascript
运行
复制
RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif)$

和/或添加一个额外的RewriteCond指令,以排除已经映射到物理文件的请求(尽管这“稍微”昂贵)。例如:

代码语言:javascript
运行
复制
RewriteCond %{REQUEST_FILENAME} !-f

摘要:

代码语言:javascript
运行
复制
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]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63315877

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档