突然心血来潮,想注册个4位的.cn域名,但一个个查显然是不可能的事情,于是萌生了写一个查询域名是否已注册的API的想法。
恰巧上周四活动抢了个EdgeOne套餐,正好拿来试试他的边缘函数。
用户访问API,EdgeOne根据规则路由到边缘函数。
边缘函数获取用户需要查询的域名,并请求腾讯云域名注册的API查询域名是否可用。
最后解析并返回查询结果。
● 一个EdgeOne套餐,可以点击这里购买。或者点击这里参加最新的活动,一年仅需45元
● 账号的API凭证,可以点击这里获取
使用GET请求,通过GET参数携带待查询域名
https://api.com/?domain=[待查询域名]
API对接的是腾讯云的域名查询接口,根据文档可知,接口返回如下数据:
因为API的用途是查询域名是否可注册,所以只需要其中部分返回参数即可。
域名不可注册分为两种,一是已经被注册了,二是有敏感词。
当一个域名未被注册但是存在敏感词也会被标记为 不可注册。
所以需要保留敏感词字段,用来给用户做二次的判断。
{
"code": 0,
"DomainName": "域名",
"Available": false,
"BlackWord": false,
"Reason": "不可注册说明"
}
{
"code": 1,
"Message": "报错内容",
"ErrorCode": "报错代码"
}
// 将字符串编码为ArrayBuffer
function stringToArrayBuffer(str) {
const encoder = new TextEncoder();
return encoder.encode(str);
}
// 将ArrayBuffer转换为十六进制字符串
function arrayBufferToHexString(arrayBuffer) {
const byteArray = new Uint8Array(arrayBuffer);
const hexCodes = [...byteArray].map(value => value.toString(16).padStart(2, '0'));
return hexCodes.join('');
}
async function hmacSHA256(key, data) {
const importedKey = await crypto.subtle.importKey(
'raw',
key,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const msgBuffer = stringToArrayBuffer(data);
const signatureBuffer = await crypto.subtle.sign('HMAC', importedKey, msgBuffer);
return signatureBuffer;
}
function uint8ArrayToHex(array) {
return Array.from(array).map(byte => byte.toString(16).padStart(2, '0')).join('');
}
// 签名算法
async function qcloud_v3_post(SecretId,SecretKey,Service,bodyString,headersOper) {
const HTTPRequestMethod = "POST"
const CanonicalURI = "/"
const CanonicalQueryString = ""
// 将 JSON 对象中的键按 ASCII 升序进行排序
let sortedheadersOper = Object.keys(headersOper).filter(key => (key.toLowerCase() !== "x-tc-version")).sort();
// 遍历排序后的键并拼接
let SignedHeaders = sortedheadersOper.map(key => key.toLowerCase()).join(";");
let CanonicalHeaders = sortedheadersOper.map(key => key.toLowerCase() + ":" + headersOper[key].toLowerCase()).join("\n");
CanonicalHeaders = CanonicalHeaders + "\n"
let HashedRequestPayload = await sha256(bodyString)
const CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HashedRequestPayload
const currentDate = new Date();
const year = currentDate.getUTCFullYear();
const month = (currentDate.getUTCMonth() + 1).toString().padStart(2, '0');
const day = currentDate.getUTCDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
const Algorithm = "TC3-HMAC-SHA256"
// 获取当前秒级时间戳
const RequestTimestamp = Math.floor(Date.now() / 1000).toString();
// const RequestTimestamp = "1688025007"
const CredentialScope = formattedDate + "/" + Service + "/tc3_request"
const HashedCanonicalRequest = await sha256(CanonicalRequest)
const StringToSign =
Algorithm + '\n' +
RequestTimestamp + '\n' +
CredentialScope + '\n' +
HashedCanonicalRequest
const SecretDate = await hmacSHA256(new Uint8Array([...stringToArrayBuffer("TC3"), ...new Uint8Array(stringToArrayBuffer(SecretKey))]), formattedDate);
const SecretService = await hmacSHA256(SecretDate, Service);
const SecretSigning = await hmacSHA256(SecretService, "tc3_request");
const Signature = arrayBufferToHexString(await hmacSHA256(SecretSigning, StringToSign));
const Authorization =
Algorithm + ' ' +
'Credential=' + SecretId + '/' + CredentialScope + ', ' +
'SignedHeaders=' + SignedHeaders + ', ' +
'Signature=' + Signature
headersOper["X-TC-Timestamp"] = RequestTimestamp;
headersOper["Authorization"] = Authorization;
return headersOper
}
// sha256 签名摘要
async function sha256(message) {
const msgBuffer = new TextEncoder().encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
return uint8ArrayToHex(new Uint8Array(hashBuffer));
}
// 密钥填写位置
const SecretId = "";
const SecretKey = "";
const Service = "domain";
async function handleRequest(request) {
const url = new URL(request.url)
const params = url.searchParams
const checkdomain = params.get("domain");
let checkRetrunData = {};
if(checkdomain === null){
checkRetrunData["code"] = 1;
checkRetrunData["Message"] = "域名参数为空";
checkRetrunData["ErrorCode"] = "DomainIsNULL";
return new Response(JSON.stringify(checkRetrunData, null, 2), {
headers: { 'Content-Type': 'application/json',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Origin': '*' },
status: 200
})
}
const headersPending = {
'Host': 'domain.tencentcloudapi.com',
'Content-Type': 'application/json',
'X-TC-Action': 'CheckDomain',
'X-TC-Version': '2018-08-08',
'X-TC-Region': 'ap-guangzhou',
};
const apiBodyJson = {
"DomainName": checkdomain
}
const bodyString = JSON.stringify(apiBodyJson)
const headers = await qcloud_v3_post(SecretId,SecretKey,Service,bodyString,headersPending)
const apiurl = 'https://domain.tencentcloudapi.com/';
let qcloud_api_data;
await fetch(apiurl, {
method: 'POST',
headers: headers,
body: bodyString
})
.then(response => response.json())
.then(data => qcloud_api_data = data)
.catch(error => qcloud_api_data = error);
if(qcloud_api_data["Response"]["Error"] === undefined){
checkRetrunData["code"] = 0;
checkRetrunData["DomainName"] = qcloud_api_data["Response"]["DomainName"];
checkRetrunData["Available"] = qcloud_api_data["Response"]["Available"];
checkRetrunData["BlackWord"] = qcloud_api_data["Response"]["BlackWord"];
checkRetrunData["Reason"] = qcloud_api_data["Response"]["Reason"];
}else{
checkRetrunData["code"] = 1;
checkRetrunData["Message"] = qcloud_api_data["Response"]["Error"]["Message"];
checkRetrunData["ErrorCode"] = qcloud_api_data["Response"]["Error"]["Code"];
}
return new Response(JSON.stringify(checkRetrunData, null, 2), {
headers: { 'Content-Type': 'application/json',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Origin': '*' },
status: 200
})
}
addEventListener('fetch', (event) => {
if (event.request.method === 'OPTIONS') {
event.respondWith(handleOptions(event.request))
} else {
event.respondWith(handleRequest(event.request))
}
});
相较于云函数的固定地域,EdgeOne的边缘函数部署在各边缘节点,延迟更低。
更重要的是,边缘函数目前免费使用,用来部署一些小应用十分不错,节省了服务器资源也提升了用户体验。
唯一的缺点是没有调试功能,编写时出错排查起来会困难些,不过作为一款新产品,边缘函数也处于公测当中,日后应该会加上调试功能。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。