Я создал простой чат graphQL с сервером Apollo и клиентом Apollo.
Он также использует файлы cookie сеанса, поэтому я инициализировал сервер с пакетом npm cors следующим образом:
app.use(
cors({
credentials: true,
origin: "http://localhost:3000"
})
);
На стороне клиента я использую клиент apollo и создаю http-ссылку следующим образом:
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql",
credentials: "include"
});
Поэтому я включаю учетные данные, и сервер имеет источник моего клиента (который действительно http://локальный: 3000 — по умолчанию create-реагировать-приложение).
Когда я хочу выполнить запрос, я получаю эту ошибку в консоли браузера:
Access to fetch at 'http://localhost:4000/graphql' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
Почему в заголовке ответа указано, что подстановочный знак * установлен, но в cors я установил конкретное происхождение, так что это не должно быть подстановочным знаком, верно?
Что мне здесь не хватает, ребята? Я также перезапустил оба сервера, конечно.
Когда я устанавливаю клиент следующим образом:
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql",
credentials: "same-origin"
});
Я не получаю сообщение об ошибке от cors, но я не получаю файл cookie с сервера. Файлы cookie работают, потому что на GraphQL Playground все работает как положено.
Если вы хотите увидеть полный код: https://github.com/SelfDevTV/graphql-простой-чат





Проблема решена.
В моем index.js файле с сервера.
Несколькими строками ниже я применяю экспресс-приложение в качестве промежуточного программного обеспечения к экземпляру сервера apollo следующим образом:
server.applyMiddleware({ app });
Но это переопределяет параметры cors, которые я установил выше.
Поэтому я должен назвать это так: server.applyMiddleware({ app, cors: false });
Теперь все работает отлично :)
Он действительно отключается? Потому что это будет означать, что учетные данные не будут переданы клиенту? То есть куки не работали бы, а они так делают? Мне установить этот прокси-сервер, который вы упомянули в package.json, из папки create-react-app или package.json сервера?
Да, cors: false отключает cors, что не имеет ничего общего с учетными данными или файлами cookie. Это защита безопасности, которая гораздо лучше объяснена здесь: medium.com/@baphemot/understanding-cors-18ad6b478e2b Что касается прокси-сервера, вы помещаете его в свой реактивный package.json.
Хорошо, когда я установил этот прокси. Что конкретно мне делать дальше. Включите cors с помощью пакета cors следующим образом: app.use( cors({ credentials: true, origin: ["http://localhost:3000"] }) ); А также установите cors:true на экземпляре сервера apollo? А на клиенте я могу установить {credentials: "same-origin" }? Это правильно так? Обновлено: Так не работает. same-origin работает, но нет файла cookie. include та же ошибка cors с подстановочным знаком.
Вам не нужно делать что-либо явно с обеих сторон, просто установите прокси на стороне реагирования, и он нажмет http://localhost:4000, как если бы он нажал http://localhost:3000. Вот официальные документы: facebook.github.io/create-react-app/docs/…
Другое дело, что я пробовал. * Установите прокси на package.json * отключите пакет cors * включите cors вот так на сервере: server.applyMiddleware({ app, cors: { credentials: true, origin: "http://localhost:3000" } }); Это работает, но не когда я устанавливаю origin: same-origin на клиенте, так что это все еще небезопасно для производства, когда я использую include верно?
Реактивный прокси работает только в разработке. Для производства вы захотите обслуживать как реагирующую сборку, так и конечные точки API с одного и того же (экспресс?) веб-сервера, чтобы это не было запросом на перекрестное происхождение. Это не работает в среде разработки, потому что обычно вы начинаете реагировать с npm run start, а сервер — с чем-то вроде npm run server, и они не могут использовать один и тот же порт. Реагирующий прокси решает эту проблему. Для prod вам понадобится статическая сборка и обслуживайте ее оттуда, где вы обслуживаете API.
Вы нашли решение для этого? у меня точно такая же проблема
Привет, да, моя проблема решена, см. мое решение там.
Некоторые комментарии здесь заставили меня немного обеспокоиться, что, возможно, обработка CORS просто отключена cors: false . Я протестировал его и убедился, что промежуточное ПО CORS приложения действительно вызывается для всех вызовов gql. Отличный совет.
Вместо этого вы можете указать серверу Apollo, как настроить cors.
const corsOptions = {
origin: "http://localhost:3000",
credentials: true
}
server.applyMiddleware({
app,
cors: corsOptions
})
Затем вы можете полностью исключить промежуточное ПО Express Cors.
Это сработало для меня. Я думаю, что это должен быть принятый ответ.
Когда я использовал http://localhost:3000 или true в качестве источника, это работало, но не когда я добавлял *, / или /* в конце URL-адреса, например. http://localhost:3000/. Я также добавил это как переменную в свой файл env.dev: CLIENT_URL=http://localhost:3000, а затем загрузил его в индекс сервера через origin: process.env.CLIENT_URL, что сработало хорошо.
Это просто отключение cors. Лучшим решением было бы настроить прокси для локальной разработки в вашем package.json
"proxy": "http://localhost:4000/",, который указывает реагировать на прокси-порт 4000 через ваше приложение для разработки. Для производства вам необходимо объединить сервер и внешний интерфейс вместе.