
Wasp 如何在 spec 中声明自定义 HTTP 端点并实现 Node 处理函数【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/waspWasp 默认通过 Operations 完成客户端与服务端交互但当你需要一个特定的 URL 方法与路径例如POST /something/special、或者需要控制具体响应格式时Operations 不再适用这时应该使用 Wasp 的api声明自定义 HTTP 端点。完成本文后你会在main.wasp.ts的 spec 中声明一个 API 端点在src/下写出对应的 NodeJS 处理函数并能从客户端代码或外部系统调用这个端点。整个流程只有两步在 Wasp spec 中用api构造器声明端点然后提供该端点的 NodeJS 实现。声明完路径后端点既可以被项目客户端通过ky包装器调用也可以被浏览器、Postman、curl等外部调用方直接访问。在 Wasp spec 中声明 APIapi构造器把一个 JS 函数绑定到一个端点。声明本身很简单但要遵循 Wasp 的 reference imports 规则main.wasp.ts引用你自己的代码时import 语句必须带with { type: ref }这告诉 Wasp 这是对你应用代码的引用而不是直接执行被导入的代码。import { api, app } from wasp.sh/spec import { fooBar } from ./src/apis with { type: ref } export default app({ // ... spec: [ api(GET, /foo/bar, fooBar), ], })api的第三个参数这里是可选配置对象还可以指定该端点可用的 Entity 列表或针对这个 API 单独覆盖中间件这些见下文各节。api支持的完整字段见文档中的 API Reference。实现 NodeJS 处理函数端点声明之后处理函数是一个接收三个参数的 NodeJS 函数reqExpress Request 对象resExpress Response 对象context由 Wasp 注入的额外上下文对象包含用户会话信息以及 Entity 信息import type { FooBar } from wasp/server/api; export const fooBar: FooBar (req, res, context) { res.set(Access-Control-Allow-Origin, *); // Example of modifying headers to override Wasp default CORS middleware. res.json({ msg: Hello, ${context.user ? registered user : stranger}! }); };TypeScript 项目有两个必须注意的点FooBar类型是 Wasp 编译器根据上面的apispec 生成的。为了让编译器生成这些类型你必须先把api加入 Wasp 文件并且保持wasp start命令处于运行状态。可以通过泛型给处理函数补充类型信息获得路径参数和响应体的完整类型安全。例如一个接收:email路径参数的GET路由import { api, app } from wasp.sh/spec import { fooBar } from ./src/apis with { type: ref } export default app({ // ... spec: [ api(GET, /foo/bar/:email, fooBar, { entities: [Task] }), ], })import { FooBar } from wasp/server/api; export const fooBar: FooBar { email: string }, // params { answer: number } // response (req, res, _context) { console.log(req.params.email); res.json({ answer: 42 }); };调用端点并验证结果端点声明与实现都完成后验证方式就是直接按你声明的方法和路径发起请求文档给出了两类调用方。外部调用假设应用运行在https://example.com你可以在浏览器、Postman、curl或其他 Web 服务中对该端点发出GET请求。响应应当是你在res.json(...)中写入的对象比如上面示例返回{msg: Hello, stranger!}。从客户端调用从wasp/client/api导入api实例。这是一个预先配置好 API 基础 URL、认证和错误处理的 ky 实例ky 是外部库Wasp 只做预配置import React, { useEffect } from react; import { api } from wasp/client/api; async function fetchCustomRoute() { const data await api.get(/foo/bar).json(); console.log(data); } export const Foo () { useEffect(() { fetchCustomRoute(); }, []); return .../; };如果你从客户端收到的响应被浏览器 CORS 策略拦截见下一节。处理客户端调用的 CORS与 Operations 不同api不走默认的中间件管道因此要从客户端使用 API必须确保 CORS 已启用。做法是在 Wasp 文件中通过apiNamespace为某个路径前缀下的所有 API 应用middlewareConfigFnimport { apiNamespace, app } from wasp.sh/spec import { apiMiddleware } from ./src/apis with { type: ref } export default app({ // ... spec: [ apiNamespace(/foo, { middlewareConfigFn: apiMiddleware }), ], })实现文件中返回默认配置即可让/foo路径下的所有 API 启用 CORSimport type { MiddlewareConfigFn } from wasp/server; export const apiMiddleware: MiddlewareConfigFn (config) { return config; };这里的机制是Wasp 为每个应用内置一套 Express 默认中间件Helmet、CORS、Morgan、express.json、express.urlencoded、cookieParserMiddlewareConfigFn接收这份Mapstring, express.RequestHandler你可以增删改其中的条目后返回。apiNamespace的中间件安装在 router 层最终等价于router.use(/foo, ...)单个api的middlewareConfigFn则是按方法安装等价于router.post(/webhook/callback, ...)这种粒度。更多中间件定制全局、按 API、按路径三种层级见 Configuring Middleware。一个文档给出的典型按 API 覆盖场景是 webhook 回调把 JSON 解析换成原始字节解析并通过auth: false关闭该端点的认证import { api, app } from wasp.sh/spec import { webhookCallback, webhookCallbackMiddlewareFn } from ./src/apis with { type: ref } export default app({ // ... spec: [ api(POST, /webhook/callback, webhookCallback, { middlewareConfigFn: webhookCallbackMiddlewareFn, auth: false, }), ], })import express from express import { type WebhookCallback } from wasp/server/api import { type MiddlewareConfigFn } from wasp/server export const webhookCallback: WebhookCallback (req, res, _context) { res.json({ msg: req.body.length }) } export const webhookCallbackMiddlewareFn: MiddlewareConfigFn (middlewareConfig) { console.log(webhookCallbackMiddlewareFn: Swap express.json for express.raw) middlewareConfig.delete(express.json) middlewareConfig.set(express.raw, express.raw({ type: */* })) return middlewareConfig }修改全局中间件会影响所有 Operations 和 API文档明确提醒要谨慎不确定时优先用按 API 或按路径的覆盖方式。在 API 中使用 Entity当端点要读写数据库资源时把 Entity 名加入apispec 的entities字段Wasp 会将其注入context参数import { api, app } from wasp.sh/spec import { fooBar } from ./src/apis with { type: ref } export default app({ // ... spec: [ api(GET, /foo/bar, fooBar, { entities: [Task] }), ], })import type { FooBar } from wasp/server/api; export const fooBar: FooBar async (req, res, context) { res.json({ count: await context.entities.Task.count() }); };context.entities.Task暴露的就是 Prisma 的prisma.taskCRUD 接口因此处理函数内可以照常使用 Prisma Client 的操作方式。参考示例与限制仓库中的 kitchen-sink 示例 展示了上述能力的组合用法api(ALL, /foo/bar, fooBar, { middlewareConfigFn, entities: [Task] })、带auth: false的api(GET, /bar/baz, barBaz, { entities: [Task] })以及apiNamespace(/bar, { middlewareConfigFn })其处理函数实现在 apis.ts例如在fooBar中检查context.user并对未登录请求返回401。需要记住的边界api端点没有useQuery之类的客户端 helper客户端统一通过wasp/client/api的api实例ky 包装器调用客户端侧 CORS 不默认启用需要按上文用apiNamespace或单 API 的middlewareConfigFn显式处理TypeScript 项目的端点类型依赖wasp start运行期间由编译器生成先声明、后写实现main.wasp.ts中引用自己的代码必须使用with { type: ref }的 reference import且 reference import 不支持 re-export 和 namespace importimport * as见 spec 文档。完整字段说明与流式响应如res.write()分块推送 LLM 输出的写法可继续查阅 Custom HTTP API Endpoints 原文。【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考