将子域和 URL-路径重写为 URL 参数但允许访问文件

Rewrite subdomain and URL-path to URL parameters but allow access to files

我正在努力处理我的 .htaccess 文件并按照我想要的方式设置它。主要功能是一个网站,从子域获取语言,从子文件夹获取当前页面。

要求

我需要 .htaccess 文件完成三个要求;

  1. 通配符子域重定向到 lang 变量
  2. 子文件夹重定向到 页面 变量
  3. 尊重本地文件(这是我卡住的地方)
  4. (奖励) 将页面变量拆分为每个斜杠的段;页、sub1、sub2 等

例子

我当前的 .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 网站管理员堆栈中的以下问题: