Apollo服务器订阅中间件

时间:2019-07-15 16:42:40

标签: server apollo subscription

我将currentuser auth传递给应用middlware,它的工作原理还不错...但是当我在graphql中运行订阅时,它说当前用户未找到....我在做什么错人?当我从阿波罗服务器中删除currentuser时,它起作用了...我试图遵循阿波罗网站上的文档来创建它

我曾尝试将逻辑转移到apollo服务器的主体上,但由于某些原因未能解决

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}`)
})

1 个答案:

答案 0 :(得分:0)

对于订阅,您使用的是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)
         },
      }),
    ...

这是一个非常简单的示例,如果未设置reqconnection,也可以检查是否存在req并生成错误,请处理不是令牌等,但是您了解基本概念。

请参阅Apollo Server文档中的Context with Subscriptions,以获取更多参考。