node.js - 订阅不适用于 Apollo Server Express
问题描述
我想用 express 添加对我已经工作的 apollo 服务器的订阅,但我什至无法连接到操场上。我从操场上得到这个错误
"error": "Could not connect to websocket endpoint ws://localhost:4000/graphql. Please check if the endpoint url is correct."
从 Firefox 和 chrome 我得到类似的错误
Firefox can’t establish a connection to the server at ws://localhost:4000/graphql
这是我的 app.js 我的主文件。
const express = require('express');
const mongoose = require('mongoose');
const { ApolloServer } = require('apollo-server-express');
const cors = require('cors');
const session = require('express-session');
const Keycloak = require('keycloak-connect');
const { typeDefs } = require('./graphql/Schema');
const { resolvers } = require('./graphql/Resolvers');
const { userTypeDefs, userResolvers } = require('./graphql/User');
const { campusTypeDefs, campusResolvers } = require('./graphql/Campus');
const { profileTypeDefs, profileResolvers } = require('./graphql/Profile');
const { notificationTypeDefs, notificationResolvers } = require('./graphql/Notification');
const { rideTypeDefs, rideResolvers } = require('./graphql/Ride');
const app = express();
app.use(i18n.init);
const keycloak = new Keycloak({
memoryStore
}, 'keycloak.json');
app.use('/graphql', keycloak.middleware());
const server = new ApolloServer({
typeDefs: [KeycloakTypeDefs, typeDefs, rideTypeDefs, userTypeDefs, campusTypeDefs, profileTypeDefs, notificationTypeDefs],
schemaDirectives: KeycloakSchemaDirectives,
cors: cors(corsOptions),
resolvers: [resolvers, rideResolvers, userResolvers, campusResolvers, profileResolvers, notificationResolvers],
context: ({ req, connection }) => {
console.log(connection);
return { kauth: new KeycloakContext({ req }) };
},
subscriptions: {
onConnect: async (connectionParams, webSocket) => {
console.log("xxx");
console.log(connectionParams);
if (connectionParams.authToken) {
return validateToken(connectionParams.authToken)
.then(findUser(connectionParams.authToken))
.then(user => {
return {
currentUser: user,
};
});
}
throw new Error('Missing auth token!');
},
}
});
server.applyMiddleware({ app });
server.installSubscriptionHandlers(app);
mongoose.connect(
'mongodb://deaventon:mapache@localhost:27017/deaventon')
.then(result => {
app.listen(4000);
})
.catch(err => console.log(err));
根据一些例子 server.installSubscriptionHandlers 应该足够了,在其他一些情况下他们不使用它。但我认为它与 apollo-server-express 有关,通常使用 apollo-server-express 的示例使用它。当我对连接执行 console.log() 时,我得到一个未定义的结果,即使来自套接字连接的请求也是如此。我可以看到 req 或 socket 请求。我从来没有在 subscription.onConnect 函数中得到任何东西,它显然没有被调用,因为它从不建立连接。如果我从上下文到 req var 执行 console.log,我会得到这样的结果
IncomingMessage {
_readableState: ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: null,
ended: true,
endEmitted: false,
reading: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
emitClose: true,
autoDestroy: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: true,
decoder: null,
encoding: null,
[Symbol(kPaused)]: null
},
readable: true,
_events: [Object: null prototype] {
end: [Function: resetHeadersTimeoutOnReqEnd]
},
_eventsCount: 1,
_maxListeners: undefined,
socket: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
似乎它甚至没有验证订阅。
解决方案
您必须将另一台 http 服务器传递给installSubscriptionHandlers
非快递服务器并监听它。这是您的代码简化和工作:
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const { gql } = require('apollo-server');
const http = require('http');
const app = express();
/* I have removed your middleware to simplify example
but you can observe that middleware is still used */
app.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
});
const resolvers = {
Query: { test: () => {} },
Subscription: { test: () => {} },
Mutation: { test: () => {} },
};
const typeDefs = gql`
type Query {
test(id: ID!): ID
}
type Mutation {
test(id: ID!): ID
}
type Subscription {
test(id: ID!): ID
}
`;
const server = new ApolloServer({
typeDefs: [typeDefs],
resolvers: [resolvers],
context: ({ req, connection }) => {
console.log(connection);
return {};
},
subscriptions: {
onConnect: async (connectionParams, webSocket) => {
console.log('xxx');
console.log(connectionParams);
},
},
});
const httpServer = http.createServer(app);
server.applyMiddleware({ app });
server.installSubscriptionHandlers(httpServer);
const port = 4003;
httpServer.listen(port, () => {
console.log(
` Server ready at http://localhost:${port}${server.graphqlPath}`,
);
console.log(
` Subscriptions ready at ws://localhost:${port}${server.subscriptionsPath}`,
);
});
推荐阅读
- python-3.x - 如何迭代子列表的元素
- android - ReactNative 的 Picker 组件的 Mode 属性没有按预期工作?
- android - Android 10 (api-29) 文件写入
- python - 如何安排数据实验室 ipynb 定期运行
- javascript - 解析错误:保留关键字“类”
- webpack - laravel mix node_modules css-loader中的错误
- c# - WPF Datagrid - 突出显示数据更改行
- sql - 参考另一列更新列
- python - Trying to make a text/password manager
- php - Ger 用户 IPv4 地址通过 cloudflare 和 azure