.htaccess语言路径重写问题:本地正常线上404
.htaccess语言路径重写线上服务器404问题
问题现象
本地环境中,带语言路径的URL(如http://spa.domain.loc/en/about-us.html)可正常匹配语言规则并跳转至对应控制器;但在线上服务器访问https://spa.domain.ro/en/rezervare-spa.html时出现404错误,语言匹配规则未触发。
需求
通过/en/这类路径传递lang参数到PHP(实际对应请求为https://spa.domain.ro/rezervare-spa.html?lang=en),且用户看不到该参数。
当前.htaccess配置
RewriteEngine On # REWRITE IF HAVE LANGUAGE /en/ path RewriteBase / # Force trailing slash on language code RewriteRule ^(en)$ $1/ [R=301,L] # Default to Romanian (other languages example path. /en/<anything>) RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} ^/(.*) #RewriteRule !^(en/|/)(.*) %1 [R,L] # Route language URLs RewriteRule ^([a-zA-Z]{2})/(.*) $2?lang=$1 [QSA,L] # END LANGUAGE # Security Fixes RewriteRule ^\.htaccess$ - [F,L] RewriteRule ^_scripts/ - [F,L] RewriteRule ^_sql/ - [F,L] RewriteRule ^_logos/ - [F,L] RewriteRule ^etc/live\.2CQA\-VZRG\-6AVL\-PB0Q\-1KJP\.public\.cer$ - [F,L] RewriteRule ^etc/live\.2CQA\-VZRG\-6AVL\-PB0Q\-1KJPprivate\.key$ - [F,L] RewriteRule ^etc/config\.php$ - [F,L] RewriteRule ^etc/config-index\.php$ - [F,L] RewriteRule ^etc/config-admin\.php$ - [F,L] RewriteRule ^etc/init\.php$ - [F,L] RewriteRule ^etc_online/config\.php$ - [F,L] RewriteRule ^etc_online/config-index\.php$ - [F,L] RewriteRule ^etc_online/config-admin\.php$ - [F,L] RewriteRule ^etc_online/init\.php$ - [F,L] RewriteRule ^tmp/ - [F,L] RewriteRule ^wpub/\.htaccess$ - [F,L] RewriteRule ^wpub/\#wpub$ - [F,L] RewriteRule ^\#db/ - [F,L] ##### Temporary maintenance ; must be 302 as 307 does not behave correctly (if the file maintenance.html exists in the web root) RewriteCond %{HTTP_HOST} ^(.*)\. RewriteCond /maintenance.html !-f RewriteRule ^maintenance.html$ / [L,R=301] RewriteCond %{HTTPS} off RewriteCond %{HTTP_HOST} ^(?:(spa)\.)?(domain\.ro)$ RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # Redirect to www if no sub-domain (Ex: http(s)://domain.ext -> http(s)://www.domain.ext) RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$ RewriteCond %{HTTPS}s ^on(s)| RewriteRule ^ http%1://spa.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # Homepage Rules #RewriteCond %{HTTP_HOST} ^(www)\. RewriteRule ^$ index.php?page=frontend.homepage [QSA,L] # Custom Rules: old-rules RedirectMatch 301 ^/about\.html$ /about-us.html RedirectMatch 301 ^/rates\.php$ /rates.html RedirectMatch 301 ^/news\.php$ /news.html RedirectMatch 301 ^/location\.php$ /location.html RedirectMatch 301 ^/gallery\.php$ /gallery.html RedirectMatch 301 ^/privacy-policy\.php$ /privacy-policy.html RedirectMatch 301 ^/contact\.php$ /contact.html # RULES MOBILPAY PAYMENT # Custom Rules: return-mobilpay RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^return-mobilpay\.html$ index.php?page=frontend.mobilpay-return [QSA,L] # Custom Rules: confirm-mobilpay RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^confirm-mobilpay\.html$ index.php?page=frontend.mobilpay-confirm [QSA,L] # RULES VIVA WALLET PAYMENT # Custom Rules: return-vivawallet RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^return-vivawallet\.html$ index.php?page=frontend.vivawallet-return [QSA,L] # Custom Rules: confirm-vivawallet RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^confirm-vivawallet\.html$ index.php?page=frontend.vivawallet-confirm [QSA,L] # Custom Rules: #RewriteCond %{REQUEST_FILENAME} !-f #RewriteCond %{REQUEST_FILENAME} !-d #RewriteRule ^rezervare-bungalow\.html$ index.php?page=frontend.rezervare-camera&roomid=3 [QSA,L] # Custom Rules: RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^offers\.html$ index.php?page=frontend.offers-view [QSA,L] ### Sitemap XML Index RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^sitemap\.xml$ /index.php?page=frontend.sitemap-sdom-idx [QSA,L] ### Sitemap XML Content RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^sitemap-content\.xml$ /index.php?page=frontend.sitemap-sdom-content [QSA,L] ### # Custom Rules: backend RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^backend.(.*)\.html$ admin.php?page=backend-new.$1 [QSA,L] # General rewrite rules: map controller name to something else RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)\.(html|stml|json|xml|rss|csv|txt|png|gif|jpg|pdf|webp)$ index.php?page=$1 [QSA,L] ErrorDocument 400 /index.php?page=frontend.400 ErrorDocument 404 /index.php?page=frontend.404
问题分析与修复方案
线上服务器出现404的核心原因是语言规则位置靠后,被后续带[L]标记的HTTPS/域名跳转规则截断。本地环境无强制跳转,规则能正常执行;但线上请求先被跳转规则终止处理,语言规则根本没机会触发。
修复步骤
- 调整规则顺序:将语言重写规则移到所有跳转规则(HTTPS、域名跳转、维护页跳转)之前,确保语言路径先被解析。
- 优化语言规则条件:添加文件/目录存在判断,避免真实存在的资源被误改写。
- 保留跳转时的语言路径:现有跳转规则已通过
%{REQUEST_URI}保留完整路径,无需额外修改。
修正后的核心规则片段
RewriteEngine On RewriteBase / # REWRITE IF HAVE LANGUAGE /en/ path # Force trailing slash on language code RewriteRule ^(en)$ $1/ [R=301,L] # Route language URLs - 先处理语言路径,添加文件/目录判断 RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^([a-zA-Z]{2})/(.*) $2?lang=$1 [QSA,L] # END LANGUAGE # 之后放置所有跳转、安全、路由规则 ##### Temporary maintenance ; must be 302 as 307 does not behave correctly (if the file maintenance.html exists in the web root) RewriteCond %{HTTP_HOST} ^(.*)\. RewriteCond /maintenance.html !-f RewriteRule ^maintenance.html$ / [L,R=301] # HTTPS强制跳转 RewriteCond %{HTTPS} off RewriteCond %{HTTP_HOST} ^(?:(spa)\.)?(domain\.ro)$ RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # 子域名跳转 RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$ RewriteCond %{HTTPS}s ^on(s)| RewriteRule ^ http%1://spa.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # 其余规则保持不变...
额外检查项
- 确认线上服务器
mod_rewrite模块已启用。 - 检查服务器
AllowOverride配置是否为All,确保.htaccess规则生效。 - 清除浏览器缓存,避免旧301跳转缓存干扰测试。
内容的提问来源于stack exchange,提问作者BoBiTza
相关产品推荐
相关产品推荐

