2021.01.15更新 整个项目已经搞好了,放在了GitHub上steam_info_page,搞完之后忘了在这里改一下了……
cloudflare Workers 是近期新出的一种serveless的简单的边缘计算服务,就是把简单的JavaScript代码直接安排到cloudflare的cdn服务器上去运行,这样处理的效果会更快。
目前cloudflare对个人免费账户的使用限额每天最多调用十万次,一次的cpu时间不得超过10ms。
官网对cloudflare workers的介绍是:
在覆盖 95 个国家/地区超过 200 个城市的 Cloudflare 全球云网络上构建无服务器应用程序。 Cloudflare Workers 提供了一个轻量级的 JavaScript 执行环境,允许开发人员在不配置或不维护基础设施的情况下,扩充现有应用程序或创建全新应用程序。
按照这个说法在cloudflare Workers 安排的JavaScript是直接运行在cdn里面的,这样就省了cdn回源这一步。当然按照上面的说法,免费账户的这些种种限制并不能使用cloudflare Workers 支撑起一个大型网站的,所以通常来说还是要有内容或者数据源的。
之前看到有大佬在WordPress上面做了一个展示steam库存的页面,按照大佬说法结合github仓库代码,需要从steam社区获取数据,然而 【数据删除】,这显然是不方便的,需要用别人的api或者境外服务器自行搭建。但steam有着自己的一套api,就是Steam Web Api,其中https://api.steampowered.com/到目前为止是可以访问的,而且这个网站仅仅提供json之类的给自动化程序阅读的文本,将来出问题的可能性不大,完全可以绕过steam社区对相关游戏数据进行获取。
这个Api的调用需要API key,登录steam账号之后就可以一键获取,里面的api也很多,涵盖各种信息,具体可以去官方文档里面去看。
按照官方文档的说法,api key分为两种,一种是普通用户的apikey,一个steam账号可以申请一个,申请完了之后还可以注销(没试过),有些api只能用发行商apikey调用,在这类api说明上面都有禁止前端直接调用的警告标志,必须通过安全的服务器调用。普通的api上面则没有这个警告。意思就是可以在前端直接调用?
考虑到前端直接调用等于直接把apikey公开出来,这可能对steam的账号有着不可预知的系统性风险,于是决定还是不在前端直接调用了。如果不在乎账号或者有一个新创的小号或者是steam内部工作人员的背书,那就可以直接在前端调用了,也就会省了好多事。
在“安全的服务器”上调用api的方式有很多,如果是一年前的我,肯定会用flask
和jinjia
模板直接整一个html页面出来,(那时候就会这个)。如果是一个月前的我,肯定会用flask_restful
直接整一个API出来(那时候刚会了api的制作),现在的我决定用cloudflare workers
,顺便学一下这种serveless的模式与JavaScript。
在服务端运行的JavaScript之前从来也没有写过,只能照葫芦画瓢,对着官网上的例子和JavaScript教程一点一点搞,最后搞了出来,安排(代理)了其中五个比较常用的api。API最终发布在https://cfwk.dogcraft.top。
服务端调用的JavaScript与网页端的差不多,毕竟脚本解释器都是一样的,但还是有区别的,毕竟服务端与浏览器端的工作环境与要求完全不同。
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
/**
* Respond with hello worker text
* @param {Request} request
*/
async function handleRequest(request) {
return new Response('Hello worker!', {
headers: { 'content-type': 'text/plain' },
})
}
这个是cloudflare给出的hello world
示例 其中
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
应该是监听事件的函数,应该是与JavaScript解释器或cloudflare服务器的运行环境或沙箱对接的一部分,想我这种刚开始写JavaScript一般是不需要改动的,真正处理网络请求的函数是下面那个,返回内容需要new
一个Response
对象。
从返回数据已经掌握(划掉)了,那获得数据就需要用fetch
了,这里的fetch
方法应该和前端JavaScript是一样的,前端可以异步调用,但这里就需要同步调用了。不知道是为什么,盲猜回调函数不能返回response到event.respondWith(handleRequest(event.request))所以要用await
了。
fetch
回来的数据还要await
才能读出来,异步方法真是多。
const sde = await fetch(url2+url3,suit)
// console.log(url2+url3)
return await sde.text();
能通过console.log
调试是真的出乎意料……
还有就是url的切分与路由,从一个例子上找到了解决办法。
let su= new URL(request.url);
var path = su.pathname.split('/')
这会简单的把url且分开,并存储到path
这个数组上,然后通过if else
的
组合就可以处理不同路径的请求了(开始怀念flask的路由处理了)
最后不要忘记允许跨域,不然辛辛苦苦搞了这么多前端没法调用。
response.headers.set('Access-Control-Allow-Origin', "*")
完整的代码就安排在下面,新开一个workers把下面的粘上就能用,别忘了把const stkey="YOUR STEAM WEB API KEY";
改成自己的。
服务端的API到此就算是搞完了,剩下的就是前端页面了……不会css、不会懒加载只会拿 bootstrap4
往上套的我要哭了
目前前端已经安排完了大部分。目前放在https://www.dogcraft.top/steaminfo/。最近家里的联通网络经常抽风,一抽风
github
和套上cloudflare
的网页就打不开(包括刚搞好的API),具体表现是cloudflare的服务器是可以ping通的,但用tenlent
连443端口都没反应,连一个端口关闭的信息都不给,最后都是以链接超时收场。一般一次抽风短则几分钟,长则两三个小时,让人心态崩溃。更让人难受的是我的【数据删除】是过cloudflare的,一旦cloudflare连不上就全完了……剩下的几个功能等网络正常一点再搞,搞完了会尽快把过程发到这里来。
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
/**
* Respond to the request
* @param {Request} request
*/
async function handleRequest(request) {
const init = {
headers: {
'content-type': type,
},
};
let su= new URL(request.url);
var path = su.pathname.split('/')
//const lud= await fetch('https://sig.dogcraft.top/',init)
if (path[1]=='dog') {
req = await dog(request,path);
} else if (path[1]=='cat'){
req = await cat(request,path);
}else if (path[1]=='sum'){
req = await sumf(request,path);
}else if (path[1]=='pig'){
req = await fnd(request,path);
}else if (path[1]=='zig'){
req = 'doge';
}else
{
req = "cat";
}
response = new Response(req, {status: 200});
// console.log(request.referrer);
response.headers.set('Access-Control-Allow-Origin', "*")
return response;
}
const type = 'application/json;charset=UTF-8';
const url2='https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/';
const url4='https://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v0001/';
const url5='https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/';
const url6='https://api.steampowered.com/ISteamUser/GetFriendList/v0001/'
const stkey="YOUR STEAM WEB API KEY";
const stid = "76561198343712334";
async function dog(resdog1,resdog2) {
// let r=resdog1;
let path = resdog2;
// let formData = new FormData();
let stid2 = (resdog2[2])
let url3=`?key=${stkey}&steamid=${stid2}&format=json&include_appinfo=true`;
let suit= {
headers: {
'content-type': type,
},
};
const sde = await fetch(url2+url3,suit)
// console.log(url2+url3)
return await sde.text();
// return r.url+path[1]+" <->"+path[2]
}
async function cat(resdog1,resdog2) {
let path = resdog2;
// let formData = new FormData();
let stid2 = (resdog2[2])
let url3=`?key=${stkey}&steamid=${stid2}&format=json&include_appinfo=true`;
// formData.append("key","EDQW93AFF9BQ45956DC0FDC30D96DRW6");
let suit= {
headers: {
'content-type': type,
},
};
const sde = await fetch(url4+url3,suit)
// console.log(url2+url3)
return await sde.text();
}
async function sumf(resdog1,resdog2) {
let stid2 = (resdog2[2])
let url3=`?key=${stkey}&steamids=${stid2}&format=json`;
let suit= {
method: 'GET',
headers: {
'content-type': type,
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/83.0.4103.61 Chrome/83.0.4103.61 Safari/537.36'
},
};
// console.log(url5+url3);
const sde = await fetch(url5+url3,suit)
// console.log(sde);
return await sde.text();
}
async function fnd(resdog1,resdog2) {
let stid2 = (resdog2[2])
let url3=`?key=${stkey}&steamid=${stid2}&format=json`;
let suit= {
method: 'GET',
headers: {
'content-type': type
// 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/83.0.4103.61 Chrome/83.0.4103.61 Safari/537.36'
},
};
// console.log(url5+url3);
const sde = await fetch(url6+url3,suit)
// console.log(sde);
return await sde.text();
}