我的Apollo服务器的订阅不起作用:无法读取未定义的属性“标头”

时间:2019-09-06 00:17:44

标签: javascript graphql subscription apollo-server express-graphql

我尝试将其与上下文连接一起使用,并将订阅参数添加到Apollo Server中,但是它不起作用。我是第一次使用Apollo Server Subscriptions,我不知道错误是在服务器配置中还是在解析器中。 我在查询或变异中都没有问题,问题在于订阅。

这是我的index.js:

    import express from 'express';
    import { createServer } from 'http';
    import { ApolloServer } from 'apollo-server-express';
    import { typeDefs } from './data/schema';
    import { resolvers } from './data/resolvers';
    import cors from 'cors';
    import jwt from 'jsonwebtoken';

    const bodyParser = require('body-parser');
    const PORT = process.env.PORT ||  4004;
    const app = express();

    app.use(bodyParser.json());
    app.use(cors());

    const server = new ApolloServer({
          typeDefs,
          resolvers,
          context: async({req, connection}) => {
            console.log("Context connection", connection)  
            const token = req.headers['authorization'];
              if(connection){
                return connection.context;
              } else {
                if(token !== "null"){
                    try{

                      //validate user in client.
                      const currentUser = await jwt.verify(token, process.env.SECRET);

              //add user to request
              req.currentUser = currentUser;

              return {
                  currentUser
              }   
            }catch(err){
                return "";
            }

      }

    } 

  },
  subscriptions: {
    path: "/subscriptions",
    onConnect: async (connectionParams, webSocket, context) => {
      console.log(`Subscription client connected using Apollo server's built-in SubscriptionServer.`)
    },
    onDisconnect: async (webSocket, context) => {
      console.log(`Subscription client disconnected.`)
    }
   }

});

    server.applyMiddleware({app});

    const httpServer = createServer(app);
    server.installSubscriptionHandlers(httpServer);

    httpServer.listen({ port: PORT }, () =>{
      console.log(`? Server ready at 
      http://localhost:${PORT}${server.graphqlPath}`)
      console.log(`? Subscriptions ready at 
    ws://localhost:${PORT}${server.subscriptionsPath}`)
    })

在操场上

我的变异:

    mutation {
      pushNotification(label:"My septh notification") {
        label
      }
    }

我的查询:

    query {
      notifications {
        label
      }
    }

我的订阅:

    subscription {
      newNotification {
        label
      }
    }

错误是:

{
       "error": {
         "message": "Cannot read property 'headers' of undefined"
        }
 }

3 个答案:

答案 0 :(得分:1)

您可以在上下文回调时检查jwt令牌

server = new ApolloServer({
  schema: schema ,
  graphiql: true ,
  context:({req, connection} )=>
    if connection
      token = connection.context["x-access-token"]
      decoded = await LoginService.verify token #verify by jwt

      if decoded == null
        throw new Error("auth required")
      return connection.context
    headers = req.headers
    token = headers["x-access-token"]
    decoded = await LoginService.verify token #verify by jwt
    return authed: decoded != null
})

答案 1 :(得分:0)

问题是,您所在的行中

const token = req.headers['authorization'];

对于WebSocket连接,变量req将是未定义的。有关这些身份验证的信息,请参阅https://www.apollographql.com/docs/graphql-subscriptions/authentication/

答案 2 :(得分:0)

我这样做是解决问题的:

const server = new ApolloServer({
      typeDefs,
      resolvers,
      context: async ({ req, connection }) => {
        if (connection) {
         // check connection for metadata
         return connection.context;
        } else {
         // check from req
         const token = req.headers.authorization


        if(token !== "null"){
          try{

          //validate user in client.
          const currentUser = await jwt.verify(token, process.env.SECRET);

          //add user to request
          req.currentUser = currentUser;

          return {
              currentUser
          }   
        }catch(err){
            return "";
                }
             }

         }
       },


    });