#express #server #graphql
#выражать #сервер #graphql
Вопрос:
У меня есть сервер node / graphql, работающий на sitename.com: 3333 Я создал другой сервер, на котором я работаю на sitename.com: 3334
Я могу отправлять запросы на сервер по адресу sitename.com:3333 с sitename.com а также subdomain.sitename.com
Но если я попытаюсь подключиться к sitename.com:3334 (просто другой порт) из subdomain.sitename.com это дает мне ошибку cors:
Заблокирован запрос из разных источников: политика одного и того же источника запрещает чтение удаленного ресурса в https://sitename.com:3334/graphql . (Причина: запрос CORS не был выполнен успешно)
Я открыл порты в брандмауэре и настроил ssl на сервере и клиенте.
Пожалуйста, помогите!
Код клиента приведен ниже:
import { ApolloClient } from 'apollo-client'
import { withClientState } from 'apollo-link-state'
import { HttpLink } from 'apollo-link-http'
import { Agent } from 'https'
import fs from 'fs'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { setContext } from 'apollo-link-context'
import { onError } from 'apollo-link-error'
import { ApolloLink } from 'apollo-link'
import decode from 'jwt-decode'
import history from '../history'
import Cookies from 'universal-cookie'
import {
APP,
AUTH,
CLIENT_AUTH_REQUEST_TYPE,
CLIENT_AUTHENTICATION_METHOD,
JWT,
VERSION
} from '../environment'
import https from 'https'
import { defaults, resolvers } from '../api'
import { createUploadLink } from 'apollo-upload-client'
const { CONSTANTS: { UNAUTHORIZED, FORBIDDEN } = {} } = APP
const cookies = new Cookies()
const opts = {
credentials: 'same-origin',
headers: {
'frontend-version': VERSION,
[AUTH.STRATEGIES.CLIENT.AUTH_HEADER]: CLIENT_AUTH_REQUEST_TYPE
}
}
const useLocalStorage = CLIENT_AUTHENTICATION_METHOD.LOCAL_STORAGE
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
// const apolloCache = new InMemoryCache();
const apolloCache = new InMemoryCache({
// dataIdFromObject: e => `${e.__typename}_${e.id}` || null // eslint-
disable-line no-underscore-dangle
})
// const watchedMutationLink = new WatchedMutationLink(apolloCache,
watchedMutations);
const stateLink = withClientState({
cache: apolloCache,
defaults,
resolvers
})
const uploadLink = createUploadLink({
// uri: 'http://localhost:3333/graphql',
uri: 'https://demo.MYSITE.in:3334/graphql',
fetchOptions: {
agent: new https.Agent()
}
})
const httpLink = new HttpLink({
uri: 'https://demo.MYSITE.in:3334/graphql',
...opts
})
const TOKEN_NAME = 'x-connector-token'
const authLink = new ApolloLink((operation, forward) => {
operation.setContext(({ headers = {} }) => {
const token = cookies.get('token')
if (token) {
headers = { ...headers, 'x-connector-token': token }
}
return { headers }
})
return forward(operation)
})
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors amp;amp; graphQLErrors.filter(e => e).length > 0) {
graphQLErrors.map(({ message = '', status = 200 }) => {
if (UNAUTHORIZED === message || status === 401) {
if (
history amp;amp;
history.location amp;amp;
history.location.pathname !== '/login'
) {
history.push('/login')
}
}
if (FORBIDDEN === message || status === 403) {
history.push(`/error-page/403`)
}
return null
})
}
if (networkError amp;amp; networkError.statusCode === 401) {
// eslint-disable-next-line
history.push('/login')
}
if (networkError amp;amp; networkError.statusCode === 403) {
// Do something
}
if (networkError amp;amp; networkError.statusCode === 400) {
// Do something
}
if (networkError amp;amp; networkError.statusCode >= 500) {
// eslint-disable-next-line
history.push(`/error-page/${networkError.statusCode}`)
}
})
let links = [errorLink, stateLink, httpLink]
links = [
errorLink,
stateLink,
// afterwareLink,
// authMiddlewareLink,
authLink,
// watchedMutationLink,
// httpLink,
uploadLink
]
const link = ApolloLink.from(links)
export default new ApolloClient({
link,
cache: apolloCache,
connectToDevTools: true,
// opts: {
// agent
// },
fetchOptions: {
agent: new https.Agent()
// rejectUnauthorized: false
},
defaultOptions: {
query: {
errorPolicy: 'all'
}
},
onError: ({ networkError, graphQLErrors }) => {}
})
Код сервера:
const app = express();
// tried this too
const corsOptions = {
origin: 'https://demo.MYSITE.in',
}
// also tried app.use(cors)
app.use(cors({
'allowedHeaders': ['Content-Type'],
'origin': '*',
'preflightContinue': true
}));
app.use(helmet());
// app.use(cors());
Комментарии:
1. забыл упомянуть, что клиенты — это сборки приложений node / express, установленные на nginx
Ответ №1:
Браузер не будет отправлять запросы на сервер, источник которого отличается от источника, с которого была отправлена сама веб-страница (а другой порт представляет собой другой источник), если вы специально не включите этот запрос для этого нового источника на своем сервере. Это проблема CORs, о которой есть миллионы сообщений и статей о том, как справиться. Поскольку вы не показываете свой код в своем вопросе, мы не можем рекомендовать конкретное исправление кода для вашего кода.
Ваш сервер должен поддерживать конкретный запрос CORS, который вы пытаетесь выполнить. Если вы используете Express, то модуль CORS выполняет большую часть работы за вас, если он правильно реализован. CORS существует для защиты вашего сайта, поэтому Javascript на веб-страницах других людей, запускаемых из браузера, не может произвольно использовать ваши API, поэтому будьте осторожны с тем, что именно вы открываете для запросов CORS.
И, поскольку это кажется вам новой проблемой, я бы настоятельно рекомендовал вам прочитать и узнать о том, что такое CORs и как он работает.
Кроме того, обратите внимание, что существуют «простые» CORS-запросы и «запросы с предварительной обработкой» (непростые запросы), и для включения запросов с предварительной обработкой требуется дополнительная работа. Браузер решает, является ли данный запрос перекрестного происхождения простым или требует предварительной обработки, на основе точных параметров запроса, и вашему серверу приходится выполнять больше действий, чтобы разрешить предварительные запросы.
Комментарии:
1. Клиентская страница выполняется на nginx, сервер на порту 3333. сервер не обслуживает страницу, он обслуживается nginx
2. @rainmaker — я не уверен, что означает этот комментарий. Дело в том, что вы пытаетесь отправить запрос Javascript на другой порт, отличный от того, откуда поступает страница, чтобы сделать его перекрестным источником. Таким образом, серверу потребуется специальная поддержка перекрестного происхождения для этого конкретного типа запроса, прежде чем браузер разрешит его. Читали ли вы что-нибудь о том, как применяются ограничения CORs и как включить доступ CORs? Все это довольно ванильный материал, описанный в тысячах сообщений и статей. Я ответил на несколько вопросов по этой самой теме только сегодня в stackoverflow.
3. возможно, я не понял. Сервер, который работает на порту 3333, является сервером graphql. Он не обслуживает никаких страниц. Клиентское приложение является отдельным и выполняется на nginx, установленном в том же окне. Я прочитал документ cors, но пока не смог найти решение.
4. Ну, сервер graphql должен включить CORs.
5. Я пробовал это и многие другие варианты… безуспешно! const app = express(); // CORS промежуточное ПРОГРАММНОЕ обеспечение const allowCrossDomain = function(req, res, next) { res.header(‘Access-Control-Allow-Origin’, ‘demo. MYSITE.in ‘); res.header(‘Access-Control-Allow-Methods’, ‘GET,PUT,POST,DELETE’); res.header(‘Access-Control-Allow-Headers’, ‘Content-Type’); next(); } app.use(шлем()); const corsOptions = { origin: ‘ демонстрация. MYSITE.in ‘ } //app.use(cors(corsOptions)); app.use(cors); app.use(morgan(‘dev’));