Как исправить ошибку «Ответ на предварительный запрос не проходит проверку контроля доступа: у него нет статуса HTTP ok» в приложении реакции с API-интерфейсом nodejs

Я пытался выполнить вызов API (nodejs с экспресс-запуском на локальном хосте) из реагирующего приложения, работающего в браузере, через локальный сервер разработки (сервер разработки веб-пакета). Все работало хорошо, пока я не попытался вызвать API. Они оба работают на разных портах.

Я попытался добавить заголовки cors (рекомендуется MDN) как к почтовому вызову (из приложения в браузере), так и к ответу от Nodejs API, но ни один из них не решил проблему.

Код для вызова API (в браузере):

const headers = {
  'Content-Type': 'application/json',
  'access-token': '',
  'Access-Control-Allow-Origin': '*',
}

export default async () => {
  try {
    const body = JSON.stringify({
      test: true,
    })
    const response = await fetch('http://localhost:1337/internal/provider/check_email_exist', {
      method: 'POST',
      headers,
      body,
    })
    console.info(response)
  } catch (e) {
    return e
  }
}

Промежуточное ПО API (в nodejs):

// Verify All Requests
app.use(VerifyToken)

// Compress
app.use(compression())

// Helmet middlware
app.use(helmet())

// Body Parser
app.use(bodyParser.urlencoded({
  extended: false,
}))
app.use(bodyParser.json())

Ожидаемый результат — просто дать код состояния 200 и ответить данными.

Фактический результат:

OPTIONS http://localhost:1337/internal/provider/check_email_exist 404 (Not Found)
Access to fetch at 'http://localhost:1337/internal/provider/check_email_exist' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

Заголовок Access-Control-Allow-Origin должен исходить от сервера, а не от клиента. Вы можете попробовать использовать модуль cors (app.use(cors())), чтобы это заработало, но я предлагаю вам прочитать о CORS и о том, как он используется для защиты пользователей веб-браузера. Также похоже, что вы не реализовали маршрут для /internal/provider/check_email_exist, поэтому запрос в целом не работает.

Jake Holzinger 10.05.2019 20:37

Сервер, на который вы отправляете запрос, должен быть настроен для ответа на запросы OPTIONS с ответом 200 OK. Прямо сейчас он отвечает ошибкой 404 на запрос CORS preflight OPTIONS, который отправляет ваш браузер. Таким образом, у вас еще нет сервера с должным образом включенным CORS.

sideshowbarker 11.05.2019 02:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
4 003
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Поскольку вы используете webpack-dev-server, вы можете использовать опцию proxyDevServerProxy.

Ваша конфигурация будет выглядеть так:

// webpack.config.js
devServer: {
    proxy: {
      '/internal': 'http://localhost:1337'
    }
  }

Поскольку я не вижу ваших маршрутов express по вашему вопросу, я размышляю о прокси-маршруте, если ваш API живет на конечной точке /internal, тогда вам следует изменить свой код React следующим образом:

const response = await fetch('/internal/provider/check_email_exist', {
   method: 'POST',
   headers,
   body,
})

Как видите, я пропустил https://localhost:1337, потому что опция proxy из webpack-dev-server справится с этим и перенаправит на http://localhost:1337. Надеюсь, что это поможет вам. Привет, Зигфрид.

РЕДАКТИРОВАТЬ

Как указано в комментарии к вашему вопросу, вы должны установить заголовки на своем сервере express, а не на клиенте, для этой задачи вы можете использовать пакет cors-middleware.

Возможно, это может помочь, если вы столкнетесь с ошибками предварительной проверки.

Моя полная конфигурация:

const cors = require('cors');
const express = require('express');
const { createProxyMiddleware: proxy } = require('http-proxy-middleware');

...
const logLevel = 'info';
const ip = require('ip').address();

const proxyOptions = {
  xfwd: true,
  target,
  changeOrigin: true,
  logLevel,
  cookieDomainRewrite: {
    '*': 'localhost',
  },
  headers: {
    'X-Forwarded-For': ip,
    'X-Node': 'true',
  },
};

const backNginxApp = express();

backNginxApp.use(
  cors({
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    origin: 'http://localhost:3000',
    optionsSuccessStatus: 200,
    credentials: true,
  })
);
backNginxApp.use('/api', proxy(proxyOptions));

API: const target = 'https://someapi.com'

Локальная разработка работает по адресу: http://localhost:3000

Другие вопросы по теме