ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Node.js初学笔记

2021-09-27 21:30:12  阅读:161  来源: 互联网

标签:Node const log res app req js 初学 console


Node.js初学笔记

Node.js学习笔记,包括原生模块、Express框架、Koa框架的基本使用。以及基于Koa项目的搭建以及Postman接口测试和一些使用技巧。

Node.js http模块基础功能

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(`创建服务器`);
});

Express.js框架的简单使用

  • 服务的创建
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");
});
  • json参数的解析

app.use(express.json());

app.post('/login', (req, res, next) => {
    // 参数解析
    console.log(req.body);
    res.end("hello world");
});

  • x-www-from-urlencoded参数解析
app.use(express.urlencoded());
app.post('/login', (req, res, next) => {
    // 参数解析
    console.log(req.body);
    res.end("hello world");
});
  • from-data参数解析
// 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");
});
  • Query Params解析
// 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");
});
  • response返回json数据
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": "请求失败"});
});

koa.js框架的简单使用

  • 服务的创建
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参数和x-www-form-urlencoded参数解析
// 参数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";
});
  • form-data参数解析
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);
});
  • 结合Koa-log4.js日志的使用
// 配置文件
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);
  • 基于Koa.js框架搭建项目结构目录

包括目录结构、路由、环境变量、数据库配置、错误处理、日志等功能。
在这里插入图片描述

项目下载地址

JWT的Token机制

组成部分 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

Postman的使用技巧

  • 环境变量的设置

点击眼睛,添加环境变量

在这里插入图片描述

在这里插入图片描述

后面在请求接口中就可以使用
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变量
在这里插入图片描述

标签:Node,const,log,res,app,req,js,初学,console
来源: https://blog.csdn.net/wj610671226/article/details/120517752

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有