You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署时配置NextAuth与tRPC WebSocket遇问题求助

问题:tRPCv10 WebSocket订阅部署后连接失败 + NextAuth登录401错误

背景

用tRPCv10和NextAuth开发了一款需要实时更新的应用,参考tRPC订阅相关文档及示例项目实现了WebSocket订阅功能。按照实现逻辑,tRPC使用WebSocket需要独立HTTP服务器与Next.js应用并行运行,通过EventEmitter推送数据给订阅者,因此将独立HTTP服务器部署在Railway(端口6957),Next.js应用部署在Vercel。

本地开发一切正常,但部署后出现两个问题:

  • 客户端无法连接WebSocket服务器,报错:WebSocket connection to 'wss://xxx-server.up.railway.app:6957/' failed
  • 点击登录按钮触发NextAuth的authorize函数时,控制台返回错误:POST https://xxx-client.vercel.app/api/auth/callback/credentials 401

相关代码片段

_app.tsx

const MyApp: AppType = ({
  Component,
  pageProps: { session, ...pageProps },
}) => {
  return (
    <SessionProvider session={session} refetchOnWindowFocus={false}>
      <Component {...pageProps} />
    </SessionProvider>
  );
};

const getBaseUrl = () => {
  if (typeof window !== "undefined") {
    return "";
  }
  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url

  return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
};

function getEndingLink() {
  if (typeof window === "undefined") {
    return httpBatchLink({
      url: `${getBaseUrl()}/api/trpc`,
    });
  }

  const client = createWSClient({
    url: "wss://xxx-server.up.railway.app:6957"
  });

  return wsLink<AppRouter>({
    client,
  });
}

export default withTRPC<AppRouter>({
  config({ ctx }) {
    /**
     * If you want to use SSR, you need to use the server's full URL
     */
    const url = `${getBaseUrl()}/api/trpc`;

    return {
      url,
      transformer: superjson,
      links: [getEndingLink()],

      /**
       * @link https://react-query.tanstack.com/reference/QueryClient
       */
      // queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },
    };
  },
  /**
   * @link https://trpc.io/docs/ssr
   */
  ssr: true,
})(MyApp);

prodServer.ts

const port = parseInt(process.env.PORT || "3000", 10);
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = http.createServer((req, res) => {
    const proto = req.headers["x-forwarded-proto"];
    if (proto && proto === "http") {
      // redirect to ssl
      res.writeHead(303, {
        location: `https://` + req.headers.host + (req.headers.url ?? ""),
      });
      res.end();
      return;
    }
    const parsedUrl = parse(req.url!, true);
    handle(req, res, parsedUrl);
  });
  const wss = new ws.Server({ server });
  const handler = applyWSSHandler({ wss, router: appRouter, createContext });

  process.on("SIGTERM", () => {
    console.log("SIGTERM");
    handler.broadcastReconnectNotification();
  });
  server.listen(port);

  // tslint:disable-next-line:no-console
  console.log(
    `> Server listening at http://localhost:${port} as ${dev ? "development" : process.env.NODE_ENV}`
  );
});

内容的提问来源于stack exchange,提问作者sweic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:10:42