如何在Nextjs 13中编写一个在服务器和客户端都能工作的fetcher?

brjng4g3  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(174)

我有一个Nextjs 13前端(应用程序路由器),它通过API与Laravel支持的后端通信。对于API中的身份验证,我使用Laravel Sanctum(Laravel为SPA推荐):基本上,身份验证通过在登录后设置两个cookie(一个会话和一个CSRF令牌)来工作,然后应该将其附加到所有未来的请求中,沿着传递CSRF令牌的X-Xsrf-Token报头。
要从客户端组件发送请求,我可以执行以下操作:

import cookies from 'js-cookie'

fetch( [url], {
   headers: {
      "Accept": "application/json",
      "Content-Type": "application/json",
      "Origin": [origin],
      "X-Requested-With": "XMLHttpRequest",  
      "X-Xsrf-Token": cookies.get( "XSRF-TOKEN" ),
      // Since we're on the browser, cookies are automatically attached via the 'Cookie' header
   },
   credentials: 'include'
})

字符串
如果我从服务器组件发送请求,我可以做:

import { cookies, headers } from "next/headers"

fetch( [url], {
   headers: {
      "Cookie": cookies().toString(), // Must attach cookies manually
      "Referer": headers().get( "referer" ) ?? "",
      "X-Xsrf-Token": cookies().get( "XSRF-TOKEN" ).value,
   },
})


两个提取器都工作。然而,有时我需要从服务器组件和客户端组件发出相同的请求,所以我想使用一个像这样的提取器(这是一个快速而肮脏的例子,只是为了让我的观点得到理解):

import cookies from 'js-cookie'
import { cookies, headers } from "next/headers"

fetch( [url], 
   isServer 
   ?
   {
      headers: {
         "Cookie": cookies().toString(), // Must attach cookies manually
         "Referer": headers().get( "referer" ) ?? "",
         "X-Xsrf-Token": cookies().get( "XSRF-TOKEN" ).value,
      }   
   }
   :
   {
      headers: {
         "Accept": "application/json",
         "Content-Type": "application/json",
         "Origin": process.env.NEXT_PUBLIC_APP_URL,
         "X-Requested-With": "XMLHttpRequest",  
         "X-Xsrf-Token": cookies.get( "XSRF-TOKEN" ),
         // Since we're on the browser, cookies are automatically attached via the 'Cookie' header
      },
      credentials: 'include'
   } 
)


但这会在客户端组件中引发错误,因为cookies()headers()函数只能在服务器组件中使用。
因此,简而言之,我如何编写一个同时在服务器和客户端组件上工作的提取器?

ecfsfe2w

ecfsfe2w1#

的确,在客户端组件中不能使用cookie()和headers()函数,因为它们是服务器函数。这些函数设计用于服务器组件或服务器操作。
但是,您可以创建一个实用程序函数来检查代码是在服务器上运行还是在客户端上运行,然后相应地执行获取。下面是一个基本的例子:

import cookies from 'js-cookie'
import { cookies as serverCookies, headers } from "next/headers"

function isServer() {
  return typeof window === 'undefined';
}

async function universalFetch(url, options = {}) {
  if (isServer()) {
    options.headers = {
      ...options.headers,
      "Cookie": serverCookies().toString(),
      "Referer": headers().get("referer") ?? "",
      "X-Xsrf-Token": serverCookies().get("XSRF-TOKEN").value,
    };
  } else {
    options.headers = {
      ...options.headers,
      "Accept": "application/json",
      "Content-Type": "application/json",
      "Origin": process.env.NEXT_PUBLIC_APP_URL,
      "X-Requested-With": "XMLHttpRequest",  
      "X-Xsrf-Token": cookies.get("XSRF-TOKEN"),
    };
    options.credentials = 'include';
  }

  return fetch(url, options);
}

字符串
这个universalFetch函数首先使用isServer函数检查它是在服务器上运行还是在客户机上运行。如果它在服务器上,它使用来自next/headers的serverCookies和headers函数来设置头。如果它在客户端上,它使用js-cookie的cookie函数来获取XSRF-TOKEN,并将凭据选项设置为'include'。

相关问题