部署时配置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
相关产品推荐
相关产品推荐

