jwt保护的graphql解析器未调用SSR Nextjs

svgewumm  于 2023-05-06  发布在  其他
关注(0)|答案(1)|浏览(170)

我有一个Nest + Graphql的后台

*me解析器:

@Query(() => User)
@UseGuards(JwtAuthGuard)
me(@Context() { req }) {
  return this.usersService.findOne(req.user.id);
}

*在前端,我使用Nextjs、Apollo客户端和code-gen:

# codegen.yml

overwrite: true
schema: 'http://localhost:3030/graphql'
documents: 'src/graphql/**/*.gql'
generates:
  src/graphql/index.tsx:
    plugins:
      - 'typescript'
      - 'typescript-operations'
      - 'typescript-react-apollo'
    config:
      reactApolloVersion: 3

*with-next-apollo封装

// utils/withApollo.ts

import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'
import { getCookie } from 'cookies-next'
import withApollo from 'next-with-apollo'

export default withApollo(
  ({ initialState, ctx }) => {
    const token = getCookie('token', ctx)
    return new ApolloClient({
      uri: 'http://localhost:3030/graphql',
      cache: new InMemoryCache().restore(initialState || {}),
      credentials: 'include',
      headers: {
        authorization: token ? `Bearer ${token}` : '',
      },
    })
  },
  {
    render: ({ Page, props }) => {
      return (
        <ApolloProvider client={props.apollo}>
          <Page {...props} />
        </ApolloProvider>
      )
    },
  }
)

*并像这样使用它:

import { useMeQuery } from '@/graphql/_generated'
import withApollo from '@/utils/withApollo'
import { getDataFromTree } from '@apollo/client/react/ssr'

const Home = () => {
  const { loading, error } = useMeQuery()
  ...
}
export default withApollo(Home, { getDataFromTree }) // server side
// export default withApollo(Home) // client side

因此,即使我指定了一个页面为ssr,我的graphql解析器在后端受到jwt(@Query(() => User))的保护,也不会调用ssr,它只会调用客户端,我在网络选项卡中清楚地看到。

如果我在一个ssr页面中调用多个解析器,jwt保护的解析器在客户端调用,其他解析器在服务器上(如预期)
// they all expected to run on the server, bcs page is ssr

// jwt protected(only calling on the client)
const {} = useMeQuery()
const {} = useUserDetailsQuery()
// not protected(working fine)
const {} = useProductsQuery()
const {} = useBlogsQuery()

export default withApollo(ThisPage, { getDataFromTree }) // ssr
nom7f22z

nom7f22z1#

我不确定这是不是真的,但值得一查。对于每个应用程序,Apollo通常会创建一个新的ApolloClient示例。在某些情况下,在SSR期间(通常是由于错误的配置),在服务器端创建的ApolloClient对于所有请求都保持不变。也就是说,与每个浏览器框架的新应用程序不同,服务器被认为是一个应用程序,因此只需要一个ApolloClient示例。一旦默认的缓存选项强制客户端为相同的查询返回相同的数据(如果它们被缓存),有时会导致解析器不被调用。要检查是否是这种情况,您可以尝试完全禁用缓存并查看是否发生了更改。

return new ApolloClient({
  uri: 'http://localhost:3030/graphql',
  cache: new InMemoryCache().restore(initialState || {}),
  credentials: 'include',
  headers: {
    authorization: token ? `Bearer ${token}` : '',
  },
  defaultOptions: { // <-- Add these options.
   query: {
     errorPolicy: 'all',
     fetchPolicy: 'no-cache'
   }
 }
})

如果它被证明是问题的根源,那么创建ApolloClient的逻辑应该改变为您的应用为每个请求创建新的ApolloClient示例的方式。

相关问题