ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Web-Dev-For-Beginners 银行项目实战:Node.js + Express 打造的 Bank API 运行、六条 REST 路由与源码级解析

Web-Dev-For-Beginners 银行项目实战:Node.js + Express 打造的 Bank API 运行、六条 REST 路由与源码级解析 Web-Dev-For-Beginners 银行项目实战Node.js Express 打造的 Bank API 运行、六条 REST 路由与源码级解析【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners本篇技术指南聚焦微软开源教程 Web-Dev-For-Beginners 第 7 大模块「Build a Bank」配套的后端服务Bank API位于 7-bank-project/api。该 API 由 Node.js Express 编写是银行课程前端各课时模板路由、登录注册表单、数据获取、状态管理共享的数据源。阅读本文后你将掌握 Bank API 的完整启动方式、全部 REST 端点与请求/响应结构并能对照 server.js 源码理解每个端点的校验逻辑、幂等策略与内存存储实现。在 7-bank-project 这套虚构银行应用课程中前端的登录、注册、余额展示与交易录入都围绕账户account与交易transaction这两类数据展开。Bank API 正是为这些前端能力提供数据服务的后端课程的设计理念是——API 已经替你写好它不是课程练习的一部分学习者的重心放在纯前端课程模板路由、表单、数据获取与状态管理上只需把 API 跑起来作为数据源使用。不过对如何用 Express 从零搭一个这样的 API感兴趣的读者官方也提供了配套的 Node.js 视频系列其中第 1721 集完整讲解本项目 API以及交互式 Express API 教程可供延伸学习。Bank API 在银行项目中的定位先厘清这份 API 文档所属的整体工程上下文。仓库中 7-bank-project/README.md 将银行项目划分为四个课时HTML Templates and Routes in a Web AppBuild a Login and Registration FormMethods of Fetching and Using DataConcepts of State Management其中课时 3 的核心实操就是启动 API 服务器并用浏览器的fetch向http://localhost:5000/api发起请求读取/写入账户数据例如fetch(//localhost:5000/api/accounts/ user)足以看出 Bank API 是支撑整套课程前端能力的关键后端组件。从工程目录看API 是一个完全独立的 Node.js 应用有自己的依赖清单与启动脚本入口实现7-bank-project/api/server.js依赖与脚本声明7-bank-project/api/package.jsonREST 客户端示例VS Code REST Client 插件可直接执行7-bank-project/api/api.http英文原版 API 文档7-bank-project/api/README.md环境要求与启动服务器前置条件运行 Bank API 的唯一硬性前提是本地已安装 Node.js。根据 package.json 的声明运行环境要求node 10同时声明的运行时依赖为dependencies: { body-parser: ^1.20.3, cors: ^2.8.5, express: ^4.21.2 }开发依赖还包含eslintnpm run lint执行与prettiernpm run format执行用于代码风格检查与格式化。三步启动文档给出的启动流程非常简洁共三步通过git clone克隆当前 Web-Dev-For-Beginners 仓库在终端中进入7-bank-project/api目录执行npm install安装依赖等待时间取决于网络状况安装完成后执行npm start启动服务。npm start实际执行的命令定义在 package.json 的scripts字段中scripts: { start: node server.js, lint: eslint, format: prettier --single-quote --write *.js }即直接以node server.js运行入口文件。启动成功后控制台会打印Server listening on port 5000服务器默认监听5000端口。两个值得注意的运行细节从源码中可以确认两点超出文档字面描述的关键信息端口可用环境变量覆盖。server.js 第 8 行声明const port process.env.PORT || 5000;也就是说默认 5000 只是一个兜底值如需换端口可执行PORT3001 npm start。但教学配套代码如课时 3 的fetch示例与 api.http都写死了 5000 端口因此按默认配置运行最稳妥。数据只存在内存中绝不持久化。文档特别强调所有记录账户与交易都保存在内存中一旦服务器停止全部数据将丢失重启后回到初始状态。原因同样在源码中——server.js 直接用一个内存对象db充当数据库源码注释也写明Store data in-memory, not suited for production use!。因此 Bank API 只适合教学演示不能用于生产环境。API 端点总览文档用一张表格完整列出了 Bank API 的六条路由覆盖了账户与交易的增删查全部操作。结合 server.js 中实际的router定义所有路由都挂载在/api前缀之下汇总如下方法路由说明GET/api/获取服务器信息POST/api/accounts/创建账户例如{ user: Giovanni, description: Il mio budget, currency: EUR, balance: 100 }GET/api/accounts/:user获取指定账户的全部数据DELETE/api/accounts/:user删除指定账户POST/api/accounts/:user/transactions添加一笔交易例如{ date: 2020-07-23T18:25:43.511Z, object: Acquistato un libro, amount: -20 }DELETE/api/accounts/:user/transactions/:id删除指定交易需要说明的是原文表格中个别行存在笔误如/api/account/:user/transactions少了一个s。上表与下方详解均以 server.js 中的实际路由为准——源码里全部是复数形式accounts。为方便阅读下文按功能把它们拆成账户操作与交易操作两组逐一讲解请求体约束、校验规则与响应状态码。这些都是源码里真实存在的逻辑对照 server.js 可直接验证。账户操作创建、查询与删除服务器信息GET /api/路由处理器在 server.jsrouter.get(/, (req, res) { return res.send(${pkg.description} v${pkg.version}); });它读取 package.json 中声明的descriptionBank API与version1.0.0以纯文本返回Bank API v1.0.0。这条路由常被当作服务器是否存活的健康检查——课时 3 就先用curl http://localhost:5000/api验证 API 已成功启动。创建账户POST /api/accounts/创建账户的完整处理逻辑位于 server.js包含如下校验阶梯必填参数检查user用户名与currency货币二者缺一即返回400 Bad Request响应体为{ error: Missing parameters }重名检查若db中已存在同名用户返回409 Conflict响应体为{ error: User already exists }余额类型容错balance若存在但不是数字会尝试parseFloat(balance)转换转换结果若为NaN返回400与{ error: Balance must be a number }字段默认值description缺省时自动生成users budgetbalance缺省为0transactions初始为空数组[]。创建成功返回201 Created与完整账户对象。原文示例创建一个名为 Giovanni、币种 EUR、余额 100 的账户{ user: Giovanni, description: Il mio budget, currency: EUR, balance: 100 }对应响应201大致为{ user: Giovanni, currency: EUR, description: Il mio budget, balance: 100, transactions: [] }获取账户GET /api/accounts/:user处理器见 server.js按路径参数:user从内存对象db中查找账户找到则返回完整账户数据含transactions数组不存在则返回404 Not Found与{ error: User does not exist }。由于服务器启动时已在内存中预置了一个名为test的测试账户见 server.js你甚至不需要先创建任何账户就可以立刻体验查询能力——课时 3 正是用curl http://localhost:5000/api/accounts/test来演示数据获取的。该预置账户内容为用户test、货币符号$、余额 75并含三笔预置交易db { test: { user: test, currency: $, description: Test account, balance: 75, transactions: [ { id: 1, date: 2020-10-01, object: Pocket money, amount: 50 }, { id: 2, date: 2020-10-03, object: Book, amount: -10 }, { id: 3, date: 2020-10-04, object: Sandwich, amount: -5 } ] } };删除账户DELETE /api/accounts/:user处理器见 server.js账户不存在时返回404与错误对象存在则执行delete db[req.params.user]将其从内存中移除并返回204 No Content无响应体。交易操作添加与删除添加交易POST /api/accounts/:user/transactions这是业务上最核心的端点处理逻辑位于 server.js它同时完成了记账与更新余额两件事账户存在性检查目标账户不存在则返回404 { error: User does not exist }必填字段检查date日期、object交易说明、amount金额三者缺一即返回400 { error: Missing parameters }。需要注意一个源码细节金额为0时!req.body.amount判定为真同样会被当作缺少参数拒绝金额容错amount不是数字时尝试parseFloat转换结果若为NaN返回400 { error: Amount must be a number }。文档示例中的-20表示支出负数扣减余额交易 ID 由内容哈希生成这是该端点最有意思的实现——交易 ID 并非自增或随机数而是对date object amount拼接字符串取MD5const id crypto .createHash(md5) .update(req.body.date req.body.object req.body.amount) .digest(hex);重复交易拦截由于 ID 由内容决定完全相同的三要素组合会算出相同的 ID若账户中已存在该 ID返回409 { error: Transaction already exists }从而天然实现同一笔交易不能重复提交的幂等保护记账与余额更新交易对象{ id, date, object, amount }被push进账户的transactions数组同时执行account.balance transaction.amount累加余额成功返回201 Created与交易对象含自动生成的id。原文给出的添加交易示例支出 20购买图书{ date: 2020-07-23T18:25:43.511Z, object: Acquistato un libro, amount: -20 }这里date采用的是 ISO 8601 时间戳格式如2020-07-23T18:25:43.511Z。删除交易DELETE /api/accounts/:user/transactions/:id处理器见 server.js先确认账户存在否则404再用findIndex按:id定位交易找不到返回404 { error: Transaction does not exist }找到则执行splice移除并返回204 No Content。源码层面的两个补充事实因为添加交易时返回的id是 MD5 哈希串删除时直接复用该id即可。仓库自带的 api.http 就演示了完整流程先 POST 一笔{ date: 2020-07-24, object: Bought book, amount: -20 }得到哈希 ID再用DELETE /api/accounts/sinedied/transactions/8825ff3e...删除它删除交易不会回滚余额——balance只在添加交易时被累加删除分支只做了splice没有反向balance - amount的操作。如果你在真实场景中想要删除即冲正需要在调用侧自行补做处理。中间件与服务器骨架要让以上路由真正可调用还需理解 server.js 中的三个中间件与整体装配方式这也能解释为什么各种请求格式都能被正确解析const app express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(cors({ origin: /http:\/\/(127(\.\d){3}|localhost)/ })); app.options(*, cors());bodyParser.urlencoded({ extended: true })支持解析表单格式application/x-www-form-urlencoded的请求体。仓库中的 api.http 在创建账户时特意用了这种格式POST http://localhost:5000/api/accounts/ Content-Type: application/x-www-form-urlencoded usersinediedcurrency$balance50bodyParser.json()支持解析application/json请求体——文档中的账户/交易示例与前端fetch调用都以 JSON 形式发送数据因此两个解析器缺一不可cors({ origin: /http:\/\/(127(\.\d){3}|localhost)/ })开启跨域资源共享但把允许的来源限定为localhost及127.x.x.x形式的本机地址。这正是银行前端页面在另一个端口/静态服务器上运行时仍能直接向 5000 端口 API 发起浏览器跨域请求的前提。app.options(*, cors())则用于响应浏览器发送的 CORS 预检请求。路由装配与启动收尾在文件末尾完成// Add api prefix to all routes app.use(apiPrefix, router); // Start the server app.listen(port, () { console.log(Server listening on port ${port}); });其中apiPrefix /apiserver.js因此所有router上定义的路由最终都以/api开头对外暴露与文档路由表一一对应。命令行快速实测启动服务器后可以用curl直接验证每个端点。下面是一组可与源码逐行对证的完整操作序列仅示意命令账户数据会随服务器重启而清空# 1) 健康检查返回 Bank API v1.0.0 curl http://localhost:5000/api # 2) 读取预置的 test 账户无需先创建服务器自带种子数据 curl http://localhost:5000/api/accounts/test # 3) 创建账户JSON 方式 curl -X POST http://localhost:5000/api/accounts/ \ -H Content-Type: application/json \ -d {user: Giovanni, description: Il mio budget, currency: EUR, balance: 100} # 4) 为账户添加一笔支出交易-20 表示支出 curl -X POST http://localhost:5000/api/accounts/Giovanni/transactions \ -H Content-Type: application/json \ -d {date: 2020-07-23T18:25:43.511Z, object: Bought a book, amount: -20} # 5) 查询账户确认余额已被自动更新为 80 curl http://localhost:5000/api/accounts/Giovanni # 6) 删除某笔交易:id 替换为第 4 步返回的 id curl -X DELETE http://localhost:5000/api/accounts/Giovanni/transactions/id如果你使用 VS Code 并安装了 REST Client 扩展也可以直接打开 7-bank-project/api/api.http 文件点击每个###分隔的请求块上方的 Send Request用图形化方式完成同样的增删查验证。与前端课程代码的配合方式Bank API 的价值最终体现在它与银行前端模块的对接上课时 3「Methods of Fetching and Using Data」(7-bank-project/3-data/README.md) 将启动 API 服务器并测试连通性作为前置步骤curl http://localhost:5000/api随后用fetch(//localhost:5000/api/accounts/ encodeURIComponent(user))编写真实的getAccount()异步数据获取函数并把返回的账户 JSON 渲染到页面。该课时的作业7-bank-project/3-data/assignment.md中也以const API_BASE_URL http://localhost:5000/api;作为扩展练习的基准地址完整版前端解决方案7-bank-project/solution/app.js顶部保留了一行const serverUrl http://localhost:5000/api; // reserved for future server swap。从源码结构看该方案为了便于离线运行当前版本用 localStorage 模拟了 API 行为并把这行真实 API 地址预留作未来无缝切换真实后端的接口课程学习者参照课时 3/4 的引导即可自己动手把这一行注释真正变成可用的数据链路。换言之Bank API 在本课程中扮演的是教学数据源 真实后端蓝本双重角色运行期它是前端练习可直接请求的服务源码层面它又是一份体积小巧、适合逐行精读的 Express 教学样本。使用注意与限制最后把实践中最容易踩的坑集中说明如下数据不持久所有账户与交易存于内存db对象服务器重启即全部丢失并恢复为预置的test账户初始状态切勿在上面存放任何真实业务数据端口约定服务默认监听 5000虽可用PORT环境变量覆盖但课程全部前端示例与 api.http 均按 5000 编写改动端口需同步调整调用方CORS 限定本机浏览器跨域白名单只包含localhost与127.x.x.x这意味着该 API 的设计场景就是纯本地开发教学无法直接对接远程部署的页面金额校验语义amount为0会被判定为缺参400而balance为0则是合法的默认值——两者校验口径不同来自源码实现调用时需留意无身份认证整个 API 没有任何登录/鉴权机制账户名即全部访问凭据。这是因为 2-forms 课时 讲解的前端登录仅为本地 UI 状态模拟与真正安全的用户体系无关本 API 仅供课程教学使用。总而言之Bank API 用约 200 行 Express 代码演示了一个小型 REST 服务从中间件配置、路由组织、请求校验到状态维护的完整写法。对照 server.js 通读一遍再配合 api.http 逐个端点实测你便能同时吃透如何使用它支撑银行前端课程与如何用 Node.js 自建同款 API这两个层次的问题。【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表