01MVP 早鸟价限时开放中,产品还在打磨中,感谢信任

00 / 00

登录与 API 对接

理解桌面端如何连接后端:环境变量、Auth 客户端、API 客户端、Origin 配置和完整验证流程

你将学到

  • 桌面端 WebView 怎样和 01MVP Hono 后端通信
  • 两个关键环境变量分别控制什么
  • auth-client 和 api-client 各自的职责和配置方式
  • DESKTOP_ALLOWED_ORIGINS 在 CORS 和登录中扮演的角色
  • 按什么顺序逐项验证连接是否正常

整体架构

桌面端的本质是一个本地 WebView 窗口。它和浏览器一样发 HTTP 请求,但 origin 不同——浏览器预览跑在 http://localhost:7410,Tauri 原生窗口跑在 tauri://localhosthttp://tauri.localhost

请求链路:

WebView (React 前端)
  ↓ fetch / credentials: "include"
Hono 服务 (http://localhost:7001/api)
  ├── /auth   → Better Auth 处理登录、会话、OAuth 回调
  └── /rpc    → oRPC 处理业务 API 调用

两个端点的地址都从 VITE_DESKTOP_SERVER_URL 派生。客户端代码在:

文件职责
src/lib/auth-client.ts登录、注册、会话、OAuth
src/lib/api-client.ts业务 API(health、billing、account 等)
src/config/desktop-env.ts环境变量读取和 Zod 校验

所有路径相对于 products/01mvp/apps/desktop/

环境变量

桌面端需要两个公开环境变量。复制模板文件后编辑:

cp products/01mvp/apps/desktop/.env.example products/01mvp/apps/desktop/.env.local
变量默认值说明
VITE_DESKTOP_SERVER_URLhttp://localhost:7001/apiAPI 基础地址,必须以 /api 结尾
VITE_DESKTOP_WEB_URLhttp://localhost:7001网页入口,不带 /api,用于打开价格页、用户后台等

VITE_DESKTOP_SERVER_URL 同时决定 auth 端点(/api/auth)和 oRPC 端点(/api/rpc)。两个客户端内部都会自动拼接,你不需要分别配置。

VITE_DESKTOP_* 会进入前端 bundle。数据库连接串、支付密钥、Better Auth secret 等服务端变量不能放在这里。

Auth 客户端

src/lib/auth-client.ts 使用 Better Auth 的 React 客户端:

import { createAuthClient } from "better-auth/react";

export const desktopAuthClient = createAuthClient({
  baseURL: joinUrlPath(DESKTOP_ENV.VITE_DESKTOP_SERVER_URL, "auth"),
  fetchOptions: {
    credentials: "include",
  },
});

关键点:

  • baseURL 指向 http://localhost:7001/api/auth
  • credentials: "include" 让浏览器/WebView 自动携带 cookie,这是 session 认证的前提
  • 模板导出了 DesktopAuthSession 类型,供组件里做类型推断

登录流程:桌面端调用 desktopAuthClient.signIn.email()desktopAuthClient.signIn.social() → 后端 Better Auth 创建 session → cookie 写入 WebView → 后续请求自动带上。

API 客户端

src/lib/api-client.ts 使用 oRPC 的 fetch link:

const link = new RPCLink({
  fetch(url, requestOptions) {
    return fetch(url, {
      ...requestOptions,
      credentials: "include",
    });
  },
  url: joinUrlPath(DESKTOP_ENV.VITE_DESKTOP_SERVER_URL, "rpc"),
});

模板默认注册了三个 API 调用,可以用来验证整条链路:

调用权限用途
health.live公开后端是否活着
billing.plans公开价格数据能否返回
account.profile需要登录session 和 cookie 是否生效

先用 health.live 确认后端可达,再用 account.profile 确认登录链路完整。

Origin 配置

后端需要认识桌面端的 origin,否则 CORS 和 Better Auth 都会拒绝请求。

products/01mvp/packages/config/.env 里:

DESKTOP_ALLOWED_ORIGINS="http://localhost:7410,http://127.0.0.1:7410,tauri://localhost,http://tauri.localhost"

这个变量被两处读取:

  • packages/auth/src/index.ts — Better Auth 的 trusted origins
  • apps/web/src/server/hono.ts — CORS 中间件

不同场景对应的 origin:

场景Origin
浏览器预览 (vpr @01mvp/desktop#dev)http://localhost:7410
Tauri 原生窗口tauri://localhosthttp://tauri.localhost
OAuth 回调取决于 Better Auth 配置的回调地址
生产环境你实际分发的桌面 origin

本地开发默认值已经覆盖常见情况。如果你修改了桌面端 dev server 端口,或在生产使用自定义 origin,要把对应的值加进去。每次改完后端的 env 文件,记得重启后端服务。

验证流程

后端是否可达

先确认 01MVP Web/API 已启动,然后直接请求 health 端点:

curl http://localhost:7001/api/rpc/health/live

返回成功说明后端在跑,网络没问题。

登录能否完成

打开桌面端浏览器预览或 Tauri 窗口,用测试账号登录。登录成功后,检查浏览器 DevTools 的 Application > Cookies 里有没有 session cookie。

受保护 API 能否访问

登录后调用 account.profile。如果能拿到用户信息,说明 credentials: "include" 和 origin 配置都正确。

生产地址是否正确

VITE_DESKTOP_SERVER_URL 改成正式后端地址,重新构建桌面端,重复以上三步。生产环境的 DESKTOP_ALLOWED_ORIGINS 必须包含桌面端实际使用的 origin。

常见问题

health 正常,但 profile 返回 401

health 是公开端点,不需要 session。profile 需要登录态。按顺序排查:

  1. DESKTOP_ALLOWED_ORIGINS 是否包含了你当前的桌面 origin
  2. VITE_DESKTOP_SERVER_URL 是否以 /api 结尾
  3. 请求头里有没有带 cookie(DevTools > Network > 点击请求 > Headers)
  4. 后端是否重启过,新的 env 是否已经生效

浏览器里正常,Tauri 窗口里失败

浏览器预览跑在 http://localhost:7410,Tauri 窗口跑在 tauri://localhost。如果 DESKTOP_ALLOWED_ORIGINS 只配了浏览器的 origin,Tauri 窗口里的请求会被 CORS 拒绝。确保两个 origin 都加进去。

OAuth 回调打不开或显示空白

OAuth 登录需要浏览器跳转。在 WebView 里,Better Auth 会尝试打开系统浏览器完成 OAuth 流程,然后通过 deep link 回到桌面应用。如果回调地址配置不对或 deep link 没注册,用户会看到空白页。先确认 Better Auth 的回调 URL 和 Tauri 的 URL scheme 配置一致。

下一步

登录和 API 都跑通后,下一步了解 Tauri 原生能力:Runtime 与权限

这篇文档有问题?