.htaccess - 将子域重写到现有文件夹
问题描述
我有一个这样的文件夹结构:
public_html
...images
...v2020
...v2021
使用 mod_rewrite,我重定向到文件夹 v2021 并强制到https://www.example.com。现在我很难添加子域。当我转到 images.example.com 时,我希望重定向到文件夹 images,而 images.example.com 在地址字段中保持不变。我分别对代码进行了两部分测试,首先是对 https://www 的转发,包括子域。它可以在没有子域的情况下工作,但如果我添加任何子域,它就会无处可去。
RewriteEngine on
# "example.com" to "www.example.com" (and HTTPS)
RewriteCond %{HTTP_HOST} ^(example\.com) [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,R=301,L]
# HTTP to HTTPS (same host) - preserve subdomain
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
作为最小工作示例的第二部分是标准域(无子域)的前言和子域转发到调试脚本。
RewriteCond %{HTTP_HOST} ^www\.example\.com
RewriteRule ^((?!v2021/).*)$ v2021/$1 [L]
RewriteCond %{HTTP_HOST} ^(.+?)\.example\.com
RewriteRule (.*) echo.php\?a=%1\&b=$1 [L]
该脚本工作正常,并在与上限条件一起使用时输出 a="www",但不与下限一起执行。我被转发到无处。谢谢你的帮助!
解决方案
这里似乎有几个问题......
RewriteCond %{HTTP_HOST} !^www\. [OR,NC] RewriteCond %{HTTPS} off RewriteRule ^ https://www.example.com%{REQUEST_URI} [NE,R=301,L]
您的第一条规则将您的所有子域(每个未启动的主机名www.
)重定向到www.example.com
,因此子域丢失。您可能需要更改第一个条件,以便它仅将example.com
(域顶点)的请求重定向到www.example.com
. 但是您还需要将 HTTP 拆分为 HTTPS 重定向以保留子域(images
等)
例如:
# "example.com" to "www.example.com" (and HTTPS)
RewriteCond %{HTTP_HOST} ^(example\.com) [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,R=301,L]
# HTTP to HTTPS (same host) - preserve subdomain
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com RewriteRule ^(.*)$ %1/$1 [L,NC,QSA]
这将导致内部重写循环(500 错误),因为它反复重写subdomain/url-path
导致subdomain/subdomain/subdomain/url-path
等等。
您需要一个条件来仅重写直接/初始请求(而不是重写请求),或者检查子域是否尚未被重写到同名的子目录。
但是,这也会重写www
子域,我认为这不是意图,因此需要另一个条件来排除它。
例如,仅重写初始请求并排除 www 子域:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule (.*) %1/$1 [L]
通过始终重写初始请求并且不明确检查子目录是否与子域不匹配,这意味着您可以拥有与子域同名的子子目录(如果需要)。例如。/images/images/foo.jpg
不是问题。
NC
和上的QSA
标志RewriteRule
不是必需的。(因为它已经不区分大小写,并且您没有要附加的查询字符串。)
REDIRECT_STATUS
环境变量在初始请求时为空,并在第一次成功重写后设置为(200
如 200 OK 状态),因此通过检查它是否为空,可以避免重写循环。
如果您配置了通配符子域,那么您可能需要在重写之前检查该子目录是否存在。(虽然文件系统检查相对昂贵,所以如果可能的话最好避免这样做。特别是在服务资产时。)
RewriteRule ^((?!v2021/).*)$ /v2021/$1 [L]
这似乎与上述规则相冲突。这不应该只适用于www
子域(与上述重写相反)吗?例如:
RewriteCond %{HTTP_HOST} ^www\.
RewriteRule ^((?!v2021/).*)$ v2021/$1 [L]
推荐阅读
- google-app-engine - AppEngine 日志不接受上下文
- https - Gitbook API 返回 HTTP 代码 429
- python - Python Pandas:高效地为切片赋值
- python-3.x - 从 BaseOperator 到 PythonOperator 的气流或将参数传递给 BaseOperator
- java - 当我开始 ant build 并继续编码时会发生什么,我的更改(运行 ant build 之后)是否被忽略?
- android - 在第二个实时数据之后观察实时数据
- amazon-web-services - 与 CF 分发链接的 Route53 CNAME 记录返回 REFUSED
- python - Tensorflow numpy 图像重塑 [灰度图像]
- android - Gradle 错误:任务 ':app:compileDebugJavaWithJavac' 执行失败
- hook-woocommerce - 如果我想在 Woocommerce 批量编辑页面上更改我的自定义价格,我可以使用哪种挂钩?