当前位置: 首页 > news >正文

Koa学习

Koa 安装与配置

1. 初始化项目

在终端中执行以下命令:

# 创建项目文件夹
mkdir koa
cd koa# 初始化并安装依赖
npm init -y
npm install koa
npm install nodemon --save-dev

2. 修改 package.json

package.json 文件中进行如下修改:

{"type": "module","scripts": {"dev": "nodemon index.js","test": "echo \"Error: no test specified\" && exit 1"}
}

3. 编写初始化代码

在终端中新建 index.js 文件:

# 测试代码文件
code index.js

index.js 中添加以下代码:

import Koa from 'koa';const hostname = "127.0.0.1"; // 服务器监听的 IP 地址
const port = 8008; // 服务器监听的端口号// 实例化一个 Koa 对象
const app = new Koa();// 注册中间件
app.use(async ctx => {ctx.body = "Helloworld"; // 设置响应体的内容
});// 启动 HTTP 服务器
app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

4. 启动服务器

在终端中运行以下命令以启动服务器:

npm run dev

2. 中间件

import Koa from 'koa';const hostname = "127.0.0.1"; // 服务器监听的 IP 地址
const port = 8008; // 服务器监听的端口号// 实例化一个 Koa 对象
const app = new Koa();// 演示中间件
app.use(async (ctx, next) => {console.log(111);await next();console.log(222);
});// 注册中间件
app.use(async ctx => {ctx.body = "Helloworld"; // 设置响应体的内容console.log(333);
});// 启动 HTTP 服务器
app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

打印两遍是因为请求了图标,block即可

在这里插入图片描述


3. 安装和配置路由 - GET 请求

安装路由:

npm i @koa/router

测试代码:

import Koa from 'koa';
import Router from '@koa/router';const hostname = "127.0.0.1"; // 服务器监听的 IP 地址
const port = 8008; // 服务器监听的端口号// 实例化一个 Koa 对象
const app = new Koa();
const router = new Router(); // 实例化一个 Router 对象router.get('/', async ctx => { // GET 请求ctx.body = "Helloworld";
});router.get('/test', async ctx => { // GET 请求let id = ctx.query.id;let web = ctx.query.web;ctx.body = id + " : " + web;
});router.get('/test2/id/:id/web/:web', async ctx => {let id = ctx.params.id;let web = ctx.params.web;ctx.body = id + " : " + web;
});router.redirect('/test3', 'https://www.baidu.com');app.use(router.routes());// ************************
const userRouter = new Router({ prefix: '/user' });
userRouter.get('/add', async ctx => {ctx.body = "添加用户";
});
userRouter.get('/del', async ctx => {ctx.body = "删除用户";
});
app.use(userRouter.routes());// 在所有路由之后添加 404 处理函数
app.use(async ctx => {if (!ctx.body) { // 若没有设置 ctx.body, 则说明没有匹配任何路由ctx.status = 404;ctx.body = '404 Not Found';}
});// 启动 HTTP 服务器
app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

4. POST 请求

安装 @koa/bodyparser

npm i @koa/bodyparser

测试代码:

import Koa from 'koa';
import Router from '@koa/router';
import BodyParser from '@koa/bodyparser';const hostname = "127.0.0.1"; // 服务器监听的 IP 地址
const port = 8008; // 服务器监听的端口号// 实例化一个 Koa 对象
const app = new Koa();
const router = new Router(); // 实例化一个 Router 对象app.use(BodyParser()); // 使用 @koa/bodyparser 中间件来解析 POST 请求// ------ POST 请求
// [application/x-www-form-urlencoded] http://127.0.0.1:8008/postUrl
router.post('/postUrl', async ctx => {let id = ctx.request.body.id;let web = ctx.request.body.web;ctx.body = id + " : " + web;
});// [application/json] http://127.0.0.1:8008/postJson
router.post('/postJson', async ctx => {let id = ctx.request.body.id;let web = ctx.request.body.web;ctx.body = id + " : " + web;
});app.use(router.routes()); // 将定义在 router 对象中的路由规则添加到 app 实例中// 启动 HTTP 服务器
app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

5. 错误处理

测试代码:

import Koa from 'koa';
import Router from '@koa/router';const hostname = "127.0.0.1";
const port = 8008;const app = new Koa();
const router = new Router();router.get('/', async ctx => {throw new Error("测试");
});/*将 '错误处理中间件' 放在 '路由处理中间件' 之前, 当一个请求到达时,会先经过 '错误处理中间件', 然后才会进入 '路由处理中间件',是为了确保可以捕获错误
*/
app.use(async (ctx, next) => { // 错误处理中间件try {await next();} catch (err) {console.log('err:', err);ctx.status = 500;ctx.body = 'err: ' + err.message;}
});app.use(router.routes()); // 路由处理中间件app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

6. 跨域

测试代码:

import Koa from 'koa';
import Router from '@koa/router';
import Cors from '@koa/cors';const hostname = "127.0.0.1";
const port = 8008;const app = new Koa();
const router = new Router(); // 实例化一个 Router 对象app.use(Cors()); // 允许跨域请求router.get('/', async ctx => { // GET 请求ctx.body = "Helloworld";
});app.use(router.routes()); // 将定义在 router 对象中的路由规则添加到 app 实例中app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

