WEB__backend--api应用[node.js]
npm i koa node-fetch koa-router lru-cache
lru-cache(做缓存)
工具(无法使用postman时)
curl http://localhost:3000
curl -i http://localhost:3000
time curl -i http://localhost:3000
* 通过以下模拟保护APIkey,密码==》“不落盘”=》不放在磁盘里(硬件磁盘,u盘,stdout)
解决:设置系统环境变量
//命令行
export APPID=5fd90c67a09815ca08b3dc39a36c4ba8 //只对执行的terminal有效
查看是否设置成功
node
>process.env.APPID
code:
const APPID = process.env.APPID;
进入dashboard.heroku.com/apps创建新的app应用
命令行
heroku login
[https://dashboard.heroku.com/apps/weatherdemo33/deploy/heroku-git
按照网页指示操作
heroku log --tail //log日志
(package.json中要加"start":"node index.js",)
heroku config//查看环境变量
heroku config:set APPID= //设置环境变量
heroku会自动给个端口号
const PORT = process.env.PORT || 3000;
app.listen(PORT,()=>{
console.log(`APP listens on PORT: ${PORT}`)
});
一般来说key定期都会换一次,来防止泄漏
Mac操作系统大小写不敏感
但是发布到linux服务器
所以要注意大小写!!!
Key的管理(命名大写)
本地:export
远端:heroku config:set KEY=VALUE
技巧:
- assert断言库---如果第一个参数为false,输出第二个参数并立即终止程序(一般第二个参数都为断言句式)
一般一切对假定(外部等)的依赖都需要做assert
1.判断key有无设置
const assert = require('assert');//断言库
assert(APPID,'APPID must be set before use');
2.判断端口
>heroku config:set HEROKU=true
const isHeroku = !!process.env.HERUKU;//!!将其由string true转换为bool true
if(isHeroku){
assert(process.env.PORT,"PORT must exit!");
}
//其他类似平台
digitalocean
……
代码】weather应用
'use strict';
//所有需要用的库都需要require
const Koa = require('koa');
const Router = require('koa-router');
const fetch =require('node-fetch');
const LRU = require('lru-cache');
//检测key是否存在
const assert = require('assert');//断言库
const isHeroku = !!process.env.HERUKU;//!!将其由string true转换为bool true
assert(APPID,'APPID must be set before use');
//APIKey不应该明文放在代码里
//const APPID ='5fd90c67a09815ca08b3dc39a36c4ba8';
//process:不需要require可以使用,还有很多
const APPID = process.env.APPID;
const weatherUrl = 'https://api.openweathermap.org/data/2.5/weather';
const weatherRouter = new Router();
const maxAge = process.env.PORT?60000*60:3000;
//缓存数据有时效性,所以需要一个过期机制
const cache = new LRU({
maxAge,
max:100
});
//cache.peek(city)
//该api限制每分钟请求60次,可通过缓存解决
//const cache =new Map();
//cache.has(city)
weatherRouter.get('/:city',async (ctx) =>{
const {city} =ctx.params;
if(cache.peek(city)){
ctx.body = cache.get(city);
console.log('fetch weather data from local cache!');
return;
}
// 拼接请求
const requestURL = `${weatherUrl}?q=${city}&appid=${APPID}`;
const res = await fetch(requestURL);
console.log('fetch weather data from remote server!');
if(res.ok){
const weatherContent = await res.json();
//存储缓存
cache.set(city,weatherContent);
ctx.body = weatherContent;
}else{
//handle404 ,可读建议,参考链接
if(res.status === 404){
ctx.body = {
message: `${city} not found! Pl ensure the city name!`
};
ctx.status = 404;
}
//不要让黑客了解漏洞,所以隐藏status code, 可以协议一个errorcode
if(res.status === 500){
ctx.body = {
message: `Service is not avaiable now, pl try again later`,
errorcode:123
};
ctx.status = 200;
}
//500
}
//console.log(res);
});
const app = new Koa();
app.use(weatherRouter.routes());
if(isHeroku){
assert(process.env.PORT,"PORT must exit!");
}
const PORT = process.env.PORT || 3000;
app.listen(PORT,()=>{
console.log(`APP listens on PORT: ${PORT}`)
});
https://nodejs.org/dist/latest-v12.x/docs/api/
Stability Index
Stability 0:不稳定,不建议用
Stability 1: 新api,不稳定(基数版本
Stability 2: 稳定
判断列表是否是真gloabal
- Assert
assert.deepEqual(v1,v2)判断相等 - Buffer
复杂,重要,实际工作接触不多 - Child Process子进程
重要
父进程fork(创建)子进程
用途:share 命令
基于管道和流的design在node中经常使用
【
|:管道
ls|grep json stream概念
】
eg.fs.createReadFileStream('').pipe()
child_process.exec('ls')
child_process.fork()
- Cluster
超级重要 - Command LIne Option(了解)
- Console(了解)
- Cryto(了解)
- DNS(了解)
- ECMAScriptModules(暂时没用)
- Errors
- Events
超级重要(后端用的少但是前端非常重要,要深刻理解) - File System
超级重要 - Globals重要
__dirname不是真的global
__filename不是真的global
process
setTimeout - HTTP
非常非常重要 - HTTPS
重要几乎和http一样 - Modules
非常重要 - Net (了解)
- OS (了解)cpu核心数
- Path
非常重要(路径拼接/多系统工作) - Process
重要
process.env
(kill)
process.argv - QueryString
看看
encode
decode - UDP/Datagram(视频直播)
*URL
科普重要 - Util
工具函数 - Zlib
压缩处理