突然心血来潮,想注册个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"]?===??developer/article/2353521/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 删除。