使用EdgeOne的边缘函数获取用户IP
原本是想用EdgeOne Pages实现 像CloudFlare Pages那样部署一个
后来发现EdgeOne的边缘函数可以搞定 然后就折腾了一下
首先添加域名
进入edgeone控制台 选择已绑定域名
点击添加域名 输入你需要设置的二级域名 回源配置随便填 模板选择 不使用模板
添加完成后等待部署完成 HTTPS配置选择免费证书
在等待部署期间 左侧菜单滑动到底部 边缘函数 选择函数管理
新建函数 选第一个 创建Hello World 模板即可 点击下一步
输入函数名称 下面函数代码区域 粘贴函数代码 替换原有的
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
function handleRequest(request) {
const url = new URL(request.url);
const path = url.pathname;
// 通过 request.eo.clientIp 获取客户端 IP
const ip = request.eo.clientIp || '';
if(path==='/'){
return new Response(ip, {status: 200,headers: {
"content-type": "text/html;charset=UTF-8",
}})
} else if(path==='/json'){
return new Response(JSON.stringify({ ip }), {
headers: {
'content-type': 'application/json',
},
});
} else if(path==='/info') {
const info = {
ip,
geo: request.eo.geo
}
return new Response(JSON.stringify({ info }), {
headers: {
'content-type': 'application/json',
},
});
} else {
return new Response("404", {status: 404})
}
}
20250905更新
支持cors白名单 设置allowedDomains 就行
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
function handleRequest(request) {
const url = new URL(request.url);
const path = url.pathname;
const ip = request.eo.clientIp || '';
const origin = request.headers.get('Origin');
// ✅ 配置你想要支持的主域名列表(不包含协议和路径)
const allowedDomains = [
'lcsoul.cn',
'localhost',
'127.0.0.1'
];
// 检查 origin 是否匹配任何一个允许的域名(包括子域名)
const corsOrigin = isOriginAllowed(origin, allowedDomains) ? origin : null;
// 处理预检请求 (OPTIONS)
if (request.method === 'OPTIONS') {
if (corsOrigin) {
const headers = {
'Access-Control-Allow-Origin': corsOrigin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400', // 24小时缓存预检
};
return new Response(null, { status: 204, headers });
}
return new Response('Forbidden', { status: 403 });
}
// 构建实际响应
let response;
if (path === '/') {
response = new Response(`${ip}\n`, {
status: 200,
headers: { 'content-type': 'text/html;charset=UTF-8' },
});
} else if (path === '/json') {
response = new Response(JSON.stringify({ ip }), {
headers: { 'content-type': 'application/json' },
});
} else if (path === '/info') {
const info = {
ip,
geo: request.eo.geo,
};
response = new Response(JSON.stringify({ info }), {
headers: { 'content-type': 'application/json' },
});
} else {
response = new Response('404 Not Found', { status: 404 });
}
// 添加 CORS 响应头(仅当来源合法)
if (corsOrigin) {
response.headers.set('Access-Control-Allow-Origin', corsOrigin);
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
}
return response;
}
/**
* 判断 origin 是否属于允许的域名或其子域名
* 支持 http:// 和 https://,忽略协议
*/
function isOriginAllowed(origin, allowedDomains) {
if (!origin || typeof origin !== 'string') return false;
try {
const url = new URL(origin); // 自动补全协议处理
const hostname = url.hostname; // 如:api.example.com
for (const domain of allowedDomains) {
// 匹配主域名本身:example.com
if (hostname === domain) return true;
// 匹配子域名:*.example.com
if (hostname.endsWith('.' + domain)) return true;
}
} catch (e) {
return false;
}
return false;
}
点击 创建并保存部署
在部署成功弹窗中 点击新增触发规则
触发条件中填入上面添加的子域名然后确定保存
这时候就可以访问子域名获取访问用户的IP了
PS:添加域名时选择开启IPv6访问 因网络访问默认IPv6优先 大概率只能获取到v6地址(如果有)
如果需要获取IPv4 可以再添加一个域名 关闭IPv6访问 然后再去边缘函数 触发配置中 在刚添加的规则中添加新增的子域名即可
如果啥也不知道 添加完边缘函数 在列表中点击函数名称 进入详情后点击编辑代码
编辑页面右上角有个AI助手 可以让AI帮你写(有坑自行注意)
参考文档:
阅读剩余
版权声明:
作者:lc_soul
链接:https://blog.lcsoul.cn/archives/556
文章版权归作者所有,未经允许请勿转载。
THE END