1.关于 EdgeOne
最近腾讯云搞了个 EdgeOne ,搞得沸沸扬扬的,而边缘函数作为现代CDN普遍功能,在提升简单小功能的响应速度上具有非常大的帮助. 我没兑换码别找我.
2.定价
EdgeOne 免费试用版提供了 300w request/month,300w COREms/month 的免费配额,基本上和 Cloudflare 差不多.
EdgeOne | Clodflare |
---|---|
![]() |
![]() |
300w R/month 300w COREms/month | 10w R/day |
超出不知道怎么计费,还没超过,不过现在没绑卡,超出也不可能扣钱就是了 | 超出发账单 |
3.功能
这里我们主要讲 EdgeOne 的边缘函数功能, 其他的功能估计经常使用的人已经了如指掌了.
3.1.创建一个边缘函数
- 点击
新建函数
跳转到以下界面: - 点击下一步跳转到以下步骤:
函数名称
和注释
只要合法,随便写,函数代码可以先按照他的不改,我们后期再做修改. 如果添加成功,那么会显示如下界面:我们点击新增触发规则/或直接点击暂不需要.
3.2.创建触发规则
如果在上一步选择新增触发规则,那么就会来到以下界面:
- 匹配类型: 选择让指定的请求通过我们创建的函数
例如我们设置为HOST
等于
123.com
, 那么所有通过腾讯云EdgeOne的请求只要符合请求头/sni中HOST
为123.com
的请求都会通过我们设定的边缘函数
3.3.设置环境变量
回到函数管理->点击函数名进入函数管理->向下拉可以看到环境变量块.
可以添加以文本或者JSON添加环境变量.作为示例,我这里添加一个
default_output_key
值为 clientIp
的变量用于演示.
在添加完毕后,不要忘了点击右上角的 部署
进行变量的部署
3.4.编写边缘JS代码
如果没有问题,那么你在他部署完毕后应该可以使用他提供的 默认访问域名
访问到你的 Hello World
边缘函数了.EdgeOne 提供了一些示例代码可以参考,同时也提供了RuntimeAPI用于参考. 在这里我也创建一个自己的边缘函数示例代码,用于获取请求者IP信息,不过在介绍我的方法之前,先介绍以下主要的几个方法和类型:
3.4.1.addEventListener :fetch
注册事件监听器,是边缘函数的运行入口。addEventListener
仅支持注册一个事件监听器。当前仅支持 fetch
请求事件,通过注册 fetch
事件监听器,生成 HTTP
请求事件 FetchEvent
,进而实现对 HTTP
请求的处理。通俗来说就是你请求的入口,通过监听这个事件来做到回调,这部分和 cloudflare
的边缘函数有些许不同,但大体上是差不多的.
3.4.2.Request
根据 官方文档 对 Request
的描述, Request
代表 HTTP
请求对象,基于 Web APIs 标准 Request 进行设计. 我们要知道其中有 eo
这个属性(IncomingRequestEoProperties)对我我们编写一个IP查询函数十分重要.
3.4.3.Response
根据 官方文档 , 我们可以知道 Response
代表 HTTP 响应,基于 Web APIs 标准 Response 进行设计。这个知不知道无所谓,反正就是用来做返回 body
header
等功能.
3.4.3.编写主方法
当我们知道了如何调用和request
的使用方法后,我们就能写出如下代码:
函数执行流程:
- 从环境变量中读取预先设置的
default_output_key
的值; - 将所有能使用的ip信息存到
full_info
对象中; - 获取URL信息,包括URL参数用于设定返回的body类型,是否返回美化后的Json,是否返回全部可用值,和指定返回的值;
- 将需要返回的值放入
resp
对象中; - 根据
ret_type
决定返回类型,可选返回Json或者直接返回文本; - 将数据编为JSON格式或者以
key=value\n
格式返回;
async function handleRequest(request) {
let resp = {};
let full_info = {};
let response_body = "";
let select_all = false;
let stringify_settings = {
visual_view : false
}
let headers = {
"Access-Control-Allow-Origin": "*"
};
const keys_available = [
"clientIp", "asn", "countryName", "countryCodeAlpha2",
"countryCodeAlpha3", "countryCodeNumeric", "regionName",
"regionCode", "cityName", "latitude", "longitude"
];
const env_default_key = env.default_output_key;
const key_alias = {
ip: "clientIp",
country: "countryName",
lat: "latitude",
lng: "longitude",
city: "cityName",
region: "regionName"
};
let selectedFields = [env_default_key] || [
"clientIp",
];
let ret_type = "text";
// 拷贝 ip 信息
full_info = {
...(request.eo?.clientIp && { clientIp: request.eo.clientIp }),
...(request.eo?.geo || {})
};;
// 获取URL信息
const urlInfo = new URL(request.url);
const params = urlInfo.searchParams;
if (params.keys().length > keys_available.length + 4) {
return new Response("Too many params.\n", {status:403});
}
// 获取url参数
for (let [key,value] of params.entries()) {
switch (key) {
case "type":
ret_type = value;
break;
case "v":
stringify_settings.visual_view = true;
break;
case "j":
ret_type = "json";
break;
case "all":
select_all = true;
break;
default:
let rKey = key_alias[key] || key;
if ((keys_available.includes(rKey)) && !selectedFields.includes(rKey)) {
selectedFields.push(rKey);
}
break;
}
}
// 注入resp
if (select_all) {
keys_available.forEach(key => {
if (full_info[key] !== undefined) {
resp[key] = full_info[key];
}
});
} else {
selectedFields.forEach(key => {
if (full_info[key] !== undefined) {
resp[key] = full_info[key];
}
});
}
switch (ret_type) {
case "json":
response_body = stringify_settings.visual_view
?JSON.stringify(resp,null,2) + "\n"
:JSON.stringify(resp) + "\n";
headers["content-type"] = "application/json; charset=UTF-8";
break;
default:
if (Object.keys(resp).length == 1) {
response_body = resp[Object.keys(resp)[0]] + "\n";
} else {
response_body = Object.entries(resp)
.map(([k, v]) => `${k}=${v}`)
.join("\n") + "\n";
}
headers["content-type"] = "text/plain; charset=UTF-8";
}
return new Response(response_body,{ headers });
}
addEventListener('fetch', event => {
event.passThroughOnException();
event.respondWith(handleRequest(event.request));
});
4.Tips
- 3.4.3的主方法已经可用直接被用于边缘函数.即你可以直接将这个代码块全部写入保存并部署;如果出现访问之后返回空,请检查环境变量是否已成功设置
default_output_key
变量 - 该方法只是一个简单的示例, 理论上你可以用JS完成任何网页的构建,甚至可以只用边缘函数编写一个完整的Blog
5.Demo
访问地址: http://myip.icu
可选参数:
j
: 以JSON格式获取输出v
: 以利于阅读的格式输出all
: 获取所有信息type
: 指定输出格式,可选:json
,text
clientIp
orip
: 获取IPasn
: 获取ASN号countryName
orcountry
: 获取国家名countryCodeAlpha2
: 获取国家的 ISO-3611 alpha2 代码countryCodeAlpha3
: 获取国家的 ISO-3611 alpha3 代码countryCodeNumeric
: 获取国家的 ISO-3611 numeric 代码regionName
orregion
: 获取区域名regionCode
: 获取区域代码cityName
orcity
: 获取城市名latitude
orlat
: 获取纬度longitude
orlng
: 获取经度
示例:
- 直接获取自己的IP地址: http://myip.icu
- 以Json可视化格式获取自己的IP地址所有信息: http://myip.icu/?j&all&v
- 以Json可视化格式获取自己的IP地址Country和IP: http://myip.icu/?j&v&country
- 用终端 curl 获取自己的ip地址:
6.后记
花了一个下午折腾了EdgeOne和IP优选,最后总结出来把EdgeOne设置成Cname + ns服务器放在华为云搞优选是真的很爽,如下: