ruby-on-rails 通过Next.js服务器将所有调用代理到外部API的正确方法?(使SSR组件与客户端auth cookie一起工作)

oxf4rvwz  于 2023-11-20  发布在  Ruby
关注(0)|答案(1)|浏览(117)

我有一个rails API运行在我的Next.js13服务器的同一个集群中。rails API使用auth cookie来跟踪会话。
我可以登录到一个客户端组件,并开始根据从rails API接收到的set-cookie头进行身份验证的API调用,但是,当使用SSR组件时,例如.

export default async function MeTestPage () {
    try {
        let allCookies = cookies().getAll().map(c => `${c.name}=${c.value}`).join("; ");
        console.log(allCookies);

        let result = await fetch("http://0.0.0.0:3000/users/me", {
            "headers": {
                "accept": "*/*",
                "accept-language": "en-US,en;q=0.9",
                "sec-ch-ua": "\"Google Chrome\";v=\"107\", \"Chromium\";v=\"107\", \"Not=A?Brand\";v=\"24\"",
                "sec-ch-ua-mobile": "?0",
                "sec-ch-ua-platform": "\"macOS\"",
                "sec-fetch-dest": "empty",
                "sec-fetch-mode": "cors",
                "sec-fetch-site": "same-origin",
                "cookie": allCookies
            },
            "referrerPolicy": "strict-origin-when-cross-origin",
            "body": null,
            "method": "GET",
            "mode": "cors",
            "credentials": "include"
        });
        let resultJson = await result.json();
        return <p>{JSON.stringify(resultJson)}</p>
    } catch (e: any) {
        return <p>{e.toString()}</p>
    }

字符串
请求通过,rails得到正确的cookie,但rails没有将其连接到会话,我怀疑这是因为它来自不同的IP地址,尽管我还没有能够弄清楚这一点。
我觉得一个好的解决方案是通过下一个服务器代理所有客户端请求,这样下一个服务器就可以充当rails的唯一API客户端,并保持IP一致,但是我不确定最好的方法是什么。我试过在next.js.js中设置rewrites,也试过复制请求方法/route/headers/从一个/api/[...path].ts定义的端点发送一个新的请求(但是在调试为什么没有发送正文时遇到了非常令人沮丧的时间)。
我刚刚进入next.js,无法相信这是一个如此艰难的过程--我认为必须有一些规范的方法来处理这个非常常见的需要,即从两个环境中访问受cookie保护的API。

jdg4fx2g

jdg4fx2g1#

这个next.config.ts配置对我来说很好用,我所有的客户端请求都将发送到api/proxy,我使用rewrites将其Map到外部API

/** @type {import('next').NextConfig} */
  const nextConfig = {
    output: "standalone",
    typescript: {
      ignoreBuildErrors: true,
    },
    eslint: {
      dirs: ["."],
    },
    poweredByHeader: false,
    trailingSlash: false,
    basePath: "",

    // The starter code load resources from `public` folder with `router.basePath` in React components.
    // So, the source code is "basePath-ready".
    // You can remove `basePath` if you don't need it.
    reactStrictMode: true,
    rewrites: () => [
      {
        source: "/api/proxy/:path*",
        destination: `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/:path*`,
      },
    ],
  }

  module.exports = nextConfig

字符串
注意:这不适用于SSR请求。如果您有更好的解决方案,请更新此问题

相关问题