Node.js学习笔记,包括原生模块、Express框架、Koa框架的基本使用。以及基于Koa项目的搭建以及Postman接口测试和一些使用技巧。
node.js版本是v14.17.3
记录http模块常用功能:
1、url解析
2、headers数据获取
3、请求方式获取(get/post等)
4、响应状态码设置
5、响应头设置
6、从第三方服务器获取数据
const http = require('http'); const url = require('url'); const querystring = require('querystring'); const server = http.createServer((req, res) => { // request console.log(`req.url = `, req.url); console.log(`req.headers = `, req.headers); console.log(`req.method = `, req.method); // url解析处理 const parseUrl = url.parse(req.url); console.log( `parseUrl = `, parseUrl); const {pathname, query} = url.parse(req.url); console.log(`pathname = ${pathname}, quary = ${pathname}`); if (pathname === '/login') { if (req.method === 'GET') { // quary解析 // http://localhost:8989/login?name=zhangsan&age=18 const result = querystring.parse(query); console.log(result); console.log(result.name); console.log(result.age); res.end("hello world get"); return; } else if (req.method === 'POST') { // http://localhost:8989/login postman raw -> json // post 请求参数json解析 req.on('data', (data) => { // req.setEncoding('utf-8'); const {name, age} = JSON.parse(data); console.log(name, age); }); res.end("hello world post"); // 响应头文件 // res.setHeader("Content-Type", "text/plain;charset=utf8"); // res.writeHead(200, { // "Content-Type": "text/html;charset=utf8" // }); // 响应结果 // res.end("<h2>Hello Server</h2>"); // return; } } // http请求,从第三方服务器请求数据 if (pathname === '/getData') { if (req.method === 'GET') { console.log('从第三方服务器获取数据 get'); http.get('http://apis.juhe.cn/mobile/get?phone=13429667914', (response) => { response.on('data', (data) => { // console.log(`getServerData =`, data); const result = JSON.parse(data); console.log(`result = `, result); res.setHeader("Content-Type", "text/json;charset=utf8"); res.end(data); }); }); } else { console.log('从第三方服务器获取数据 post'); // http://v.juhe.cn/toutiao/index?type=top&key=APPKEY const otherReq = http.request({ method: 'POST', hostname: 'v.juhe.cn', path: '/toutiao/index' }, (response) => { response.on('data', (data) => { // console.log(`getServerData =`, data); const result = JSON.parse(data); console.log(`result = `, result); res.setHeader("Content-Type", "text/json;charset=utf8"); res.end(data); }); });; const postData = JSON.stringify({ 'type': 'top' }); otherReq.write(postData); otherReq.end(); } return; } res.end("hello world"); }); server.listen(8989, 'localhost', () => { console.log(`创建服务器`); });
const express = require("express"); const app = express(); const port = 8989; app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) })
app.use((req, res, next) => { console.log(`中间件1`); // 调用下一个中间件 next(); }); app.use((req, res, next) => { console.log(`中间件2`); res.end("hello world"); });
app.use(express.json()); app.post('/login', (req, res, next) => { // 参数解析 console.log(req.body); res.end("hello world"); });
app.use(express.urlencoded()); app.post('/login', (req, res, next) => { // 参数解析 console.log(req.body); res.end("hello world"); });
// npm install multer const multer = require('multer'); const upload = multer(); app.use(upload.any()); app.post('/login', (req, res, next) => { // 参数解析 console.log(req.body); res.end("hello world"); });
// url -> http://localhost:8989/login/23/zhangsan app.get('/login/:id/:name', (req, res, next) => { // 参数解析 { id: '123', name: 'zhad' } console.log(req.params); res.end("hello world login"); }); // url -> http://localhost:8989/login?name=zhandan app.get('/login', (req, res, next) => { // 参数解析 console.log(req.query); res.end("hello world login"); });
const multer = require('multer'); const upload = multer({ dest: "./upload" }); app.post('/upload', upload.single('file'), (req, res, next) => { res.end('文件上传成功'); });
给上传的文件修改名称和设置后缀名
const multer = require('multer'); const path = require('path'); const storage = multer.diskStorage({ destination: (req, file, callback) => { callback(null, "upload/") }, filename: (req, file, callback) => { callback(null, Date.now() + path.extname(file.originalname)); } }); const upload = multer({ storage }); app.post("/upload", upload.single('file'), (req, res, next) => { console.log(req.file.buffer); res.end('上传文件成功'); });
// npm install morgan const fs = require('fs'); const morgan = require('morgan'); const log = fs.createWriteStream("./log/login.log", { flags: 'a+' }); // 日志记录 app.use(morgan('combined', {stream: log})); app.post('/login', (req, res, next) => { // 参数解析 console.log(req.body); res.end("hello world"); });
app.post('/login', (req, res, next) => { res.json(["name", "zhangsan"]); });
const userRouter = require('./routes/users'); app.use('/user', userRouter); // users.js文件 const express = require("express"); const router = express.Router(); router.get('/:id', (req, res, next) => { res.end("根据id 获取user info"); }); module.exports = router;
把静态资源的目录设置好 // http://localhost:8989/123.png app.use(express.static('./static'));
app.get('/login', (req, res, next) => { console.log('logon test'); // 进入下一个错误处理的中间件 next(new Error()); }); app.use((err, req, res, next) => { console.log(`err`, err); res.status(400).json({"error": "请求失败"}); });
const Koa = require("koa"); const app = new Koa(); app.listen(8989, () => { console.log("创建服务器成功"); });
app.use((ctx, next) => { console.log("第一个中间件"); // 调用下一个中间件 next(); }); app.use((ctx, next) => { console.log("第二个中间件"); ctx.body = "hello koa"; });
app.use((ctx, next) => { console.log(`ctx.request.path = `, ctx.request.path); console.log(`ctx.request.method = `, ctx.request.method); ctx.body = "hello koa"; });
// npm install koa-router const userRouter = require("./router/user"); app.use(userRouter.routes()); app.use(userRouter.allowedMethods()); // user.js const Router = require('koa-router'); const router = new Router({prefix: '/user'}); // 请求url -> http://localhost:8989/user/info router.post('/info', (ctx, next) => { console.log(ctx.request.query); ctx.body = "user post"; });
// 参数json解析 npm install koa-bodyparser const bodyParser = require('koa-bodyparser'); app.use(bodyParser()); app.use((ctx, next) => { console.log(ctx.request.body); ctx.body = "user post"; });
const multer = require('koa-multer'); const upload = multer(); app.use(upload.any()); app.use((ctx, next) => { console.log(ctx.req.body); ctx.body = "user post"; });
const multer = require('koa-multer'); const upload = multer({ dest: './upload' }); router.post('/upload', upload.single('file'), (ctx, next) => { console.log(ctx.req.file); ctx.body = "上传成功"; });
上传文件并修改名称添加后缀
const multer = require('koa-multer'); const path = require('path'); const storage = multer.diskStorage({ destination: (req, file, callback) => { callback(null, "upload/") }, filename: (req, file, callback) => { callback(null, Date.now() + path.extname(file.originalname)); } }); const upload = multer({ storage }); router.post('/upload', upload.single('file'), (ctx, next) => { console.log(ctx.req.file); ctx.body = "上传成功"; });
// npm install koa-static const staticRes = require('koa-static'); app.use(staticRes('./static'));
app.use((ctx, next) => { ctx.app.emit('error', new Error('error message', ctx)); }); app.on('error', (err, ctx) => { console.log(`err.message = `, err.message); });
// 配置文件 const path = require('path'); const log4js = require('koa-log4'); log4js.configure({ appenders: { out: { type: "console" }, access: { type: 'dateFile', pattern: '-yyyy-MM-dd.log', //生成文件的规则 alwaysIncludePattern: true, //文件名始终以日期区分 encoding:"utf-8", filename: path.join('logs/', 'access.log') //生成文件名 }, application: { type: 'dateFile', pattern: '-yyyy-MM-dd.log', alwaysIncludePattern: true, encoding:"utf-8", filename: path.join('logs/', 'application.log') }, }, categories: { default: { appenders: ['out'], level: 'debug' }, access: { appenders: ['access'], level: 'info' }, application: { appenders: ['application'], level: 'info' } } }); // 记录所有访问级别的日志 const accessLogger = () => log4js.koaLogger(log4js.getLogger('access')); // 控制台输出 const debugLogger = log4js.getLogger('out'); // 记录所有应用级别的日志 const applicationLogger = log4js.getLogger('application'); module.exports = { accessLogger, applicationLogger, debugLogger }; // 使用 const { accessLogger } = require('../app/logs-config'); // koa-log app.use(accessLogger()); // 基本使用 const { applicationLogger, debugLogger } = require('../app/logs-config'); // 打印debug到控制台 debugLogger.debug('errorHandle message = ' + error.message); // 打印错误日志到文件 applicationLogger.error('errorHandle message = ' + message);
包括目录结构、路由、环境变量、数据库配置、错误处理、日志等功能。
项目下载地址
组成部分 header+payload+signature
header:
1、alg:采用的加密算法,默认是 HMAC SHA256(HS256),采用同一个密钥进行 加密和解密;
2、typ:JWT,固定值,通常都写成JWT即可;
3、会通过base64Url算法进行编码;
payload:
1、携带的数据,比如我们可以将用户的id和name放到payload中;
2、默认也会携带iat(issued at),令牌的签发时间;
3、也可以设置过期时间:exp(expiration time);
4、会通过base64Url算法进行编码
signature:
1、设置一个secretKey,通过将前两个的结果合并后进行HMACSHA256的算法;
2、HMACSHA256(base64Url(header)+.+base64Url(payload), secretKey);
3、但是如果secretKey暴露是一件非常危险的事情,因为之后就可以模拟颁发token, 也可以解密token;
生成的内容如下: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySUQiOjEsInVzZXJOYW1lIjoi5byg5LiJIiwiaWF0IjoxNjMxNzU3OTQ0LCJleHAiOjE2MzE3NjE1NDR9.ORFHXXmu_q5cFVCKhIWSfPDmUiYEE_ocN1avi8gnzkGC3BZ6bq_KZniR9TK78Yk_V9j6RedwXelPE_Y7XJHup-sMhPh6Lcsk02QnrMc_uORo2jNaD3I75S9zEl18hnFtlPJGJAbyxaLzNVTAbeJvWTVMF4tjsByCzRHx991xB3A
点击眼睛,添加环境变量
后面在请求接口中就可以使用
base_url代替http://localhost:8989
获取某个接口的数据,设置某个值为全局变量,比如token
在接口的Tests中编写脚本
// {{base_url}}/createToken 请求接口 返回值 { "success": 0, "data": { "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySUQiOjEsInVzZXJOYW1lIjoi5byg5LiJIiwiaWF0IjoxNjMxODQ2Nzk2LCJleHAiOjE2MzE4NTAzOTZ9.fwFUeusq0JJ_sZ7ysksH9NRlpTqanVOU10XN96kY62OzcIJSMQ3SrQVK0oBI-r2oiS-NnQUuvdwdpD14Tns6BHFuWFjNBTET_udzkOTgrgyn4xz-aDY8MjLG61XFoqEVXXnFaAi209XyKwNi-MFAEcMaieRtYJXT3dibKzi7GaU" }, "message": null } // 设置全局变量token const res = pm.response.json(); console.log(res.data.token); pm.globals.set('token', res.data.token);
在其他接口处使用token变量