与 'ws://localhost:4444/subscriptions' 的 WebSocket 连接失败:WebSocket 在建立连接之前关闭
WebSocket connection to 'ws://localhost:4444/subscriptions' failed: WebSocket is closed before the connection is established
OS: Windows 10 专业版
快递:4.17.1
apollo-server-express: 2.9.13
apollo-client: 2.6.4
apollo-link-context: 1.0.18
apollo-link-http: 1.5.15
apollo-link-ws: 1.0.18
所以,我正在从 graphql-yoga 迁移到 apollo-server 2,并且遇到了 ws 连接问题(见图)。我忽略了什么?
我的代码如下:
withData.js
const endpoint = `http://localhost:4444/graphql`;
const endpointWS = `ws://localhost:4444/subscriptions`;
const httpLink = createHttpLink({
uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
credentials: 'include',
});
const wsLink = process.browser ? new WebSocketLink({
uri: process.env.NODE_ENV === 'development' ? endpointWS : prodEndpointWS,
options: {
reconnect: true,
timeout: 3000,
}
}) : null;
const authLink = setContext(() => {
return {
headers: {
...headers,
}
}
});
const link = process.browser ? split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
) : httpLink;
index.js
const PORT = '4444';
const path2 = '/graphql';
const createServer = require('./createServer');
const server = createServer();
const app = express();
app.use(cookieParser());
server.applyMiddleware({
app,
path: path2,
cors: {
credentials: true,
origin: process.env.FRONTEND_URL,
},
});
const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);
httpServer.listen(PORT, err => {
if (err) throw err
console.log(` Server ready at http://localhost:${PORT}${server.graphqlPath}`)
console.log(` Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`)
});
createServer.js
const Mutation = require('./resolvers/Mutation');
const Query = require('./resolvers/Query');
const Subscription = require('./resolvers/Subscription');
const db = require('./db');
const typeDefsFile = importSchema(__dirname.concat('/schema.graphql'));
const typeDefs = gql(typeDefsFile);
function createServer() {
return new ApolloServer({
typeDefs,
resolvers: {
Mutation,
Query,
Subscription,
},
cors: {
credentials: true,
origin: process.env.FRONTEND_URL,
},
subscriptions: {
keepAlive: 1000,
path: '/subscriptions',
},
playground: process.env.NODE_ENV === 'production' ? false : '/',
tracing: true,
introspection: true,
context: req => ({ ...req, db }),
});
}
module.exports = createServer;
db.js
const { Prisma } = require('prisma-binding');
const db = new Prisma({
typeDefs: __dirname + "/schema_prep.graphql",
endpoint: process.env.PRISMA_ENDPOINT,
secret: process.env.PRISMA_SECRET,
debug: false,
});
module.exports = db;
Subscriptions.js
const Subscription = {
item: {
subscribe: async (parent, args, ctx, info) => {
const itemResult = await ctx.db.subscription
.item({
where: {
mutation_in: ['CREATED', 'UPDATED'],
},
},
info
);
return itemResult;
},
},
itemDeleted: {
subscribe: (parent, args, ctx, info) => {
const selectionSet = `{ previousValues { id, userIdentity } }`
return ctx.db.subscription.item(
{
where: {
mutation_in: ['DELETED'],
},
},
selectionSet,
);
},
resolve: (payload, args, context, info) => {
return payload ? payload.item.previousValues : payload
},
},
};
module.exports = Subscription;
我通过将查询和突变解析器中上下文的响应和请求属性分别从 ctx.response 和 ctx.request 更改为 ctx.res 和 ctx.req 来解决这个问题.
OS: Windows 10 专业版
快递:4.17.1
apollo-server-express: 2.9.13
apollo-client: 2.6.4
apollo-link-context: 1.0.18
apollo-link-http: 1.5.15
apollo-link-ws: 1.0.18
所以,我正在从 graphql-yoga 迁移到 apollo-server 2,并且遇到了 ws 连接问题(见图)。我忽略了什么?
我的代码如下:
withData.js
const endpoint = `http://localhost:4444/graphql`;
const endpointWS = `ws://localhost:4444/subscriptions`;
const httpLink = createHttpLink({
uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
credentials: 'include',
});
const wsLink = process.browser ? new WebSocketLink({
uri: process.env.NODE_ENV === 'development' ? endpointWS : prodEndpointWS,
options: {
reconnect: true,
timeout: 3000,
}
}) : null;
const authLink = setContext(() => {
return {
headers: {
...headers,
}
}
});
const link = process.browser ? split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
) : httpLink;
index.js
const PORT = '4444';
const path2 = '/graphql';
const createServer = require('./createServer');
const server = createServer();
const app = express();
app.use(cookieParser());
server.applyMiddleware({
app,
path: path2,
cors: {
credentials: true,
origin: process.env.FRONTEND_URL,
},
});
const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);
httpServer.listen(PORT, err => {
if (err) throw err
console.log(` Server ready at http://localhost:${PORT}${server.graphqlPath}`)
console.log(` Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`)
});
createServer.js
const Mutation = require('./resolvers/Mutation');
const Query = require('./resolvers/Query');
const Subscription = require('./resolvers/Subscription');
const db = require('./db');
const typeDefsFile = importSchema(__dirname.concat('/schema.graphql'));
const typeDefs = gql(typeDefsFile);
function createServer() {
return new ApolloServer({
typeDefs,
resolvers: {
Mutation,
Query,
Subscription,
},
cors: {
credentials: true,
origin: process.env.FRONTEND_URL,
},
subscriptions: {
keepAlive: 1000,
path: '/subscriptions',
},
playground: process.env.NODE_ENV === 'production' ? false : '/',
tracing: true,
introspection: true,
context: req => ({ ...req, db }),
});
}
module.exports = createServer;
db.js
const { Prisma } = require('prisma-binding');
const db = new Prisma({
typeDefs: __dirname + "/schema_prep.graphql",
endpoint: process.env.PRISMA_ENDPOINT,
secret: process.env.PRISMA_SECRET,
debug: false,
});
module.exports = db;
Subscriptions.js
const Subscription = {
item: {
subscribe: async (parent, args, ctx, info) => {
const itemResult = await ctx.db.subscription
.item({
where: {
mutation_in: ['CREATED', 'UPDATED'],
},
},
info
);
return itemResult;
},
},
itemDeleted: {
subscribe: (parent, args, ctx, info) => {
const selectionSet = `{ previousValues { id, userIdentity } }`
return ctx.db.subscription.item(
{
where: {
mutation_in: ['DELETED'],
},
},
selectionSet,
);
},
resolve: (payload, args, context, info) => {
return payload ? payload.item.previousValues : payload
},
},
};
module.exports = Subscription;
我通过将查询和突变解析器中上下文的响应和请求属性分别从 ctx.response 和 ctx.request 更改为 ctx.res 和 ctx.req 来解决这个问题.