Я использую Next. js + response-apollo + apollo-server + express для моего сайта. Недавно я добавил аутентификацию cook ie и, следовательно, должен был включить CORS на сервере, чтобы аутентификация куки работала. Однако я вижу, что запросы клиента apollo приводят к состоянию http 500 при выполнении на стороне сервера. Те же запросы, когда выполняются на стороне клиента, успешно разрешаются. Я озадачен, потому что я действительно ожидал, что проблемы произойдут на стороне клиента, потому что CORS оказывает большее влияние. Я не уверен, что является причиной проблемы, любые предложения будут очень приветствоваться!
Сама ошибка я следующим образом:
ApolloError: Ошибка сети: запрос к https://example.com/graphql/ ошибка, причина: запись EPROTO 140152723232576: ошибка: 14094410: процедуры SSL: ssl3_read_bytes: ошибка квитирования оповещения sslv3: ../ deps / openssl / openssl / ssl / record / rec_layer_s3. c: 1544: SSL номер предупреждения 40
at new ApolloError (/src/node_modules/apollo-client/bundle.umd.js:92:26)
at /src/node_modules/apollo-client/bundle.umd.js:1588:34
at /src/node_modules/apollo-client/bundle.umd.js:2008:15
at Set.forEach (<anonymous>)
at /src/node_modules/apollo-client/bundle.umd.js:2006:26
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (/src/node_modules/apollo-client/bundle.umd.js:2004:20)
at /src/node_modules/apollo-client/bundle.umd.js:1483:29
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
graphQLErrors: [],
networkError: FetchError: запрос к https://example.com/graphql/ не выполнен, причина: запись EPROTO 140152723232576: ошибка: 14094410: процедуры SSL: ssl3_read_bytes: Ошибка квитирования оповещения sslv3: ../ deps / openssl / openssl / ssl / record / rec_layer_s3. c: 1544: номер оповещения SSL 40
Я использую сертификат SSL, предоставленный Amazon Cloudfront .
Это мой код клиента:
_app.js
:
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
if (pageProps.errorStatusCode && ctx.res) {
ctx.res.statusCode = pageProps.errorStatusCode;
}
}
return { pageProps };
}
render() { //render... }
}
У меня есть HO C для запросов страниц:
const withQuery = (Page, query, variables, errorPolicy = 'none') => {
Page.getInitialProps = async ctx => {
const { apolloClient } = ctx;
try {
const { data } = await apolloClient.query({
query,
variables: vars,
errorPolicy
});
return { data };
} catch (error) {
return { errorStatusCode: error.networkError ? '500' : '404' };
}
};
// if (typeof window === 'undefined') { // THIS CODE IS CAUSING THE ISSUE
// return Page;
// }
}
Вот как я запускаю клиент apollo:
import withApollo from 'next-with-apollo';
import ApolloClient, { InMemoryCache } from 'apollo-boost';
import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import introspectionQueryResultData from '../../fragmentTypes.json';
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData
});
function createClient({ ctx, headers, initialState }) {
return new ApolloClient({
credentials: 'include',
uri: 'some_graphql_url',
cache: new InMemoryCache({ fragmentMatcher }).restore(initialState || {}),
headers
});
}
export default withApollo(createClient, { getDataFromTree: 'ssr' });
Это код моего сервера:
import cors from 'cors'
const express = require('express')
const { ApolloServer } = require('apollo-server-express')
const { schema } = require('./models')
const server = new ApolloServer({
schema,
})
// required settings to accept cookies
const corsOptions = {
origin: function (origin, callback) {
if (corsWhitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true)
} else {
callback(new Error(`${origin} - not allowed by CORS`))
}
},
credentials: true
}
let app = express()
app.use(cors(corsOptions))
server.applyMiddleware({ app, cors: false })
const serverUrl = `my_server_url`
app.listen({ port }, () => console.log(`? Server ready at ${serverUrl}`))
Сумма мои выводы:
- Проблема возникает, когда
_app.js
вызывает await Component.getInitialProps(ctx)
. getInitialProps
определяется в withQuery
HO C, где выполняется запрос apolloClient.query
методом.
Без CORS все также работает.
РЕДАКТИРОВАТЬ: Я заметил, что проблема начнется, когда опция headers
добавлено к createClient
вместе с CORS.
EDIT2: ошибка возникает даже без CORS, достаточно, чтобы опция headers
была добавлена к createClient
, создающему клиента apollo.