7. Koa 图片上传功能实现指南

1. 安装依赖

在终端中执行以下命令以安装 @koa/multer

npm install @koa/multer

注意事项

安装过程中可能会出现如下警告:

npm warn deprecated @babel/plugin-proposal-export-namespace-from@7.18.9:
This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained.
Please use @babel/plugin-transform-export-namespace-from instead.

2. 编写代码

index.js 中添加以下代码:

import Koa from 'koa';
import Router from '@koa/router';
import BodyParser from '@koa/bodyparser';
import Cors from '@koa/cors';
import Multer from '@koa/multer';
import path from 'path';const hostname = "127.0.0.1";
const port = 8008;const app = new Koa();
const router = new Router(); // 实例化一个 Router 对象app.use(BodyParser()); // 使用 @koa/bodyparser 中间件解析 POST 请求
app.use(Cors()); // 允许跨域请求// 配置磁盘存储引擎
const storage = Multer.diskStorage({destination: (request, file, callbackFunc) => { // 指定文件保存路径callbackFunc(null, './upload');},filename: (request, file, callbackFunc) => { // 设置文件名callbackFunc(null, Date.now() + path.extname(file.originalname));},
});const multer = Multer({ // 实例化一个 Multer 对象storage, // 磁盘存储引擎limits: { // 限制条件fileSize: 2 * 1024 * 1024, // 限制文件大小为 2MB},fileFilter: (request, file, callbackFunc) => { // 文件过滤器const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];if (allowedTypes.includes(file.mimetype)) {callbackFunc(null, true);} else {callbackFunc(new Error('不支持的文件类型'), false);}}
});// 上传接口
router.post('/upload', multer.single('file'), async ctx => {const file = ctx.request.file; // 获取上传的文件信息if (file) {console.log(file);ctx.body = "文件上传成功";}
});// 错误处理中间件
app.use(async (ctx, next) => {try {await next();} catch (err) {ctx.status = 500;ctx.body = 'err: ' + err.message;}
});app.use(router.routes()); // 路由处理中间件// 启动服务器
app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

3. 启动服务器

在终端中运行以下命令以启动服务器:

npm run dev

4. 上传文件

使用 POST 请求上传文件到 http://127.0.0.1:8008/upload,确保请求中包含名为 file 的文件字段。

在这里插入图片描述


8. Cookie

测试代码:

import Koa from 'koa';
import Router from '@koa/router';const hostname = "127.0.0.1";
const port = 8008;const app = new Koa();
const router = new Router(); // 实例化一个 Router 对象// Cookie 可用于在浏览器中存储数据
router.get('/', async ctx => {// 赋值ctx.cookies.set("name", encodeURIComponent("hello")); // encodeURIComponent: URL 编码ctx.cookies.set("web", "baidu.com", {maxAge: 5 * 1000, // 30 秒 [maxAge: 有效期 单位: 毫秒]httpOnly: false // 允许浏览器通过 JS 访问和修改该 cookie});// 取值 - 在同一个请求内, 无法立即获取到刚刚设置的 cookie 的值let name = ctx.cookies.get("name");console.log("name:", decodeURIComponent(name)); // decodeURIComponent: URL 解码// 删除// ctx.cookies.set("name", "", { maxAge: 0 });ctx.body = "Helloworld";
});app.use(router.routes()); // 将定义在 router 对象中的路由规则添加到 app 实例中app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

9. Session(存在客户端的 Cookie 中,一般别用)

安装 koa-session

npm i koa-session

测试代码:

import Koa from 'koa';
import Router from '@koa/router';
import Session from 'koa-session';const hostname = "127.0.0.1";
const port = 8008;const app = new Koa();
const router = new Router(); // 实例化一个 Router 对象// koa-session 默认将 session 数据存储在客户端的 cookie 中
app.keys = ['session.dengruicode.com']; // 设置会话签名的密钥
const CONFIG = {key: 'DR', // 存储在 cookie 中的键名maxAge: 24 * 60 * 60 * 1000, // 24 小时 有效期 (单位: 毫秒)signed: true, // 是否启用会话签名, 用于防止 CSRF 攻击secure: false, // 是否仅通过 https 协议发送 cookie
};
app.use(Session(CONFIG, app));router.get('/', async ctx => {// 赋值ctx.session.name = "邓瑞";ctx.session.url = "dengruicode.com";if (!ctx.session.user) {ctx.session.user = 100;} else {ctx.session.user++;}// 取值let name = ctx.session.name;console.log("name:", name);// 删除// ctx.session = null; // 清空// delete ctx.session.name; // 删除 session 中的 name 属性ctx.body = "用户:" + ctx.session.user;
});app.use(router.routes()); // 将定义在 router 对象中的路由规则添加到 app 实例中app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

10. JWT

安装 jsonwebtoken

npm i jsonwebtoken

JWT 结构

JWT(JSON Web Token)是一种基于令牌的认证和授权机制,由三部分组成:Header(头部)、Payload(负载)、Signature(签名)。

Header(头部)

{"alg": "HS256", // algorithm 算法"typ": "JWT" // type 类型
}

Payload(负载)

{"sub": 1, // Subject 主题 (用户唯一 ID)"iss": "dengruicode.com", // Issuer 发行者"iat": 1719930255, // Issued At 发行时间"nbf": 1719930255, // Not Before 生效时间"exp": 1720016655, // Expiration Time 过期时间"aud": [ // Audience 观众字段为空, 表示没有观众限制, 可以被任何接收方处理""],"data": { // 自定义数据"name": "邓瑞","gender": "男"}
}

Signature(签名)

HMACSHA256(base64UrlEncode(Header) + "." +base64UrlEncode(Payload),密钥
)

测试代码:

import Koa from 'koa';
import Router from '@koa/router';
import JWT from 'jsonwebtoken';const hostname = "127.0.0.1";
const port = 8008;const app = new Koa();
const router = new Router(); // 实例化一个 Router 对象router.get('/', async ctx => {let key = 'koaTest'; // 密钥let token = generateToken(key); // 生成 tokenparseToken(token, key); // 解析 tokenctx.body = token;
});app.use(router.routes()); // 将定义在 router 对象中的路由规则添加到 app 实例中// 生成 token
let generateToken = key => {let id = 1; // 用户唯一 IDlet now = Math.floor(Date.now() / 1000); // 当前时间戳 单位: 秒let expire = 24 * 60 * 60;// 负载let payload = {sub: id, // Subject 主题 (用户唯一 ID)iss: 'dengruicode.com', // Issuer 发行者iat: now, // Issued At 发行时间nbf: now, // Not Before 生效时间exp: now + expire, // Expiration Time 过期时间aud: [''], // Audience 观众字段为空, 表示没有观众限制, 可以被任何接收方处理data: { // 自定义数据name: '邓瑞',gender: '男',}};// 使用负载(payload)、密钥(key)和指定的签名算法(HS256)生成 tokenlet token = JWT.sign(payload, key, { algorithm: 'HS256' });return token;
};// 解析 token
let parseToken = (token, key) => {let payload = JWT.verify(token, key, { algorithm: 'HS256' });console.log('解析后的 payload:', payload);
};app.listen(port, hostname, () => {console.log(`服务器已启动: http://${hostname}:${port}`);
});

