Итак, я перехожу на apollo-server-express 2.3.3 (я использовал 1.3.6) Я следовал нескольким руководствам, внося необходимые изменения, но застрял в проблеме CORS.
В соответствии с документы вы должны использовать функцию applyMiddleware для подключения сервера apollo к экспресс.
В настоящее время я делаю следующее:
const app = express();
// CORS configuration
const corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
app.use(cors(corsOptions))
// Setup JWT authentication middleware
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
} catch(e) {
console.error(e);
}
}
next();
});
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});
server.applyMiddleware({ app });
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.info(`Server listening on ${PORT}`);
})
По какой-то причине мое экспресс-промежуточное ПО, похоже, не выполняется, когда я пытаюсь выполнить запрос с локального хоста: 3000 (клиентское приложение), я получаю типичную ошибку CORS.
С apollo-server-express 1.3.6 я без проблем делал следующее:
app.use(
'/graphql',
graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }),
bodyParser.json(),
graphqlExpress(({ currentUser }) => ({
schema,
context: {
// Pass Mongoose models
Property,
User,
currentUser
}
}))
);
Теперь с новой версией, хотя в документах это выглядит как простая миграция, я, похоже, не могу заставить ее работать. Я проверил различные статьи, и, кажется, ни у кого нет проблемы.





Насколько я понимаю сервер Apollo API промежуточного программного обеспечения, параметры CORS, параметры анализатора тела и конечная точка graphql рассматриваются как специальные объекты, которые должны передаваться непосредственно объекту параметров applyMiddleware.
Итак, вы хотите попробовать следующую конфигурацию:
const app = express();
// CORS configuration
const corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
// The following is not needed, CORS middleware will be applied
// using the Apollo Server's middleware API (see further below)
// app.use(cors(corsOptions))
// Setup JWT authentication middleware
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
} catch(e) {
console.error(e);
}
}
next();
});
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});
// There is no need to explicitly define the 'path' option in
// the configuration object as '/graphql' is the default endpoint
// If you planned on using a different endpoint location,
// this is where you would define it.
server.applyMiddleware({ app, cors: corsOptions });
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.info(`Server listening on ${PORT}`);
})
Последняя версия apollo-server (2.4.8) выдает ошибку при вызове метода applyMiddleware: "To use Apollo Server with an existing express application, please use apollo-server-express"
@KarelFrajták да, метод applyMiddleware предоставляется пакетами apollo-server-{integration}, как указано apollographql.com/docs/apollo-server/api/…
@KarelFrajták, чтобы быть ясным, я не упомянул о необходимости этого пакета, поскольку ОП заявил, что он использовал apollo-server-express, который предоставляет метод
@Jaxx Я только что столкнулся с похожей проблемой, а также возникла путаница на соответствующих страницах GitHub.
Использование "apollo-client": "^2.5.1", и это решение сработало. Обратите внимание только на то, что если вы используете apollo-upload-client для клиентской ссылки, метод createUploadLink принимает параметр fetchOptions, где вы определяете credentials: 'include'.
Большое спасибо, это спасло меня, @ThomasHennes. Я обновлю документы, это обязательно должно быть где-то написано
В Apollo Server 2.x вы указываете поле cors в конструкторе ApolloServer.
Итак, в вашем случае это должно выглядеть следующим образом:
const corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
// Setup JWT authentication middleware
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
} catch(e) {
console.error(e);
}
}
next();
});
const server = new ApolloServer({
typeDefs,
cors: cors(corsOptions),
resolvers,
context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});
server.applyMiddleware({ app });
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.info(`Server listening on ${PORT}`);
})
Здесь вы найдете все параметры, принимаемые сервером apollo: https://www.apollographql.com/docs/apollo-server/api/apollo-server.html#Параметры-2
Здесь вы найдете соответствующее обсуждение: https://github.com/apollographql/apollo-сервер/issues/1142
Настройки CORS берутся из ExpressJS, а не из ApolloServer. Если вы хотите добавить пользовательское или подстановочное происхождение, вы должны обработать его с помощью функции обратного вызова/обработчика.
const server = new ApolloServer({
....,
cors: {
credentials: true,
origin: (origin, callback) => {
const whitelist = [
"http://site1.com",
"https://site2.com"
];
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error("Not allowed by CORS"))
}
}
}
});
По умолчанию промежуточное ПО Express создает экземпляр промежуточного ПО cors с параметрами по умолчанию в пути graphql, переопределяя любую конфигурацию промежуточного ПО cors, которую вы сами указали для других путей (!)
Вы можете переопределить значения по умолчанию при применении промежуточного программного обеспечения apollo, например.
apollo.applyMiddleware({ app, cors: {credentials: true, origin: true} })
Я использую apollo-server-express 2.17.
Я думаю, что это должен быть принятый ответ. Это единственный ответ, который сработал для меня.