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

发布时间:2026/9/14 22:10:38

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/9/14 22:10:38

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/9/14 22:10:38

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

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

2026/9/14 22:25:41

Claude Code /loop功能解析:AI辅助编程的效率革命

1. Claude Code /loop功能解析:终端开发者的效率革命2023年第四季度,Anthropic公司推出的Claude Code工具链中,/loop功能的发布在开发者社区引发了热烈讨论。这个看似简单的命令行交互模式,实际上重新定义了AI辅助编程的工作流程。…

2026/9/14 22:25:41

流域淹没分析4步法:应急规划快速解决方案

1. 项目概述:流域淹没分析的快速解决方案在应急规划和灾害管理中,流域淹没分析是至关重要的环节。传统的水文建模方法通常需要复杂的数据准备、专业软件操作和较长的计算时间,这对于需要快速响应的应急场景来说往往不够理想。本文介绍的"…

2026/9/14 22:25:41

【神经网络干货】当光自己开始“计算”:无记忆散射成像与卷积光学神经网络

隔着一块透明玻璃观察物体并不困难。 但如果物体前方换成毛玻璃、浑浊组织或多层复杂散射介质,原本规则的光场会经历多次散射,最终在相机上形成一幅看似毫无规律的散斑图(speckle pattern)。 此时,相机真正记录到的已经不是物体本身,而是物体信息经过复杂光学传播后形成…

2026/9/14 22:25:41

无人机小目标检测实战:YOLOv3轻量化改造与航拍图像增强

简介:本资源是一份面向计算机专业本科生与初阶AI学习者的无人机图像目标检测实践项目,聚焦YOLO系列模型在低空航拍场景下的部署与调优,适用于课程大作业、期末设计及毕业设计参考。压缩包共231个文件,含94个Python源码&#xff08…

2026/9/14 22:25:41

港股暗盘交易机制解析与实战策略

1. 2026年2月2日隔夜暗盘交易全景解读隔夜暗盘作为港股市场的特色交易机制,一直是专业投资者获取先机的重要战场。2026年2月2日的暗盘数据尤为值得关注,当天恒生指数在日间交易时段收报21,458点,市场情绪呈现明显的多空分歧。通过分析这份排行…

2026/9/14 22:20:41

2026年9月6日GitHub热榜深度盘点:从趋势解读到项目跑通

早上七点多,我照例打开 GitHub Trending,扫了一眼 2026 年 9 月 6 日的日榜。这个习惯我坚持了快五年,比看早间新闻还准时。很多人问我,为什么每天都要刷一遍热榜项目?因为日榜是过去 24 小时内全球开发者用 star、for…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

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

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

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