ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Midway Hooks 接口开发实战:从 Api() 路由到请求/响应全流程

Midway Hooks 接口开发实战:从 Api() 路由到请求/响应全流程 后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载本篇技术指南聚焦 Midway Hooks 的函数式接口开发能力如何用Api()快速定义 HTTP 接口、如何通过useContext获取请求上下文以及 Query / Params / Headers 等四种入参传递方式和 HttpCode / SetHeader / Redirect / ContentType 四种响应控制手段。读完本文你将掌握在 Midway全栈或纯后端项目中以“函数即接口”的方式完成路由声明、参数校验、响应定制与全栈零 API 调用的完整实战方案并能结合本仓库源码理解其底层元数据与路由注册机制。接口与路由用 Api() 定义一个 HTTP 接口在 Midway Hooks 中接口开发不再需要编写 Controller 类而是通过midwayjs/hooks提供的Api()函数把一段普通的异步函数直接升级为 HTTP 接口。一个 API 接口由三个部分组成Api()定义接口函数是函数式路由的入口Get(path?: string)等触发器指定 HTTP 请求方法可选参数path指定接口路径。不指定路径时会根据「函数名 文件名」自动生成路径并默认带有/api前缀Handler: async (...args: any[]) { ... }用户业务逻辑处理请求并返回结果返回值会被序列化后写入 HTTP 响应。最简单的 Hello World 示例默认路径/api/helloimport { Api, Get, } from midwayjs/hooks; export default Api( Get(), // Http Path: /api/hello, async () { return Hello World!; } );你也可以通过触发器的path参数显式指定路径import { Api, Get, } from midwayjs/hooks; export default Api( Get(/hello), // Http Path: /hello, async () { return Hello World!; } );从本仓库源码来看这套函数式能力的底层实现位于 packages/core/src/decorator/web/requestMapping.tsGet、Post等触发器本质上是createMappingDecorator(method)生成的 MethodDecorator最终会把{ path, requestMethod, routerName, middleware }等元数据通过MetadataManager.attachMetadata(WEB_ROUTER_KEY, routerMeta, target)挂载到目标上见 requestMapping.ts。支持的请求方法枚举定义在同一个文件的RequestMethod对象中export const RequestMethod { GET: get, POST: post, PUT: put, DELETE: delete, PATCH: patch, ALL: all, OPTIONS: options, HEAD: head, };Http 触发器8 种请求方法映射Midway Hooks 为每一种 HTTP 方法提供了对应的触发器声明方式完全一致均为触发器(path?: string)触发器注释All(path?: string)接受所有 Http Method 的请求Get(path?: string)接受 GET 请求Post(path?: string)接受 POST 请求Put(path?: string)接受 PUT 请求Delete(path?: string)接受 DELETE 请求Patch(path?: string)接受 PATCH 请求Head(path?: string)接受 HEAD 请求Options(path?: string)接受 OPTIONS 请求在底层实现中这些触发器均出自同一工厂函数createMappingDecorator(method)见 requestMapping.ts。需要注意一个命名差异Hooks 对外暴露的触发器名为Delete而 core 包中的装饰器导出名是Del源码见 requestMapping.ts两者指向同一能力使用时以对应包的实际导出为准。请求上下文useContext 获取 Context 对象接口处理函数内部可以通过midwayjs/hooks提供的useContext获取当前请求的上下文对象。以 Koa 框架为例useContext返回的就是 Koa 的 Context 对象包含ctx.request、ctx.response、ctx.query、ctx.params、ctx.headers、ctx.status、ctx.set()、ctx.redirect()等标准成员。基础示例一获取请求 Method 和 Pathimport { Api, Get, useContext, } from midwayjs/hooks; import { Context } from midwayjs/koa; export default Api(Get(), async () { const ctx useContextContext(); return { method: ctx.method, path: ctx.path, }; });基础示例二在响应中设置 Headerimport { Api, Get, useContext, } from midwayjs/hooks; export default Api(Get(), async () { const ctx useContextContext(); ctx.set(X-Powered-By, Midway); return Hello World!; });除了设置 Header你还可以通过SetHeader()声明式地完成同一件事详见下文「响应头 SetHeader」。从源码层面看useContext的实现位于 packages/core/src/functional/hooks.ts它从当前的异步上下文管理器Async Context中读取ASYNC_CONTEXT_KEY对应的值并返回因此无论调用栈有多深只要处于该请求的处理链路内都能拿到同一个 Context 对象。同一个文件还提供了useLogger、useConfig、useInject、useInjectSync、useApp、useMainApp、useInjectDataSource等一系列函数式 Hook见 hooks.ts分别用于获取日志器、配置、依赖注入对象、应用实例与数据源等可作为接口开发中的常用辅助。请求入参四种数据传递方式Midway Hooks 的入参设计非常直观接口的入参就是声明函数的参数并根据数据来源分为 Body、Query、Params、Headers 四种方式。传递参数 Data函数入参 / Body接口的入参直接声明为函数参数例如import { Api, Post, } from midwayjs/hooks; export default Api( Post(), // Http Path: /api/say, async (name: string) { return Hello ${name}!; } );调用该接口有两种方式方式一全栈项目中的「零 Api」调用——直接导入接口函数并调用import say from ./api; const response await say(Midway); console.log(response); // Hello Midway!方式二手动调用——通过 fetch 在 HTTP 层请求Handler(...args: any[])的入参通过请求体中的args字段传递fetch(/api/say, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify({ args: [Midway], }), }) .then((res) res.text()) .then((res) console.log(res)); // Hello Midway!也就是说args数组的元素顺序与函数形参一一对应这是 Hooks 在 HTTP 传输层与函数调用层之间约定的协议格式。查询参数 Query查询参数用于在 URL 上传递参数。使用该功能时必须通过QueryT声明类型。例如希望接口路径是/articles?page0limit10import { Api, Get, Query, useContext, } from midwayjs/hooks; export default Api( Get(), Query{ page: string; limit: string; }(), async () { const ctx useContext(); return { page: ctx.query.page, limit: ctx.query.limit, }; } );前端调用// 全栈应用零 Api import getArticles from ./api; const response await getArticles({ query: { page: 0, limit: 10 }, }); console.log(response); // { page: 0, limit: 10 } // 手动调用 fetch(/api/articles?page0limit10) .then((res) res.json()) .then((res) console.log(res)); // { page: 0, limit: 10 }路径参数 Params路径参数用于实现动态路径并从路径中取值。使用该功能时必须手动设置路径如/article/:id并必须通过ParamsT声明类型。例如希望接口路径是/article/100并获取 id 为100的值import { Api, Get, Params, useContext, } from midwayjs/hooks; export default Api( Get(/article/:id), Params{ id: string }(), async () { const ctx useContext(); return { article: ctx.params.id, }; } );前端调用// 全栈应用零 Api import getArticle from ./api/article; const response await getArticle({ params: { id: 100 }, }); console.log(response); // { article: 100 } // 手动调用 fetch(/article/100) .then((res) res.json()) .then((res) console.log(res)); // { article: 100 }请求头 Headers请求头用于通过 HTTP Headers 传递参数使用该功能时必须通过HeadersT声明类型。例如请求/auth并在 Request Headers 中传递 tokenimport { Api, Get, Headers, useContext, } from midwayjs/hooks; export default Api( Get(/auth), Headers{ token: string }(), async () { const ctx useContext(); return { token: ctx.headers.token, }; } );前端调用// 全栈应用零 Api import getAuth from ./api/auth; const response await getAuth({ headers: { token: 123456 }, }); console.log(response); // { token: 123456 } // 手动调用 fetch(/auth, { headers: { token: 123456, }, }) .then((res) res.json()) .then((res) console.log(res)); // { token: 123456 }从底层实现看Query、Paramscore 中名为Param、Headers均出自 packages/core/src/decorator/web/paramMapping.ts 中的createParamMapping(type)工厂最终以RouteParamTypes.QUERY / PARAM / HEADERS等类型见 paramMapping.ts注册参数元数据由路由层在请求进入时从ctx.query、ctx.params、ctx.headers等位置取值因此这些装饰器本质上是在为路由框架描述「参数从哪里取、是什么类型」的契约。响应控制四种声明式响应装饰器Midway Hooks 的响应控制同时支持「声明式装饰器」与「命令式 Context 操作」两种风格两者效果等价可根据代码风格自行选择。这些能力对应 core 包中的 packages/core/src/decorator/web/response.ts装饰器内部均通过MetadataManager.attachMetadata(WEB_RESPONSE_KEY, ...)将响应元数据重定向、状态码、响应头、内容类型挂载到目标上供路由响应阶段统一执行。状态码 HttpCode支持HttpCode(status: number)用于指定响应状态码// 声明式HttpCode import { Api, Get, HttpCode, } from midwayjs/hooks; export default Api( Get(), HttpCode(201), async () { return Hello World!; } ); // 命令式直接设置 ctx.status import { Api, Get, useContext, } from midwayjs/hooks; export default Api(Get(), async () { const ctx useContextContext(); ctx.status 201; return Hello World!; });响应头 SetHeader支持SetHeader(key: string, value: string)// 声明式SetHeader import { Api, Get, SetHeader, } from midwayjs/hooks; export default Api( Get(), SetHeader(X-Powered-By, Midway), async () { return Hello World!; } ); // 命令式ctx.set import { Api, Get, useContext, } from midwayjs/hooks; export default Api(Get(), async () { const ctx useContextContext(); ctx.set(X-Powered-By, Midway); return Hello World!; });值得一提的细节core 中的SetHeader实现见 response.ts除了支持(key, value)双参数形式外还允许直接传入一个对象SetHeader({ X-A: 1, X-B: 2 })一次性设置多个响应头适合批量场景。重定向 Redirect支持Redirect(url: string, code?: number 302)默认使用 302 状态码// 声明式Redirect import { Api, Get, Redirect, } from midwayjs/hooks; export default Api( Get(/demo), Redirect(/hello), async () {} ); // 命令式ctx.redirect import { Api, Get, useContext, } from midwayjs/hooks; export default Api( Get(/demo), async () { const ctx useContextContext(); ctx.redirect(/hello); } );从源码看Redirect的元数据会记录{ type, url, code }见 response.tscode默认值 302 与文档约定一致也可显式传入 301 等其他状态码。返回值类型 ContentType支持ContentType(type: string)用于指定响应体的 MIME 类型例如返回 HTMLimport { Api, Get, ContentType, } from midwayjs/hooks; export default Api( Get(), ContentType(text/html), async () { return h1Hello World!/h1; } );全栈零 API 调用前端直接调用后端函数上述四种入参方式中反复出现的「全栈应用零 Api」是 Midway Hooks 的核心特色之一在同一全栈项目中前端代码可以直接import后端接口函数并像调用本地函数一样调用它框架会自动完成参数序列化、HTTP 请求与返回值反序列化无需手写任何 fetch 调用。前后端通过{ params, query, body, headers }这样的结构化入参对象对接其中body即函数形参对应的args这正是 packages/core/src/functional/api.ts 中FunctionalRouteInput类型所描述的契约。若希望为函数式接口补充入参/出参的结构化校验可以继续阅读仓库中的 validate 文档。从 Api() 到 defineApi新一代函数式路由 API在本文所述Api()之外本仓库的 packages/core/src/functional/api.ts 还提供了更新的defineApi(prefix, factory, controllerOptions)函数式路由 API。它与Api()的定位一致但采用「Builder 链式」风格组织多条路由api.get(path)、api.post(path)、api.all(path)等工厂方法返回RouteBuilder可继续链式调用.input(schema)、.output(schema)、.middleware(mw)、.meta(options)后以.handle(fn)收尾见 api.ts。每条路由最终会通过RequestMapping注册进同一套 Web 路由体系并支持Controller(prefix, options)级别的ignoreGlobalPrefix、version、versionType等配置见 api.ts。如果追求更工程化的批量路由组织可以优先考虑defineApi相关变更设计可参考仓库中的 add-functional-web-routing-api 变更记录。小结与延伸阅读Midway Hooks 的接口开发可以用一句话概括用函数定义接口用装饰器声明协议用 Context 触碰底层。Api()负责把函数变为路由Get/Post/...决定请求方法Query/Params/Headers描述入参来源HttpCode/SetHeader/Redirect/ContentType定制响应行为useContext则提供了对底层框架Koa/Express 等Context 的直接访问通道。如果需要继续深入本仓库 site/docs/hooks 目录下还有一系列配套文档可供查阅hooks 简介Hooks 的整体设计理念与快速上手全栈开发前后端一体项目的工程组织方式客户端调用前端调用接口的更多细节文件路由基于文件目录自动生成路由的机制参数校验为函数式接口接入校验能力部署接口开发完成后的部署方式。同时仓库 samples/functional-api-service 与 samples/functional-api-hybrid 中提供了可直接运行的函数式接口示例工程可作为实践参考。赞分享后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载相关推荐Midway 路由与控制器Controller完全指南从装饰器到请求响应全流程Midway 路由与控制器Controller完全指南从装饰器到请求响应全流程 Midway 是一个面向 Node.js 前后端全栈场景的 Serverl后端微服务云原生国家中小学智慧教育平台电子课本下载终极指南让教育资源触手可及国家中小学智慧教育平台电子课本下载终极指南让教育资源触手可及 你是否曾为无法稳定访问国家中小学智慧教育平台的电子课本而烦恼是否需要在网络不稳定时仍能获取教学网页爬虫教育Nitro请求处理流程从接收请求到返回响应的全过程Nitro请求处理流程从接收请求到返回响应的全过程 Nitro是一个强大的开源Web服务器引擎能够创建、构建和部署通用Web服务器为Nuxt等框架提供支持后端Web框架SSR上一篇解锁AMD Ryzen超频潜能SMUDebugTool硬件调试完全指南下一篇AMD Ryzen处理器调试工具SMUDebugTool系统管理单元终极控制指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表