将子域和 URL-路径重写为 URL 参数但允许访问文件
Rewrite subdomain and URL-path to URL parameters but allow access to files
我正在努力处理我的 .htaccess
文件并按照我想要的方式设置它。主要功能是一个网站,从子域获取语言,从子文件夹获取当前页面。
要求
我需要 .htaccess
文件完成三个要求;
- 通配符子域重定向到 lang 变量
- 子文件夹重定向到 页面 变量
- 尊重本地文件(这是我卡住的地方)
- (奖励) 将页面变量拆分为每个斜杠的段;页、sub1、sub2 等
例子
en.example.com/hello
-> /index.php?lang=en&page=hello
es.example.com/hola
-> /index.php?lang=es&page=hola
- (奖金)
en.example.com/hello/there/sir
-> index.php?lang=en&page=hello&sub1=there&sub2=sir
我当前的 .htaccess
这是我当前的设置,如果我不需要任何本地文件,实际上 有点 可以工作(笑)。这意味着当我的 .htaccess below
处于活动状态时找不到本地图像。我尝试添加 RewriteCond %{REQUEST_FILENAME} !-f
以尊重本地文件,但这似乎破坏了整个文件 - 我不知道为什么。
RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{HTTP_HOST} ((?!www).+)\.example\.com [NC]
RewriteRule ^$ /index.php?lang=%1 [L]
RewriteCond %{HTTP_HOST} ((?!www).+)\.example\.com [NC]
RewriteRule ^(.+)$ /index.php?lang=%1&page= [L]
RewriteRule ^index\.php$ - [L]
RewriteRule ^(.*)$ /index.php?page= [L,QSA]
如果您的 URL 不包含点,则从您的正则表达式中排除点 - 这自然会排除真实文件(在文件扩展名之前包含一个点)。这避免了文件系统检查的需要。
您的脚本应该完全相同地处理 /index.php?lang=%1
和 /index.php?lang=%1&page=
,因此第一条规则是多余的。
RewriteRule ^index\.php$ - [L]
这条规则应该放在最前面,不要嵌入中间。
请尝试以下方法:
RewriteRule ^index\.php$ - [L]
RewriteCond %{HTTP_HOST} ^((?!www).+)\.example\.com [NC]
RewriteRule ^([^.]*)$ /index.php?lang=%1&page= [QSA,L]
RewriteRule ^([^.]*)$ /index.php?page= [QSA,L]
你的最后一条规则将其他所有内容重写为 index.php
,减去 lang
URL 参数是有问题的。为什么不将其包含在前面的规则中并验证脚本中的语言?无论如何你都需要这样做。
假设总有一个子域,那么您的规则可以简化为:
RewriteRule ^index\.php$ - [L]
RewriteCond %{HTTP_HOST} ^(.+)\.example\.com [NC]
RewriteRule ^([^.]*)$ /index.php?lang=%1&page= [QSA,L]
www
语言 的请求然后由您的脚本验证并相应地默认,就好像根本没有传递 lang
参数一样(这无论如何你都需要做)。
如果您的子域完全是可选的,并且您正在访问域顶点,那么在正则表达式中将其设为可选(使用 non-capturing 组):
RewriteCond %{HTTP_HOST} ^(?:(.+)\.)?example\.com [NC]
:
如果请求域顶点,lang
参数将是 空。
(Bonus) en.domain.com/hello/there/sir
-> index.php?lang=en&page=hello&sub1=there&sub2=sir
最好(更有效、更灵活等)在您的 PHP 脚本中执行此操作,而不是 .htaccess
。
但是在 .htaccess
中你可以这样做(而不是现有的规则):
:
RewriteRule ^([^/.]*)(?:/([^/.]+))?(?:/([^/.]+))?(?:/([^/.]+))?(?:/([^/.]+))?$ /index.php?lang=%1&page=&sub1=&sub2=&sub3=&sub4= [QSA,L]
当该路径段不存在时,URL 参数为空。
假定 URL-path 不以斜杠结尾(如果以斜杠结尾,则上述内容将不匹配,因此将产生 404)。如果需要允许尾部斜杠,则应将其实现为规范重定向以删除尾部斜杠。或者反转逻辑以强制执行尾部斜杠。
此特定示例最多允许 4 个额外的“子”路径段,例如。 hello/1/2/3/4
。如果需要,您可以扩展此方法以允许最多 8 个(因为 Apache 语法中有 9 个反向引用的限制)。如果再多,您将需要使用 PHP。 (您可以使用 .htaccess
处理更多,但它会变得非常混乱,因为您需要使用额外的 条件 来捕获后续路径段。)
I tried adding RewriteCond %{REQUEST_FILENAME} !-f
to respect local files but that breaks the whole file it seems
这也应该足够了(如果您的 URL 中允许使用点)。但我想知道你把它放在哪里了?它不应该“破坏”任何东西——如果请求确实映射到一个文件,它只是阻止规则被处理——规则被“忽略”。
这当然是假设您使用 root-relative(以斜杠开头)或绝对(以方案 + 主机名开头)URL 正确链接到您的 resources/static 资产。如果您使用相对 URLs 那么它们可能会导致 404s。如果是这种情况,请参阅 my answer 网站管理员堆栈中的以下问题:
我正在努力处理我的 .htaccess
文件并按照我想要的方式设置它。主要功能是一个网站,从子域获取语言,从子文件夹获取当前页面。
要求
我需要 .htaccess
文件完成三个要求;
- 通配符子域重定向到 lang 变量
- 子文件夹重定向到 页面 变量
- 尊重本地文件(这是我卡住的地方)
- (奖励) 将页面变量拆分为每个斜杠的段;页、sub1、sub2 等
例子
en.example.com/hello
->/index.php?lang=en&page=hello
es.example.com/hola
->/index.php?lang=es&page=hola
- (奖金)
en.example.com/hello/there/sir
->index.php?lang=en&page=hello&sub1=there&sub2=sir
我当前的 .htaccess
这是我当前的设置,如果我不需要任何本地文件,实际上 有点 可以工作(笑)。这意味着当我的 .htaccess below
处于活动状态时找不到本地图像。我尝试添加 RewriteCond %{REQUEST_FILENAME} !-f
以尊重本地文件,但这似乎破坏了整个文件 - 我不知道为什么。
RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{HTTP_HOST} ((?!www).+)\.example\.com [NC]
RewriteRule ^$ /index.php?lang=%1 [L]
RewriteCond %{HTTP_HOST} ((?!www).+)\.example\.com [NC]
RewriteRule ^(.+)$ /index.php?lang=%1&page= [L]
RewriteRule ^index\.php$ - [L]
RewriteRule ^(.*)$ /index.php?page= [L,QSA]
如果您的 URL 不包含点,则从您的正则表达式中排除点 - 这自然会排除真实文件(在文件扩展名之前包含一个点)。这避免了文件系统检查的需要。
您的脚本应该完全相同地处理 /index.php?lang=%1
和 /index.php?lang=%1&page=
,因此第一条规则是多余的。
RewriteRule ^index\.php$ - [L]
这条规则应该放在最前面,不要嵌入中间。
请尝试以下方法:
RewriteRule ^index\.php$ - [L]
RewriteCond %{HTTP_HOST} ^((?!www).+)\.example\.com [NC]
RewriteRule ^([^.]*)$ /index.php?lang=%1&page= [QSA,L]
RewriteRule ^([^.]*)$ /index.php?page= [QSA,L]
你的最后一条规则将其他所有内容重写为 index.php
,减去 lang
URL 参数是有问题的。为什么不将其包含在前面的规则中并验证脚本中的语言?无论如何你都需要这样做。
假设总有一个子域,那么您的规则可以简化为:
RewriteRule ^index\.php$ - [L]
RewriteCond %{HTTP_HOST} ^(.+)\.example\.com [NC]
RewriteRule ^([^.]*)$ /index.php?lang=%1&page= [QSA,L]
www
语言 的请求然后由您的脚本验证并相应地默认,就好像根本没有传递 lang
参数一样(这无论如何你都需要做)。
如果您的子域完全是可选的,并且您正在访问域顶点,那么在正则表达式中将其设为可选(使用 non-capturing 组):
RewriteCond %{HTTP_HOST} ^(?:(.+)\.)?example\.com [NC]
:
如果请求域顶点,lang
参数将是 空。
(Bonus)
en.domain.com/hello/there/sir
->index.php?lang=en&page=hello&sub1=there&sub2=sir
最好(更有效、更灵活等)在您的 PHP 脚本中执行此操作,而不是 .htaccess
。
但是在 .htaccess
中你可以这样做(而不是现有的规则):
:
RewriteRule ^([^/.]*)(?:/([^/.]+))?(?:/([^/.]+))?(?:/([^/.]+))?(?:/([^/.]+))?$ /index.php?lang=%1&page=&sub1=&sub2=&sub3=&sub4= [QSA,L]
当该路径段不存在时,URL 参数为空。
假定 URL-path 不以斜杠结尾(如果以斜杠结尾,则上述内容将不匹配,因此将产生 404)。如果需要允许尾部斜杠,则应将其实现为规范重定向以删除尾部斜杠。或者反转逻辑以强制执行尾部斜杠。
此特定示例最多允许 4 个额外的“子”路径段,例如。 hello/1/2/3/4
。如果需要,您可以扩展此方法以允许最多 8 个(因为 Apache 语法中有 9 个反向引用的限制)。如果再多,您将需要使用 PHP。 (您可以使用 .htaccess
处理更多,但它会变得非常混乱,因为您需要使用额外的 条件 来捕获后续路径段。)
I tried adding
RewriteCond %{REQUEST_FILENAME} !-f
to respect local files but that breaks the whole file it seems
这也应该足够了(如果您的 URL 中允许使用点)。但我想知道你把它放在哪里了?它不应该“破坏”任何东西——如果请求确实映射到一个文件,它只是阻止规则被处理——规则被“忽略”。
这当然是假设您使用 root-relative(以斜杠开头)或绝对(以方案 + 主机名开头)URL 正确链接到您的 resources/static 资产。如果您使用相对 URLs 那么它们可能会导致 404s。如果是这种情况,请参阅 my answer 网站管理员堆栈中的以下问题: