阿波罗服务器订阅中间件



我将当前用户身份验证传递给应用程序中间软件,它工作得很好......但是当我在 GraphQL 中运行订阅时,它说找不到当前用户......我做错了什么,伙计们?当我从阿波罗服务器中删除当前用户时,它可以工作...我试图按照阿波罗网站上的文档来创建这个

我尝试将逻辑移动到阿波罗服务器的主体,但由于某种原因没有成功

const express = require('express');
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');
const cors = require('cors');
require('dotenv').config({ path: 'variables.env' });
const app = express();
const { createServer } = require('http');
const corsOptions = {
    origin:'http://localhost:8000',
    credentials:true
};
mongoose.set('useFindAndModify', false);
app.use(cors(corsOptions));
app.use(async (req , res , next) => {
    const token = req.headers["authorization"];
    if(token !== "null"){
      try{
          const currentUser = await jwt.verify(token, process.env.SECRET);
          req.currentUser = currentUser;
          console.log(currentUser)
      }catch(err){
          console.log(err)
      }
    }
    next();
})

const Event = require('./models/Event');
const User = require('./models/User');
const Message = require('./models/Messages');
const { ApolloServer } = require('apollo-server-express');
const { typeDefs } = require('./Schema');
const { resolvers } = require('./Resolvers');

mongoose
  .connect(process.env.MONGO_URI, {useNewUrlParser: true , useCreateIndex: true})
  .then(() => console.log('DB connected'))
  .catch(err => console.error(err))

  const SERVER = new ApolloServer({
    typeDefs,
    resolvers,
    context: ({req, res}) => ({
         Event,
         User,
         Message,
         currentUser:req.currentUser
      }),
    playground: {
      settings: {
        'editor.theme': 'dark'
      }
    }
  });
SERVER.applyMiddleware({ app , path:'/graphql' });
const httpServer = createServer(app);
SERVER.installSubscriptionHandlers(httpServer);
const PORT = process.env.PORT || 5000;
httpServer.listen({ port: PORT }, () =>{
  console.log(`🚀 Server ready at http://localhost:${PORT}${SERVER.graphqlPath}`)
  console.log(`🚀 Subscriptions ready at ws://localhost:${PORT}${SERVER.subscriptionsPath}`)
})

在订阅的情况下,您使用的是 Web 套接字而不是常规的 http 请求,因此您的令牌在其他地方可用,即在 connection.context.Authorization 下(注意大写的"A"(,connection由附加到 ApolloServer context的函数提供,并在订阅上下文中定义。

您基本上希望将令牌验证移动到您的 ApolloServer 声明中:

  const SERVER = new ApolloServer({
    typeDefs,
    resolvers,
    context: ({req, connection}) => ({
         Event,
         User,
         Message,
         currentUser: async () => {
           const token = connection
                         ? connection.context.Authorization
                         : req.headers.authorization
           return await jwt.verify(token, process.env.SECRET)
         },
      }),
    ...

这是一个非常简单的例子,你也可以检查req是否存在,如果既没有设置connection也没有设置req,则生成错误,处理没有令牌的情况等,但你得到了基本的想法。

有关进一步参考,请参阅 Apollo Server 文档中的订阅上下文。

相关内容