以上是 Koa 的基本使用指南和功能实现,包括中间件、路由、错误处理、跨域、文件上传、Cookie、Session 和 JWT 等功能。确保在实际开发中根据需求进行适当的修改和扩展。

相关文章:

Koa学习

Koa 安装与配置 1. 初始化项目 在终端中执行以下命令: # 创建项目文件夹 mkdir koa cd koa# 初始化并安装依赖 npm init -y npm install koa npm install nodemon --save-dev2. 修改 package.json 在 package.json 文件中进行如下修改: {"type…...

linux线程 | 线程的概念

前言:本篇讲述linux里面线程的相关概念。 线程在我们的教材中的定义通常是这样的——线程是进程的一个执行分支。 线程的执行粒度, 要比进程要细。 我们在读完这句话后其实并不能很好的理解什么是线程。 所以, 本节内容博主将会带友友们理解什么是线程&a…...

2024年软件设计师中级(软考中级)详细笔记【3】数据结构(下)(分值5分)

上午题第3章数据结构下部目录 前言第3章 数据结构【下】(5分)3.5 查找3.5.1 查找的基本概念【考点】3.5.2 静态查找表的查找方法3.5.3 动态查找表3.5.4 哈希表3.5.4.1 哈希表的定义3.5.4.2 哈希函数的构造方法3.5.4.3 处理冲突的方法 3.6 排序3.6.1 排序的基本概念3.6.2 简单排…...

