# 手写nestjs框架 **Repository Path**: 1160/handwritten-nestjs-framework ## Basic Information - **Project Name**: 手写nestjs框架 - **Description**: 就是简单学习一下 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-11 - **Last Updated**: 2025-12-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 本工程是用来手动实现 nestj 是框架的 ## Nest 的依赖包 - @nestjs/core Nest.js 核心模块,提供构建、启动和管理 Nest.js 应用程序的基础设施 - @nestjs/common 包含了构建 Nest.js 应用程序基础设施和常用装饰器,像控制器、服务、中间件、守卫、拦截器、管道、异常过滤器等 - rxjs 用于构建异步和事件驱动程序的库。 - reflect-metadata 实现元编程的库,提供元数据反射 API,可以在运行时检查和操作对象的元数据 - @nestjs/platform-express Nest 的 Express 平台适配器,提供中间件、路由等功能 ## 启动路径 - nodemon.json 中的 ``` "exec": "ts-node -r tsconfig-paths/register ./src/main.ts" ``` 这里是和 tsconfig.json 中的 ``` "paths": { "@nestjs/*": ["src/@nestjs/*"] } ``` 配置一致,这样 ts-node 就可以识别 @nestjs/core 等模块了 ## 注意 - 注意!服务器这里会死机。更换了端口,并且清理了所有的 async/await,就能够得到需要的数据。 - 请看 **nest-application.ts** ## headers 和 accept - headers: 告诉服务器,我正在使用什么格式的数据,比如 application/json - accept: 告诉服务器,我正在接受什么格式的数据,比如 application/json ### 想象你去一家餐厅点餐: - **HTTP 请求** 就像是你向服务员点菜。 - **Headers(请求头)** 就像是你点菜时附带的一些“额外要求”或“说明”,比如: - “我不能吃辣”(用户身份、偏好) - “我要打包带走”(客户端类型) - “我预约了 8 点的位置”(认证信息) - “这是我的会员卡号”(授权令牌) 这些信息不是你点的“主菜”(也就是请求的主体 body),但对服务员(服务器)处理你的请求非常重要。 --- 而 **Accept** 是 Headers 中的一个特定字段,它的作用是告诉服务器: > “我(客户端)希望你返回什么格式的数据。” 比如: - `Accept: text/html` → “请给我网页(HTML)” - `Accept: application/json` → “请给我 JSON 格式的数据,比如 API 接口常用的那种” - `Accept: image/*` → “可以给我任何类型的图片” 这就像你在点餐时说:“我只要甜点,不要主食。” 服务器看到后,会尽量按你的要求返回合适格式的内容。 --- 总结一下: - **Headers**:请求的附加信息,用于传递身份、格式偏好、认证等。 - **Accept**:Headers 中的一项,专门用来告诉服务器“我希望你返回什么类型的数据”。 ## headers 中的 session **Session 的标识(通常是 Session ID)是包含在 HTTP 请求的 Headers 中的**,但 **Session 本身(即数据)并不在 Headers 里**。 我们来分开说清楚: --- ### ✅ 1. **Session ID 通常放在 Headers 里(通过 Cookie)** 当你第一次访问网站,服务器创建 Session 后,会通过响应头(Response Headers)返回一个 Cookie,例如: ```http Set-Cookie: sessionId=abc123xyz; Path=/; HttpOnly ``` 之后,你的浏览器**每次发请求**,都会自动把这个 Cookie 放到请求头(Request Headers)里: ```http Cookie: sessionId=abc124xyz ``` 这个 `Cookie` 字段就是 **Headers 的一部分**,里面包含了 Session ID。 > 所以:**Session ID 是通过 Headers(Cookie)传递的**。 --- ### ❌ 2. **Session 的实际数据(比如用户名、购物车)不在 Headers 里** - 那些真正的用户数据(比如 `userId=1001`, `isLoggedIn=true`)是**存在服务器上的**(比如内存、Redis、数据库)。 - 浏览器**只保存一个 ID**,不保存具体内容。 - 服务器收到 ID 后,自己去查:“哦,ID=abc123xyz 对应的是张三,已登录。” > 所以:**Session 内容 ≠ Headers,只有 Session 的“钥匙”(ID)在 Headers 里。** --- ### 🔁 类比再回顾: - 你去健身房,前台给你一张**手环(ID)** → 这个手环相当于 Cookie,每次进门都要出示(放在请求 Headers 里)。 - 你的**真实信息**(姓名、会员等级、剩余次数)存在**前台电脑里(服务器)**,不在手环上。 --- ### 💡 小知识:也有不用 Cookie 传 Session ID 的方式 虽然最常见的是用 Cookie,但有些 API 会把 Session ID 放在: - URL 参数里(不推荐,不安全) 比如:`/api/profile?sessionid=abc123` - 请求体(Body)里(少见) - 自定义 Header 里(比如 `X-Session-ID: abc123`) 但**标准、主流的做法还是通过 Cookie 放在 Headers 里**。 --- ✅ 总结: > **Session ID 通常包含在 HTTP 请求的 Headers 中(通过 Cookie 字段),但 Session 的实际数据存储在服务器上,不在 Headers 里。** - 代码片段 ```typescript @Get("session") handlerSession(@Session() session: any, @Session("pageView") pageView: string) { console.log("session", session); // 会话 if(session.pageView){ // 第一次请求,是没有pageView的 session.pageView++; }else{ session.pageView = 1; } return `pageView: ${pageView}` } ``` ## 动态路由或者参数化路由 ```typescript @Get(":username/info/:age") getUserNameInfo(@Param() param: any,@Param("username") username: string,@Param("age") age: number) { console.log("param", param); console.log("username", username); console.log("age", age); return `username: ${username} age: ${age}`; } ``` - 浏览器请求 ```bash http://localhost:3000/zhangsan/info/18 ``` - 就能拿到 username 和 age 了。 ## 如果是使用路由通配符 - 例如: ```typescript @Get("ab*de") handleWildcard() { return "handleWildcard"; } ``` - 浏览器请求 ```bash http://localhost:4501/user/abcde ``` 需要修改 **nest-application.ts** 中的 **resolveParams()** 函数的 ```typescript const paramsMetadataOfMethod: ParamMetadata[] = Reflect.getMetadata(paramsSymbol, instance, methodName) ?? []; ``` - 这里注意使用 **??** - typescript 3.7 新增的语法,表示如果左边的值为 null 或者 undefined,则返回右边的值。 - 如果是 **||**,那么 0、""、false、null、undefined 都会返回 **false**。