我的 Apollo 服务器的订阅不起作用:无法读取未定义的 属性 'headers'
My Apollo Server's Subscription doesn't works: Cannot read property 'headers' of undefined
我尝试将它与上下文连接一起使用,并将订阅参数添加到 Apollo 服务器中,但它不起作用。我是第一次使用 Apollo 服务器订阅,我不知道错误是在服务器配置中还是在解析器中。
我在查询或突变中没有问题,问题是订阅。
这是我的 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"
}
}
问题是,在你的行中
const token = req.headers['authorization'];
对于 WebSocket 连接,变量 req
将是未定义的。那些的认证,参考https://www.apollographql.com/docs/graphql-subscriptions/authentication/
我这样做就解决了:
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 "";
}
}
}
},
});
上下文回调时可以查看jwt token
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
})
我尝试将它与上下文连接一起使用,并将订阅参数添加到 Apollo 服务器中,但它不起作用。我是第一次使用 Apollo 服务器订阅,我不知道错误是在服务器配置中还是在解析器中。 我在查询或突变中没有问题,问题是订阅。
这是我的 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"
}
}
问题是,在你的行中
const token = req.headers['authorization'];
对于 WebSocket 连接,变量 req
将是未定义的。那些的认证,参考https://www.apollographql.com/docs/graphql-subscriptions/authentication/
我这样做就解决了:
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 "";
}
}
}
},
});
上下文回调时可以查看jwt token
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
})