WPF|依赖属性SetCurrentValue方法不会使绑定失效, SetValue方法会使绑定失效?是真的吗?

引言 最近因为一个触发器设置的结果总是不起效果的原因,进一步去了解[依赖属性的优先级](Dependency property value precedence - WPF .NET | Microsoft Learn)。在学习这个的过程中发现对SetCurrentValue一直以来的谬误。 在WPF中依赖属性Dependency property的…...

Windows搭建Java开发环境(Building a Java development environment on Windows)

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…...

用FPGA做一个全画幅无反相机

做一个 FPGA 驱动的全画幅无反光镜数码相机是不是觉得很酷? 就是上图这样。 Sitina 一款开源 35 毫米全画幅 (3624 毫米) CCD 无反光镜可换镜头相机 (MILC),这个项目最初的目标是打造一款数码相机,将 SLR [单镜头反光] 相机转换为 DSLR [数码…...

使用 Go 语言与 Redis 构建高效缓存与消息队列系统

什么是 Redis? Redis 是一个开源的内存数据库,支持多种数据结构,包括字符串、列表、集合、哈希和有序集合。由于 Redis 运行在内存中,读写速度极快,常被用于构建缓存系统、实时排行榜、会话存储和消息队列等高并发场景…...

springboot 整合spring ai实现 基于知识库的客服问答

rag 需求产生的背景介绍: 在使用大模型时,常遇到的问题之一是模型可能产生幻觉,即生成的内容缺乏准确性。此外,由于大模型不直接访问企业的专有数据,其响应可能会显得泛泛而谈,不够精准或具体,…...

云原生(四十九) | WordPress源码部署

文章目录 WordPress源码部署 一、WordPress部署步骤 二、创建项目目录 三、上传源码到WordPress 四、配置安全组 五、配置WordPress 六、访问WordPress WordPress源码部署 一、WordPress部署步骤 第一步:创建项目目录 第二步:上传源码到项目目…...

Spring Boot 集成 LiteFlow 实现业务流程编排

LiteFlow 是一款轻量级的流程编排框架,它允许开发者通过简单的配置方式,将复杂的业务流程分解为多个独立的节点,然后通过定义规则来编排节点,达到解耦业务逻辑、提高代码可维护性的目的 1. LiteFlow 的基本概念 在 LiteFlow 中,主要有以下几个概念: 节点 (Node):代表一…...

在 Android Studio 中引入android.os.SystemProperties

在 Android Studio 中引入android.os.SystemProperties 前言 网上有很多种方法,其中直接导入包的办法是行不通的,昨天自己发现问题后也踩了很多坑,现在把问题解决了也全面汇总了几种方法,确保可以百分百引入 1. layoutlib.jar包…...

代码随想录算法训练营总结

这几天一直有事情需要忙,所以现在来准备总结以下训练营的成果。 先说以下总体感受,非常值得!!! 从两个月前开始跟着每天看发布的任务,然后每天坚持打卡,收获还是很大的,从数组开始…...

【uniapp】使用uniapp实现一个输入英文单词翻译组件

目录 1、组件代码 2、组件代码 3、调用页面 4、展示 前言&#xff1a;使用uniapp调用一个在线单词翻译功能 1、组件代码 2、组件代码 YouDaoWordTranslator <template><view class"translator"><input class"ipttext" type"te…...

6. 继承、重写、super、final

文章目录 一、重新定义需求二、继承1. 继续分析2. 概念3. 代码① 父类② 子类③ 测试结果 4. 饿狼传说之多层继承① 概念② 代码 5. 多继承 三、方法的重写1. 情境2. 代码① 吃什么② 怎么叫(Override重写) 3. 小结 四、super1. 啃老2. 啃老啃到底 五、final1. 用途及特征2. 举…...

Redis 其他类型 渐进式遍历

我们之前已经学过了Redis最常用的五个类型了&#xff0c;然而Redis还有一些在特定场景下比较好用的类型 Redis最关键的五个数据类型&#xff1a; 上面的类型是非常常用&#xff0c;很重要的类型。 除此之外的其他类型不常用&#xff0c;只是在特定的场景能够发挥用处&#…...

科研绘图系列:R语言绘制SCI文章图2

文章目录 介绍加载R包导入数据图a图b图d系统信息介绍 文章提供了绘制图a,图b和图d的数据和代码 加载R包 library(ggplot2) library(dplyr) library(readxl) library(ggpmisc)导入数据 数据可从以下链接下载(画图所需要的所有数据): 百度网盘下载链接: https://pan.baid…...

ARM知识点三和串口代码的编写流程

ARM的一些常见问题 ARM 体系结构的主要特点是什么&#xff1f; 精简指令集 (RISC)&#xff1a;ARM 采用 RISC 结构&#xff0c;指令集较小且简单&#xff0c;执行效率高。相比于复杂指令集 (CISC)&#xff0c;RISC 更强调每条指令的执行速度。低功耗设计&#xff1a;ARM 处理…...

【unity踩坑】打开vs2022没有文字联想/杂项文件

unity打开vs2022没有文字联想 修改外置编辑器安装unity开发插件vs编辑器显示杂项文件 修改外置编辑器安装unity开发插件 参考 在unity项目里选择Edit-> Preferences->External Tools然后更换编辑器 在vs工具界面添加unity游戏开发选项。 重新打开还是有问题&#xff…...

WebGoat JAVA反序列化漏洞源码分析

目录 InsecureDeserializationTask.java 代码分析 反序列化漏洞知识补充 VulnerableTaskHolder类分析 poc 编写 WebGoat 靶场地址&#xff1a;GitHub - WebGoat/WebGoat: WebGoat is a deliberately insecure application 这里就不介绍怎么搭建了&#xff0c;可以参考其他…...

大数据-161 Apache Kylin 构建Cube 按照日期、区域、产品、渠道 与 Cube 优化

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…...

uni-app使用v-show编译成微信小程序的问题

问题 在uni-app使用v-show语法编译成微信小程序会有一个问题 当我们设置成v-show"false" 在Hbuilder X里面确实没有显示 然后运行到 微信开发程序里面 发现显示了出来&#xff0c;说明设置的 v-show"false"没有起作用 解决办法 首先去uniapp官网查看v…...

充电宝租赁管理系统网站毕业设计SpringBootSSM框架开发

目录 1. 概述 2. 技术选择与介绍 3. 系统设计 4. 功能实现 5. 需求分析 1. 概述 充电宝租赁管理系统网站是一个既实用又具有挑战性的项目。 随着移动设备的普及和人们日常生活对电力的持续依赖&#xff0c;充电宝租赁服务已成为现代都市生活中的一项重要便利设施。它不仅为…...

喜讯!迈威通信TSN产品通过“时间敏感网络(TSN)产业链名录计划”评测,各项指标名列前茅

TSN技术&#xff0c;作为推动企业网络化与智能化转型的关键力量&#xff0c;已成为工业网络迈向下一代演进的共识方向&#xff0c;正加速重构工业网络的技术架构与产业生态。为响应这一趋势&#xff0c;工业互联网产业联盟携手中国信息通信研究院及50余家产学研用单位&#xff…...

国产工具链GCKontrol-GCAir助力控制律开发快速验证

前言 随着航空领域技术的不断发展&#xff0c;飞机的飞行品质评估和优化成为了航空领域的一个重要任务&#xff0c;为了确保飞行器在各种复杂条件下的稳定性&#xff0c;控制律设计过程中的模型和数据验证需要大量仿真和测试。 本文将探讨基于世冠科技的国产软件工具链GCKont…...

嵌入式开发:STM32 硬件 CRC 使用

测试平台&#xff1a;STM32G474系列 STM32硬件的CRC不占用MCU的资源&#xff0c;计算速度快。由于硬件CRC需要配置一些选项&#xff0c;配置不对就会导致计算结果错误&#xff0c;导致使用上没有软件计算CRC方便。但硬件CRC更快的速度在一些有时间资源要求的场合还是非…...

基于STM32的智能家居语音控制系统:集成LD3320、ESP8266设计流程

一、项目概述 项目目标和用途 近年来&#xff0c;智能家居产品逐渐成为家庭生活中不可或缺的一部分。为了提升家庭生活的便捷性和舒适度&#xff0c;本项目旨在设计一款基于STM32F407VGT6&#xff08;Cortex-M4内核&#xff09;微控制器的多功能智能家居语音控制系统。该系统…...

【docker】要将容器中的 livox_to_pointcloud2 文件夹复制到宿主机上

复制文件夹 使用 docker cp 命令从容器复制文件夹到宿主机&#xff1a; docker cp <container_id_or_name>:/ws_livox/src/livox_to_pointcloud2 /path/to/host/folder sudo docker cp dandong_orin_docker:/ws_livox/src/livox_to_pointcloud2 /home...

网络编程(17)——asio多线程模型IOThreadPool

十七、day17 之前我们介绍了IOServicePool的方式&#xff0c;一个IOServicePool开启n个线程和n个iocontext&#xff0c;每个线程内独立运行iocontext, 各个iocontext监听各自绑定的socket是否就绪&#xff0c;如果就绪就在各自线程里触发回调函数。为避免线程安全问题&#xf…...

【rust/egui/android】在android中使用egui库

文章目录 说在前面AndroidStudio安装编译安装运行问题 说在前面 操作系统&#xff1a;windows11java版本&#xff1a;23android sdk版本&#xff1a;35android ndk版本&#xff1a;22rust版本&#xff1a; AndroidStudio安装 安装AndroidStudio是为了安装sdk、ndk&#xff0c;…...

Git---Git打标签

打标签 像其他版本控制系统&#xff08;VCS&#xff09;一样&#xff0c;Git 可以给仓库历史中的某一个提交打上标签&#xff0c;以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点&#xff08; v1.0 、 v2.0 等等&#xff09;。 在本节中&#xff0c;你将会学习如…...