Предполетный ответ CORS не соответствует фактическому ответу

#node.js #express #cors #apollo #apollo-server

#node.js #выразить #cors #apollo #apollo-сервер

Вопрос:

В моем node.js сервер, на котором я включил CORS в качестве промежуточного программного обеспечения, вот так:

 app.use(cors({ origin: 'http://<CORRECT_ORIGIN_URL>:3030', credentials: true }))
  

Я использую Apollo Client в приложении, которое отправляет запрос, и установил учетные данные на ‘include’ при инициализации ApolloClient, вот так:

 // Create a WebSocket link
const wsLink = process.browser ? new WebSocketLink({
    uri: `ws://<CORRECT_REQUEST_URL>:8000/graphql`,
    options: {
        reconnect: true,
    },
}) : null

// Create an http link (use batch, allow cookies response from server)
const httpLink = new BatchHttpLink({
    uri: 'http://<CORRECT_REQUEST_URL>/api/',
    credentials: 'include'
})


// Split terminating link for websocket and http requests
const terminatingLink = process.browser ? split(
    ({ query }) => {
        const { kind, operation } = getMainDefinition(query)
        return kind === 'OperationDefinition' amp;amp; operation === 'subscription'
    },
    wsLink,
    httpLink,
) : httpLink

// Create Apollo client
const client = new ApolloClient({
    link: ApolloLink.from([authLink, errorLink, terminatingLink])
})
  

Когда я пытаюсь войти в систему, я вижу, что отправляется запрос параметров предполетной проверки и возвращается правильный ответ:

Заголовки запроса (ПАРАМЕТРЫ запроса)

 Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://<CORRECT_ORIGIN_URL>:3030
Referer: http://<CORRECT_ORIGIN_URL>/login
  

Заголовки ответа (запрос ПАРАМЕТРОВ)

 Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: http://<CORRECT_ORIGIN_URL>:3030
Connection: keep-alive
Content-Length: 0
Date: Wed, 20 Mar 2019 03:09:14 GMT
Server: nginx/1.15.5 (Ubuntu)
Vary: Origin, Access-Control-Request-Headers
X-Powered-By: Express
  

Тем не менее, когда отправляется фактический запрос POST, я получаю следующий ответ:

Заголовки ответа (POST-запрос)

 Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Wed, 20 Mar 2019 03:09:15 GMT
Server: nginx/1.15.5 (Ubuntu)
Transfer-Encoding: chunked
Vary: Accept-Encoding, Origin
X-Powered-By: Express
  

Я понятия не имею, почему заголовки ответа отличаются в запросе post, когда параметры предварительного запуска показывают, что это должно быть правильно.

Этот неправильный ответ POST приводит к следующему сообщению об ошибке на клиенте:

 Access to fetch at 'http://<CORRECT_REQUEST_URL/api/' from origin
'http://<CORRECT_ORIGIN_URL>:3030' 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'.
  

Я пробовал поискать решение в Google и stackoverflow, но ничего не могу найти. Есть идеи?

Ответ №1:

Я решил свою проблему.

Проблема в том, что сервер Apollo по умолчанию добавляет промежуточное программное обеспечение CORS, которое переопределяло мои настройки CORS. Из документации Apollo:

Укажите false, чтобы полностью удалить промежуточное программное обеспечение CORS, или true, чтобы использовать конфигурацию вашего промежуточного программного обеспечения по умолчанию.

Значение по умолчанию равно true.

Чтобы решить проблему, мне просто пришлось отключить функциональность CORS в Apollo, для чего просто потребовалась настройка cors: false в .applyMiddleware вот так:

 server.applyMiddleware({
    app,
    path: '/',
    cors: false,
});
  

Дополнительная ссылка:

Ответ №2:

У меня были похожие проблемы с прокси apache2, запущенным перед моими экспресс-службами. Прокси-сервер кэшировал некоторые (только некоторые!) ответы. Это то, что я добавил в конфигурацию apache, и это решило проблему:

 Header set Cache-Control "no-cache, must-revalidate"    env=no-cache-headers
Header set Pragma        "no-cache"                     env=no-cache-headers
Header set Expires       "Sat, 1 Jan 2000 00:00:00 GMT" env=no-cache-headers