首页 > 其他分享 >koa-body 中间件解析原理

koa-body 中间件解析原理

时间:2023-05-15 21:13:58浏览次数:34  
标签:body isText const koa ctx 中间件 isMultipart import

常见的请求数据类型:

  1. application/json  常见于post请求 未经过任何处理 以json的格式通过body传输

  2. application/x-www-form-urlencoded 提交的表单数据会转换为键值对并按照key1=val&key2=val2的方式进行编码,常见于POST提交表单以及原生的处理方式。

  3. multipart/form-data 多媒体类型 多用于上传图片文件等 以boundary作为分隔。

  4. text/xml 以xml的格式传输数据 多用于文本传输

Koa-body 原理解析:

  1.  核心主要依赖于co-body 做上述4种不同的数据格式的转换。
  2.   通过patchNodeAndKoa 进行不同数据格式的判断。最终返回响应体。
  1 import { KoaBodyMiddlewareOptionsSchema } from './types';
  2 import type { KoaBodyMiddlewareOptions } from './types';
  3 import type { Context, Middleware, Next } from 'koa';
  4 import * as Koa from 'koa';
  5 import type { Files } from 'formidable';
  6 import coBody from 'co-body';
  7 import toHttpMethod from './utils/string-method-to-enum-method';
  8 import throwableToError from './utils/throwable-to-error';
  9 import { isJsonBody, isMultipartBody, isTextBody, isUrlencodedBody } from './utils/body-type-util';
 10 import parseWithFormidable from './utils/parse-with-formidable';
 11 import { patchNodeAndKoa } from './utils/patch-util';
 12 import type { ContextWithBodyAndFiles } from './utils/patch-util';
 13 
 14 export * from './types';
 15 
 16 declare module 'koa' {
 17   interface Request extends Koa.BaseRequest {
 18     body?: any;
 19     files?: Files;
 20   }
 21 }
 22 
 23 export function koaBody(options: Partial<KoaBodyMiddlewareOptions> = {}): Middleware {
 24   const validatedOptions = KoaBodyMiddlewareOptionsSchema.parse(options);
 25   const optionsToUse = { ...options, ...validatedOptions };
 26   return async (ctx: Context, next: Next) => {
 27     const isJson = isJsonBody(ctx, optionsToUse);
 28     const isText = isTextBody(ctx, optionsToUse);
 29     const isUrlencoded = isUrlencodedBody(ctx, optionsToUse);
 30     const isMultipart = isMultipartBody(ctx, optionsToUse);
 31     const {
 32       encoding,
 33       jsonStrict,
 34       jsonLimit,
 35       includeUnparsed: returnRawBody,
 36       formLimit,
 37       textLimit,
 38       queryString,
 39       formidable,
 40       one rror,
 41       patchNode,
 42       patchKoa,
 43     } = optionsToUse;
 44     // only parse the body on specifically chosen methods 只解析body中指定的请求方法
 45     if (validatedOptions.parsedMethods.includes(toHttpMethod(ctx.method.toUpperCase()))) {
 46       try {
 47         if (isJson) { // application/json 数据格式
 48           const jsonBody = await coBody.json(ctx, {
 49             encoding,
 50             limit: jsonLimit,
 51             strict: jsonStrict,
 52             returnRawBody,
 53           });
 54           patchNodeAndKoa(ctx as ContextWithBodyAndFiles, jsonBody, {
 55             isText,
 56             includeUnparsed: returnRawBody,
 57             isMultipart,
 58             patchKoa,
 59             patchNode,
 60           });
 61         } else if (isUrlencoded) { // urlencode数据格式 key=value value默认编码 get和post请求都可使用
 62           const urlEncodedBody = await coBody.form(ctx, {
 63             encoding,
 64             limit: formLimit,
 65             queryString: queryString,
 66             returnRawBody,
 67           });
 68           patchNodeAndKoa(ctx as ContextWithBodyAndFiles, urlEncodedBody, {
 69             isText,
 70             includeUnparsed: returnRawBody,
 71             isMultipart,
 72             patchKoa,
 73             patchNode,
 74           });
 75         } else if (isText) { // 文本数据格式
 76           const textBody = await coBody.text(ctx, {
 77             encoding,
 78             limit: textLimit,
 79             returnRawBody,
 80           });
 81           patchNodeAndKoa(ctx as ContextWithBodyAndFiles, textBody, {
 82             isText,
 83             includeUnparsed: returnRawBody,
 84             isMultipart,
 85             patchKoa,
 86             patchNode,
 87           });
 88         } else if (isMultipart) { // 多媒体数据格式 
 89           const multipartBody = await parseWithFormidable(ctx, formidable || {});
 90           patchNodeAndKoa(ctx as ContextWithBodyAndFiles, multipartBody, {
 91             isText,
 92             includeUnparsed: returnRawBody,
 93             isMultipart,
 94             patchKoa,
 95             patchNode,
 96           });
 97         }
 98       } catch (parsingError) {
 99         const error = throwableToError(parsingError);
100         if (typeof one rror === 'function') {
101           one rror(error, ctx);
102         } else {
103           throw error;
104         }
105       }
106     } else { // 处理未指定的请求方法
107       patchNodeAndKoa(
108         ctx as ContextWithBodyAndFiles,
109         {},
110         {
111           isText,
112           includeUnparsed: returnRawBody,
113           isMultipart,
114           patchKoa,
115           patchNode,
116         },
117       );
118     }
119 
120     return next();
121   };
122 }
123 
124 export default koaBody;
 1 export function patchNodeAndKoa(ctx: ContextWithBodyAndFiles, body: any, options: PatchOptions) {
 2   const { patchKoa, patchNode, isMultipart, includeUnparsed, isText } = options;
 3  // 请求放置在Node
 4   if (patchNode) {
 5     if (isMultipart) {
 6       ctx.req.body = body.fields;
 7       ctx.req.files = body.files;
 8     } else if (includeUnparsed) {
 9       ctx.req.body = body.parsed || {};
10       if (!isText) {
11         ctx.req.body[symbolUnparsed] = body.raw;
12       }
13     } else {
14       ctx.req.body = body;
15     }
16   }
17   if (patchKoa) { // 请求放置在Koa
18     if (isMultipart) {
19       ctx.request.body = body.fields;
20       ctx.request.files = body.files;
21     } else if (includeUnparsed) {
22       ctx.request.body = body.parsed || {};
23       if (!isText) {
24         ctx.request.body[symbolUnparsed] = body.raw;
25       }
26     } else {
27       ctx.request.body = body;
28     }
29   }
30 }

 

