Cloudflare Pages Worker调用Supabase API时DFW节点报1016错误求助
Cloudflare Pages边缘运行时调用Supabase出现1016 DNS错误(仅DFW节点)
环境配置
// src/lib/supabase.ts import { createClient } from "@supabase/supabase-js"; export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, // https://[ref].supabase.co process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { global: { headers: { 'x-application-name': 'my-app' } } } );
// src/app/blog/[slug]/page.tsx export const runtime = "edge"; const getPost = cache(async (slug: string) => { const { data, error } = await supabase .from('BlogPost') .select('*') .eq('slug', slug) .single(); if (error) { console.error('Fetch error:', error.message); // logs "error code: 1016" throw error; } return data; });
错误日志
{ "colo": "DFW", "logs": [{ "message": ["Fetch error:", "error code: 1016"], "level": "error" }] }
现象
- BOM(孟买)边缘节点:✅ Supabase查询成功
- DFW(达拉斯)边缘节点:❌ 所有查询、所有表均返回error code: 1016
已排除的可能原因
- Supabase网络限制:已禁用,允许所有IP
- Supabase网络封禁:无
- API密钥:正确,在孟买节点可正常使用
- RLS策略:非问题所在(包括公共表在内的所有表均失败)
- Cloudflare智能部署:已启用,Worker仍在DFW执行
推测
my-site.com和supabase.co均为Cloudflare代理域名。当DFW节点的Worker调用fetch("https://[ref].supabase.co/rest/v1/...")时,Cloudflare将其作为Orange-to-Orange(O2O)请求路由。DFW边缘解析器在该O2O场景下无法解析Supabase源主机名,在建立TCP连接前返回1016错误。孟买节点正常可能因为其地理位置接近Supabase项目区域ap-south-1,使用了不同的内部路由路径。
问题
是否可以强制Cloudflare Pages Worker的fetch()调用绕过O2O路由,使用标准公共DNS解析?我了解Worker的fetch()有cf选项:
fetch(url, { // @ts-ignore cf: { /* ??? */ } })
是否存在特定的cf选项可强制使用外部DNS解析而非Cloudflare内部O2O路径?或者有其他方法让Worker的出站请求独立于Cloudflare内部路由解析主机名?
解决方案
1. 强制使用公共DNS解析
通过自定义Supabase客户端的fetch方法,在cf参数中设置dns: "public",让边缘节点跳过内部O2O路由的DNS解析逻辑,直接使用公共DNS:
// src/lib/supabase.ts import { createClient } from "@supabase/supabase-js"; // 自定义fetch,注入公共DNS解析配置 const customFetch = (url: RequestInfo, init?: RequestInit) => { return fetch(url, { ...init, cf: { ...init?.cf, dns: "public" // 强制使用公共DNS解析 } }); }; export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { global: { headers: { 'x-application-name': 'my-app' }, fetch: customFetch // 替换为自定义fetch } } );
2. 直接指定Supabase实例IP(备选方案)
如果公共DNS解析仍有问题,可以通过resolveOverride直接指定Supabase实例的IP地址(可通过nslookup [ref].supabase.co获取对应IP):
// src/lib/supabase.ts import { createClient } from "@supabase/supabase-js"; const supabaseHost = new URL(process.env.NEXT_PUBLIC_SUPABASE_URL!).hostname; // 替换为你的Supabase实例实际IP const SUPABASE_IP = "1.2.3.4"; const customFetch = (url: RequestInfo, init?: RequestInit) => { const targetUrl = typeof url === 'string' ? new URL(url) : new URL(url.url); const cfOptions = targetUrl.hostname === supabaseHost ? { resolveOverride: SUPABASE_IP } : {}; return fetch(url, { ...init, cf: { ...init?.cf, ...cfOptions } }); }; export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { global: { headers: { 'x-application-name': 'my-app' }, fetch: customFetch } } );
原理说明
dns: "public":强制Cloudflare边缘节点使用公共DNS服务器解析目标域名,绕开内部O2O路由的解析逻辑,避免DFW节点的内部解析故障。resolveOverride:直接指定目标域名的IP,完全跳过DNS解析步骤,从根源上解决1016 DNS错误问题。
内容的提问来源于stack exchange,提问作者Gods Neo
相关产品推荐
相关产品推荐

