我在使用cloudflare pages的时候,发现了一个非常奇怪的问题,就是发布的带有.html后缀的网页,会自动308重定向到一个没有.html的地址,并且,这个行为是cloudflare pages底层硬编码,无法通过配置参数关闭。
这个问题我用中文咨询了所有主流ai,都没有得到好的解决,有给方案说,使用.htm代替.html,因为cloudflare pages不会重写.htm文件,但这对于老网站的seo来说显然不行,还有一个方案说是使用 pages 函数进行拦截,说将一段代码放入functions/[[path]].js 文件中,然后重新发布,然后就会返回 200 + html内容,不会再有308重定向的状态码。我按照其方法发布了,也不行。
接着,我使用google搜索“cloudflare pages html 308 permanent redirect”这样的关键词,看到一大堆cloudflare的用户反馈同样的问题,但每一个问题都没有给出解决方案,翻了好几页也没找到解决方法。
后来,我用google translate将我原先的问题翻译为英文,然后提交给google gemini,这时候gemini给出了一个全新的方案,这是以前没见过的,我按照这个新方案试了一下,竟然成功了,使用 curl -i url,得到的回应从308变成200了,再访问网页,也没有再跳转了,看来还是英文ai更靠谱啊。
这个解决方案,通过使用cloudflare pages 函数(中间件)绕过308重定向限制,在重定向发生之前拦截请求,在内部获取html,并将其连同200 ok状态一起返回给浏览器。
下面就是保留.html扩展名的解决方案:
1、在项目根目录(与输出/构建目录同级,但不要位于其内部)创建一个文件夹functions。
2、在它里面创建一个名为_middleware.js的文件。
3、添加以下代码以拦截.html请求:
javascript代码如下:
export async function onrequest(context) {
const url = new url(context.request.url);
// 1. check if the incoming request is for an .html file
if (url.pathname.endswith('.html')) {
// 2. remove the .html extension for the internal lookup
url.pathname = url.pathname.slice(0, -5);
// 3. clone the original request (to keep headers) but use the new url
const newrequest = new request(url.tostring(), context.request);
// 4. fetch the extension-less asset internally.
// this returns the 200 html response directly to the browser.
return context.env.assets.fetch(newrequest);
}
// for all other requests, proceed to normal cloudflare routing
return context.next();
}
这种方法的原理是,当用户请求.html页面时,此中间件会捕获该请求,这个函数会在后台秘密地向 cloudflare 请求不带扩展名的页面路径,然后,它会获取成功的html 响应,并将其直接发送回原始url,这时候,旧永久链接将立即加载,无需任何重定向跳转。
需要注意的是,这个功能并不是无限使用的,免费的cloudflare pages用户每天的额度是十万次,超过十万次以后当天该函数就停了,需要等到第二天重置额度。

发表评论