Как мне решить проблему CORS для приложения Angular, развернутого на heroku, с серверной частью Postgres express? - PullRequest
0 голосов
/ 05 августа 2020

Я развертываю свое приложение Angular и Postgres Express серверную часть на heroku, чтобы они могли общаться друг с другом. Большая проблема, с которой я сейчас сталкиваюсь, заключается в том, что всякий раз, когда я пытаюсь использовать методы выборки, он говорит, что мне нужен CORS или заголовок для него. Я уже установил его в моем express бэкэнде ниже:

const app = express();
const cors = require('cors');
const port = process.env.PORT || 5000;
const Pool = require('pg').Pool;
const transRoutes = require('./transactions');
const groupsRoutes = require('./budget-group');
const itemsRoutes = require('./budget_item');
const accRoutes = require('./account');

app.use(cors({origin: '*'})); //I also tried cors()
app.use(express.json());
app.use('/transactions', transRoutes);
app.use('/groups', groupsRoutes);
app.use('/items', itemsRoutes);
app.use('/accounts', accRoutes);
app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
 })

const pool = new Pool({
    connectionString: process.env.DATABASE_URL,
    ssl: {
        rejectUnauthorized: false
    }
});

app.get('/', (req, res) => {
    res.send('Welcome to your server.');
});

app.get('/users', async (req, res) => {
    try {
        const getAllUsers = await pool.query("SELECT * FROM users");
        res.json(getAllUsers);
    } catch (err) {
        console.log(err);
    }
});

app.get('/login/:username/:password', async (req, res) => {
    try {
        const getUser = await pool.query("SELECT * FROM users WHERE username = $1 AND password = $2",
        [
            req.params.username,
            req.params.password
        ]);
        res.json(getUser.rows);
    } catch (err) {
        console.log(err);
    }
});

//More routes omitted for brevity

app.listen(port, () => {console.log(`Listening on port ${port}`)});

Я думаю, что мой код подходит для бэкэнда, поэтому я чувствую, что код Angular является проблемой, но я не понять, как это исправить. Нужно ли мне вручную добавлять заголовок для каждого метода выборки, чтобы иметь функцию CORS, или мне нужно использовать какой-то прокси, который я нашел, но был слишком запутан, как это сделать?

Пример Метод выборки, который я сделал, приведен ниже:

fetch(`https://name-redacted.herokuapp.com/login/${this.username}/${this.password}`, {
        method: 'GET',
        headers: {'Content-Type': 'application/json'}
      }).then(res => res.json())
      .then(info => {
        if (info.length === 0) {
          this.failedAuth = true;
        } else {
          this.infoService.setUpLoginInfo(info[0]);
          this.router.navigateByUrl('/instructions');
        }
      });

Также для развертывания части angular я следовал этому руководству: https://youtu.be/KVFrTf4VD2o Я просто подумал, что это может быть важно, поскольку он использует сервер express для передачи файлов вместо выполнения ng serve после сборки приложения.

Изменить: для ошибки CORS: доступ для выборки в 'https://app-backend.herokuapp.com/register' из источника 'https://app-project.herokuapp.com' был заблокировано политикой CORS: на запрошенном ресурсе отсутствует заголовок Access-Control-Allow-Origin. Если непрозрачный ответ соответствует вашим потребностям, установите режим запроса на 'no-cors', чтобы получить ресурс с отключенным CORS.

Заголовки: Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept Access-Control-Allow-Methods не отображается.

Ответы [ 2 ]

0 голосов
/ 06 августа 2020

Я смог понять, как решить мою проблему. Комментарий @ WiktorZychla был правильным в том смысле, что любой запрос с учетными данными приведет к тому, что * не будет работать. Источник Чтобы исправить это, я нашел другое обсуждение, где они поместили:

const allowedOrigins = ['https://someapp.com'];
app.use(cors({
    credentials: true,
    origin: (origin, callback) => {
      if (allowedOrigins.includes(origin)) {
        callback(null, true) 
      } else {
        callback(new Error(`Origin: ${origin} is now allowed`))
      }
    }
  }));

Сначала вы создаете массив allowedOrigins, чтобы поместить любые URL-адреса, которые вы используете для доступа к API. Затем вы позволяете своему серверу использовать объект cors, который разрешает учетные данные, а затем проверяет источник запроса. Если источник существует в массиве, он вернет обратный вызов, который позволяет работать каждому запросу.

Также, если у вас есть отдельные маршруты, как я делаю ниже:

const transRoutes = require('./transactions');
const groupsRoutes = require('./budget-group');
const itemsRoutes = require('./budget_item');
const accRoutes = require('./account');
app.use('/transactions', transRoutes);
app.use('/groups', groupsRoutes);
app.use('/items', itemsRoutes);
app.use('/accounts', accRoutes);

Затем в каждом route файл, вам нужно скопировать информацию о cors, которая есть у меня вверху, и изменить ее, чтобы на каждом маршрутизаторе был настроен cors. Может быть другое решение, но это было для меня самым быстрым.

0 голосов
/ 06 августа 2020

Возможно, ваш сервер просто не готов обрабатывать предполетные запросы. Похоже, у вас нет маршрута, который обрабатывает HTTP-метод OPTIONS, каким был бы предполетный запрос. В документации Express 'по CORS есть пример обработки предполетных запросов

Самый простой способ включить его для всех запросов, согласно документации, - это настроить маршрут, который обрабатывает ОПЦИИ как таковые:

app.options('*', cors())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...