Wasp 自定义 HTTP API 端点(api 声明)完整实战指南:路由、认证、中间件与实体注入

发布时间:2026/11/5 22:58:42

Wasp 自定义 HTTP API 端点(api 声明)完整实战指南:路由、认证、中间件与实体注入 Wasp 自定义 HTTP API 端点api 声明完整实战指南路由、认证、中间件与实体注入【免费下载链接】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本篇指南围绕 Wasp当前仓库为GitHub_Trending/wa/wasp中通过api声明创建自定义 HTTP API 端点的完整流程展开。你将掌握在.wasp文件中声明 API、用 Express 风格的 NodeJS 函数实现它、从客户端或外部调用它、通过apiNamespace与middlewareConfigFn精确控制 CORS 与中间件、在context中注入实体与用户会话信息的全部细节。读完即可在 Wasp 项目中写出可复用的自定义 REST 端点包括流式响应场景。Wasp 默认的客户端—服务端交互机制是 Operationsquery/action详见 Operations 概览。但当你需要特定的 URL 方法/路径组合、特定的响应格式或需要完全掌控一个端点的行为时Operations 就不再合适。此时你应当使用api声明——它把一段 JS/TS 函数绑定到形如POST /something/special的 HTTP 端点上。与 Operations 不同api没有任何客户端辅助函数如useQuery但它仍然可以像普通 Express 路由一样被浏览器、curl、Postman 或任意 Web 服务直接调用也能通过 Wasp 提供的 HTTP 客户端从你自己的前端调用。如何创建一个 API创建一个 Wasp API 只需要两步在 Wasp 文件中用api声明描述这个端点编写它的 NodeJS 实现函数。完成这两步后你就可以从客户端代码通过 Wasp 的 HTTP 客户端包装器或从外部世界调用这个 API 了。在 Wasp 文件中声明 API在main.wasp中使用api声明即可定义端点。API 声明与它的实现不需要同名当然同名也可以下面是一个最简单的示例// ... api fooBar { // API 与其实现不必但可以同名。 fn: import { fooBar } from server/apis.js, httpRoute: (GET, /foo/bar) }fn指向实现函数的 import 语句httpRoute是一个(HttpMethod, string)元组string是 Express 风格的路由路径。关于各字段的完整说明见后文 API Reference。定义 API 的 NodeJS 实现:::note 对 TypeScript 用户为了确保 Wasp 编译器为 API 生成可供实现使用的类型请先把api声明写进.wasp文件并保持wasp start运行。Wasp 会根据声明自动生成wasp/apis/types中的类型在 0.11.8 版本中实现文件中通过import { FooBar } from wasp/apis/types引入。 :::实现函数接收三个参数reqExpress Request 对象resExpress Response 对象context由 Wasp 注入的附加上下文对象包含用户会话信息以及实体信息。为简洁起见下面例子暂不使用context其详细用法见 在 API 中使用实体。import { FooBar } from wasp/apis/types; // 该类型由 Wasp 基于上面的 api 声明自动生成。 export const fooBar: FooBar (req, res, context) { res.set(Access-Control-Allow-Origin, *); // 示例修改响应头以覆盖 Wasp 默认 CORS 中间件。 res.json({ msg: Hello, ${context.user?.username || stranger}! }); };JavaScript 版本同样简单无需类型导入export const fooBar (req, res, context) { res.set(Access-Control-Allow-Origin, *); res.json({ msg: Hello, ${context.user?.username || stranger}! }); };这个实现就是一个标准 Express 请求处理器你可以像在任意 Express 应用中一样读取req、设置响应头、返回 JSON。为 API 提供额外类型信息TypeScript假设你想创建一个GET路由它从 URL 参数中接收一个 email 地址并返回生命、宇宙以及一切的答案——在 TypeScript 中长这样先在 Wasp 中声明 APIapi fooBar { fn: import { fooBar } from server/apis.js, entities: [Task], httpRoute: (GET, /foo/bar/:email) }然后在实现中使用FooBar泛型传入params与response两个类型参数即可获得完整的类型安全import { FooBar } from wasp/apis/types; export const fooBar: FooBar { email: string }, // params { answer: number } // response (req, res, _context) { console.log(req.params.email); res.json({ answer: 42 }); };此时req.params.email的类型会被推导为string而res.json(...)的入参类型也会被约束为{ answer: number }。这一机制源于 Wasp 生成的 SDK 类型在仓库中查看 SDK 的 API 类型模板可以看到 Wasp 会为每个api声明生成一个带P extends ExpressParams ExpressParams、ResBody any、ReqBody any等泛型参数的别名类型0.11.8 模板位于 Apis 类型生成模板这正是泛型FooBarParams, ResBody的底层来源。使用 API从外部使用 API从外部调用非常简单直接使用你声明的 HTTP 方法与路径发起请求即可。例如你的应用运行在https://example.com那么上面的声明对应GET https://example.com/foo/bar文档原文示例为/foo/callback请以你声明的路径为准可以在浏览器、Postman、curl或任意 Web 服务中调用。从客户端使用 API从客户端调用自定义 API包括携带认证信息时可以导入wasp/api提供的 Axios 包装器import React, { useEffect } from react; import api from wasp/api; async function fetchCustomRoute() { const res await api.get(/foo/bar); console.log(res.data); } export const Foo () { useEffect(() { fetchCustomRoute(); }, []); return // .../; };TypeScript 版本完全一致import React, { useEffect } from react; import api from wasp/api; async function fetchCustomRoute() { const res await api.get(/foo/bar); console.log(res.data); } export const Foo () { useEffect(() { fetchCustomRoute(); }, []); return // .../; };仓库中的 kitchen-sink 示例提供了一个真实的落地样例ApisPage.tsx 通过api.get(endpoint).json()分别请求需要认证的/foo/bar与无需认证的/bar/baz并用useQuery包装以展示 loading / error / data 三种状态。配套的 e2e 测试 验证了未登录时认证 API 返回错误、/bar/baz正常返回Hello, stranger!登录后认证 API 返回Hello, email!的完整行为可以直接作为你端到端验证自定义 API 的参考。确保 CORS 正常工作API 被设计为尽可能灵活因此它们不像 Operations 那样默认挂载中间件。要在客户端正常使用这些 API你必须确保 CORS跨域资源共享被启用。做法是在 Wasp 文件中为 API 定义自定义中间件。例如apiNamespace就是一种简单声明用来把某个middlewareConfigFn应用到某个路径下的所有 APIapiNamespace fooBar { middlewareConfigFn: import { fooBarNamespaceMiddlewareFn } from server/apis.js, path: /foo }然后在实现文件中返回默认配置TS 版本引入MiddlewareConfigFn类型import { MiddlewareConfigFn } from wasp/middleware; export const apiMiddleware: MiddlewareConfigFn (config) { return config; };返回默认中间件配置即表示/foo路径下的所有 API 都启用 CORS。更完整的中间件定制说明见 中间件配置。从源码层面看apiNamespace在 ApiNamespace.hs 中被定义为仅含middlewareConfigFn :: ExtImport与path :: String两个字段的数据结构。生成阶段会把它编译为router.use(path, globalMiddlewareConfigForExpress(...))见 生成模板即挂在路由层级的路径级中间件。在 API 中使用实体多数情况下API 中要操作的资源都是 实体Entity。要把实体注入 API只需在api声明的entities字段中列出它们api fooBar { fn: import { fooBar } from server/apis.js, entities: [Task], httpRoute: (GET, /foo/bar) }Wasp 会把列出的实体注入 API 的context参数从而让你直接访问该实体的 Prisma APIimport { FooBar } from wasp/apis/types; export const fooBar: FooBar (req, res, context) { res.json({ count: await context.entities.Task.count() }); };context.entities.Task暴露的就是 Prisma CRUD API 中的prisma.task。从生成代码看这一注入由 ApiRoutesG.hs 中的getApiEntitiesObject完成最终在 生成模板 中表现为构造context.entities { Task: prisma.task, ... }传给实现函数。kitchen-sink 示例中apis.wasp.ts 的/foo/bar与/bar/baz两个 API 都声明了entities: [Task]。API 中auth字段与context.userapi声明中的auth: bool字段控制该端点是否解析 JWT当项目启用了认证时auth默认为true实现函数的context中会提供context.user对象如果你不希望该端点尝试解析 Authorization Header 中的 JWT例如公开的 webhook 回调请显式设置为false。从实现看ApiRoutesG.hs 中的isAuthEnabledForApi spec api fromMaybe (isAuthEnabled spec) (Api.auth api)表明API 的auth取值优先于全局认证开关——未显式声明时回退到项目全局是否启用认证。生成模板中启用认证的路由会被编译为router.method(path, [auth, ...middleware], defineHandler(...))并把makeAuthUserIfPossible(req.user)的结果放进context.user见 生成模板。API Referenceapi声明的完整字段如下完整示例见 apis.wasp.tsapi fooBar { fn: import { fooBar } from server/apis.js, httpRoute: (GET, /foo/bar), entities: [Task], auth: true, middlewareConfigFn: import { apiMiddleware } from server/apis.js }fn: ServerImport必填该 API NodeJS 实现的 import 语句。httpRoute: (HttpMethod, string)必填HTTP 方法与路径的二元组。方法可以是ALL、GET、POST、PUT、DELETE路径是 Express 路径字符串支持:param、通配符等 Express 语法。在 Api.hs 中该字段被定义为(HttpMethod, String)HttpMethod数据构造器恰好为ALL | GET | POST | PUT | DELETE且编译器会在 Valid.hs 的validateApiRoutesAreUnique中校验所有 API 的方法、路径组合唯一——同一路径上声明相同方法或声明ALL会与其他方法构成冲突并报错apiroutes must be unique。entities: [Entity]希望在 API 内部使用的实体列表会注入context.entities详见 在 API 中使用实体。auth: bool启用认证时默认true并提供context.user对象。如果不想解析 Authorization Header 中的 JWT设置为false。middlewareConfigFn: ServerImport该 API 的 Express 中间件配置函数 import 语句。未指定时使用默认中间件在生成模板中以idFn兜底见 生成模板指定后可以middlewareConfig.set/delete增删中间件。更多说明见 中间件配置。进阶用中间件定制一个非默认的 API由于api不使用 Operations 的默认中间件链你可以针对单个 API 完全替换其中的中间件这在处理 webhook 等场景时尤其有用。例如下面这个 webhook 回调将express.json替换为接收任意原始内容的express.rawapi webhookCallback { fn: import { webhookCallback } from server/apis.js, middlewareConfigFn: import { webhookCallbackMiddlewareFn } from server/apis.js, httpRoute: (POST, /webhook/callback), auth: false }import express from express import { WebhookCallback } from wasp/apis/types import type { MiddlewareConfigFn } from wasp/middleware export const webhookCallback: WebhookCallback (req, res, _context) { res.json({ msg: req.body.length }) } export const webhookCallbackMiddlewareFn: MiddlewareConfigFn (middlewareConfig) { middlewareConfig.delete(express.json) middlewareConfig.set(express.raw, express.raw({ type: */* })) return middlewareConfig }kitchen-sink 示例的 apis.ts 完整复现了这个模式fooBarMiddlewareFn用set(custom.route, ...)追加自定义中间件、webhookCallbackMiddlewareFn用delete/set替换express.json并且该 API 挂载在单条路由上而barNamespaceMiddlewareFn则展示了如何通过apiNamespace为/bar下所有 API 统一注入中间件。其默认中间件集合helmet、cors、morgan、express.json、express.urlencoded、cookieParser及各层级的定制方式详见 中间件配置。流式响应Streaming场景自定义 API 的另一个典型用途是流式响应利用 Express 的res.write()/res.end()把数据分块推送给客户端。在生成模板中实现函数被defineHandler包裹后直接作为路由处理器挂载见 生成模板因此原生 Express 的流式写法天然可用。kitchen-sink 示例提供了完整可运行样例export const streamingText: StreamingText async (_req, res, _context) { res.setHeader(Content-Type, text/html; charsetutf-8); res.setHeader(Transfer-Encoding, chunked); res.setHeader(Cache-Control, no-transform); // 防止代理如边缘 CDN压缩缓冲流 res.write(Hm, let me see...\n); // ...循环 res.write() 分块发送 res.end(); };对应地在 Wasp 文件中声明并确保为该路径启用 CORS 中间件api(GET, /api/streaming-test, streamingText), apiNamespace(/api/streaming-test, { middlewareConfigFn: defaultMiddlewareForStreamingText, }),客户端通过fetch的response.bodyReadableStream 逐块读取内容见 StreamingTestPage.tsx即可实现边生成边展示的效果——这正是 AI 场景下流式输出 LLM 回复的典型实现路径。小结Wasp 的api声明在保留 Operations 便捷性的同时把端点的完全控制权交还给了开发者两步即可上线一个自定义 REST 端点.wasp中声明 NodeJS 实现通过context统一获得用户会话context.user与实体 Prisma APIcontext.entities用middlewareConfigFn/apiNamespace精确控制 CORS 与中间件应对 webhook、原始 body、流式响应等特殊需求编译器自动校验路由唯一性并生成类型安全的 SDK 类型全程享受 TS 类型保障。相关参考Operations 概览、实体、中间件配置、示例实现 apis.wasp.ts 与 apis.ts。【免费下载链接】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),仅供参考
延伸阅读

更多相关文章

2026/10/25 0:19:52

Rufus:绿色U盘启动盘制作工具,5分钟把U盘变成可引导U盘

Rufus:绿色U盘启动盘制作工具,5分钟把U盘变成可引导U盘 【免费下载链接】rufus The Reliable USB Formatting Utility 项目地址: https://gitcode.com/GitHub_Trending/ru/rufus Rufus 是一个绿色单文件工具,插入U盘即可把它格式化成 …

2026/10/31 21:11:57

VisionPro手术导航:医疗MR的精度革命与临床落地

1. 项目概述:这不是一台“头显”,而是一台悬浮在视网膜上的手术导航仪 我第一次把VisionPro戴在头上时,手是悬空的——不是因为紧张,而是下意识想用手指去“推”眼前那块半透明的3D解剖图。它没动。但当我微微偏头,那颗…

2026/11/5 16:51:33

EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析

1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被…

2026/11/5 16:26:13

Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6…

2026/11/5 15:00:49

基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享…

2026/11/5 14:10:30

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