标签:body,isText,const,koa,ctx,中间件,isMultipart,import
From: https://www.cnblogs.com/taue997/p/17403134.html

相关文章

  • cookie和session、Django中间件
    cookie和session、Django中间件cookie和session简介http的五大特性:1.基于请求响应2.基于tcp和ip作用于应用层之上的协议3.无状态 服务端无法识别客户端的状态(互联网刚开始兴起的的时候所有人访问网址都是一样的数据,服务端记不住客户端的状态,服务端不得不想办法记住客......
  • cuda nbody实验
    1并行化非常简单得,直接分配4096线程处理,每个线程处理一个天体。每个kernel函数中的循环,就去全局变量里面找其他点的信息,进行计算就好了2优化2.1共享内存按1中的,是每个线程处理n个,这里的话,每个线程分批次处理,每次处理一部分。引入共享内存。......
  • Centos环境下部分中间件“rabbitmq、rocketmq、clickhouse”部署
    部分中间件部署目录部分中间件部署docker部署rabbitmqdocker部署rocketmq单机部署clickhousedocker部署rabbitmq#拉镜像dockerpullrabbitmq:3.8-management#启动dockerrun\-eRABBITMQ_DEFAULT_USER=guest\-eRABBITMQ_DEFAULT_PASS=guest\-v/data/rabbitmq/ra......
  • Django高级之-中间件
    目录一什么是中间件二中间件有什么用七个中间件中间件中的方法三自定义中间件process_request和process_responseprocess_viewprocess_exceptionprocess_template_response四中间件应用场景1、做IP访问频率限制2、URL访问过滤五CSRF_TOKEN跨站请求伪造背景信息form表单中如何......
  • 【nodejs基础】Express、路由、中间件详解04
    一、Express简介Express是基于Node.js平台,快速、开放、极简的Web开发框架通俗的理解:Express的作用和Node.js内置的http模块类似,是专门用来创建Web服务器的。本质就是一个npm上的第三方包,提供了快速创建Web服务器的便捷方法中文官网http://www.expressjs.com.cn......
  • 中间件
    中间件一、中间件介绍官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。但是由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。说......
  • WEB中间件常见漏洞总结
    WEB中间件常见漏洞总结什么是WEB中间件是一类提供系统软件和应用软件之间的连接,便于软件各部件之间的沟通的软件,应用软件可以借助中间件在不同的技术架构之间共享信息和资源。中间件位于客户机服务器的操作系统之上,管理着计算资源和网络通信。中间件=平台+通信一、IIS中间件1......
  • Django操作session和中间件以及csrf跨站服务
    Django操作session#cookie保存在浏览器,数据不安全session可以将用户信息保存在服务端,基于cookie工作的1.用户信息认证2.生成随机字符串3.随机字符串和用户信息绑定一起,保存,默认在mysql4.把随机字符串返回到浏览器,将其保存,再次访问直接带其一起传输至服务端,服务端用其进......
  • 使用 @ResponseBody 注解直接返回json字符串结果中文出现乱码
    在类上直接使用@RestController,这样子,里面所有的方法都只会返回json字符串了,不用再每一个都添加@ResponseBody!我们在前后端分离开发中,一般都使用@RestController,十分便捷!@RestControllerpublicclassUserController{//produces:指定响应体返回类型和编码@Request......
  • Django框架——cookie与session简介、django操作cookie与session、django中间件
    cookie与session简介"""回忆:HTTP协议四大特性 1.基于请求响应 2.基于TCP、IP作用于应用层之上的协议 3.无状态 不保存客户端的状态 4.无连接"""最开始的网站都不需要用户注册所有人来访问获取到的数据都是一样的随着互联网的发展很多网站需要指定当前用户的状态cook......