Публикация во внешний API вызывает CORS, но работает от Postman

Я использую i mgur api для загрузки изображений через узел js приложение.

Я конвертирую изображения в строки base64 и отправляю их через Postman, отлично работает.

Я использую node-fetch для вызовов API.

const fetch = require('node-fetch')
...
async uploadImage(base64image) {
        try {
            const url = 'https://api.imgur.com/3/image'
            const res = await fetch(url,
                {
                    method: 'POST',
                    body: { image: base64image },
                    headers: {
                        'content-type': 'application/json',
                        'Authorization': 'Client-ID [my-client-id]',
                        'Access-Control-Allow-Headers': 'Content-Type, Authorization, Access-Control-Allow-Headers',
                        'Access-Control-Allow-Methods': 'POST',
                    }
                }
            )

            console.log(res)
        } catch(err) {
            console.log(err)
        }
    }

Ошибка: доступ к загрузке по адресу 'https://api.imgur.com/3/image 'from origin' http://localhost:3000 'заблокирован политикой CORS: заголовок запроса поле Access-Control-Allow-Headers не разрешено с помощью Access-Control-Allow-Headers в предпечатном ответе.

Я пробовал много заголовков Access-Control-Allow-xxx, но ни один из них не работал.

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


person Cristian G    schedule 08.12.2018    source источник
comment
CORS - это исключительно проблема браузера, почтальон больше похож на сервер.   -  person ABOS    schedule 08.12.2018
comment
Мне все еще нужно исправить это, чтобы мое приложение работало, верно? @ABOS   -  person Cristian G    schedule 08.12.2018
comment
Я знаю. Я просто сказал, что CORS не имеет ничего общего с почтальоном. чтобы другие люди не были сбиты с толку вашим наблюдением   -  person ABOS    schedule 08.12.2018
comment
А, ладно, я думал, ты имел в виду, что это можно обойти   -  person Cristian G    schedule 08.12.2018
comment
извините за путаницу. его нельзя обойти без разрешения сервера. в противном случае это нарушение безопасности   -  person ABOS    schedule 08.12.2018
comment
Та же проблема @TheMaster   -  person Cristian G    schedule 08.12.2018


Ответы (3)


Браузер ограничивает HTTP-запросы тем, что они находятся в том же домене, что и ваша веб-страница, поэтому вы не сможете использовать imgur api непосредственно из браузера, не столкнувшись с проблемой CORS.

Я конвертирую изображения в строки base64 и отправляю их через Postman, отлично работает.

Это связано с тем, что Postman не является браузером и не ограничивается политикой CORS.

Я пробовал много заголовков Access-Control-Allow-xxx, но ни один из них не работал.

Эти заголовки должны быть возвращены сервером в ответ - в вашем случае сервером imgur. Вы не можете установить их в запросе из браузера, поэтому он никогда не сработает.

Ошибка: доступ к выборке на "https://api.imgur.com/3/image" from origin 'http://localhost:3000' заблокирован политикой CORS: поле заголовка запроса Access-Control-Allow- Заголовки не разрешены Access-Control-Allow-Headers в предпечатном ответе.

Возможные решения вашей проблемы:

  1. Если у вас есть доступ к внутреннему api, вы можете установить заголовок «Access-Control-Allow-Origin» на сервере и позволить своему приложению получить доступ к api, но, поскольку у вас не будет доступа к серверу imgur, вы, вероятно, сможете ' не делай этого.

  2. Отключите CORS в браузере - вы можете использовать такой плагин, как: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en. Этот обходной путь подходит для разработки. Плагин отключит ваши настройки CORS, и вы сможете нажать imgur apis.

  3. Третье решение - использование прокси. Вы можете настроить небольшой сервер узла с помощью express. Затем вы попадете на свой собственный сервер node, который, в свою очередь, попадет в imgur api. Поскольку сервер node не является средой браузера, у него не будет проблем с CORS, и вы сможете получить доступ к imgur API таким образом. Это также причина, по которой вы смогли без проблем использовать API из Postman. Поскольку Postman не является браузерной средой, она не ограничивается политикой CORS.

person Jatin Gupta    schedule 07.09.2019
comment
Ссылка на магазин Chrome не работает, но я нашел другое расширение, которое помогло. Спасибо, сэр, вы заслужили голосование "вверх" !!! - person Rodrigo; 05.02.2020
comment
Допустим, я использую расширение и отключаю его локально. Что произойдет, когда я его разверну? Не будут ли пользователи заблокированы вещью cors? - person Cristian G; 06.03.2021

Это потому, что Access-Control-Allow-Headers, Access-Control-Allow-Methods - это заголовки, которые использует сервер. Сервер добавляет заголовок с помощью промежуточного программного обеспечения.

Теперь представьте, что на сервере (в этом примере ниже - экспресс-сервер) с включенным CORS устанавливаются такие заголовки (по умолчанию):

app.use(function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Accept');
});

И вы отправляете Access-Control-Allow-Headers со стороны клиента, и сервер видит это как заголовок, не внесенный в белый список.

Итак, в заголовках просто используйте это:

headers: {
    'content-type': 'application/json',
    'Authorization': 'Client-ID [my-client-id]'
}

Должно работать нормально.

Кстати, я думаю, что он работает с почтальоном, потому что:

  • Почтальон не может установить определенные заголовки, если вы не установите это крошечное расширение захвата почтальона.
  • Безопасность браузера останавливает запросы на перекрестное происхождение. Если вы отключите защиту Chrome, он будет выполнять любой запрос CORS без проблем.

Кроме того, согласно этому:

Я считаю, что, скорее всего, Chrome не поддерживает localhost для прохождения Access-Control-Allow-Origin - см. проблему с Chrome

Чтобы Chrome отправлял Access-Control-Allow-Origin в заголовке, просто укажите псевдоним вашего localhost в файле / etc / hosts на какой-то другой домен, например:

127.0.0.1   localhost yourdomain.com

Затем, если вы обращаетесь к своему скрипту, используя yourdomain.com вместо localhost, вызов должен быть успешным.

Примечание: я не думаю, что тип контента должен быть application/json, он должен быть похож на image/jpeg или что-то в этом роде. Или, может быть, не включайте этот заголовок, если он не работает.

person Aritra Chakraborty    schedule 08.12.2018
comment
Я использовал application/json в Postman, и это сработало, я не думаю, что в этом проблема. Я удалил дополнительные заголовки и оставил только content-type и authorization, и это сообщение об ошибке, которое я получаю: Доступ к выборке в 'api.imgur.com/3/image 'from origin' localhost: 3000 'заблокирован Политика CORS: в запрошенном ресурсе отсутствует заголовок Access-Control-Allow-Origin. Если непрозрачный ответ соответствует вашим потребностям, установите для режима запроса значение «no-cors», чтобы получить ресурс с отключенным CORS. - person Cristian G; 08.12.2018
comment
Хорошо, как насчет добавления этого в свой заголовок 'Access-Control-Allow-Headers': 'Content-Type, Authorization' - person Aritra Chakraborty; 08.12.2018
comment
Теперь я вернулся к исходному сообщению об ошибке Access to fetch at 'https://api.imgur.com/3/image' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers in preflight response. - person Cristian G; 08.12.2018
comment
Из запроса CURL к их API я вижу, что вам нужен только auth. И, необязательно, тип контента. curl --request POST \ --url https://api.imgur.com/3/image \ --header 'Authorization: Client-ID {{clientId}}' \ --header 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \ --form image=R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7 - person Aritra Chakraborty; 08.12.2018
comment
Отредактировал ответ, кажется, chrome / ff не поддерживает localhost для cors - person Aritra Chakraborty; 08.12.2018
comment
Я добавил 127.0.0.1 localhost ttttestdomain.com в свой файл hosts (все остальное в нем прокомментировано) и добавил заголовок 'Access-Control-Allow-Origin': '*', но он выдает ту же ошибку, и я вижу, что он не использует псевдоним, он все еще говорит Access to fetch at 'https://api.imgur.com/3/image' from origin 'http://localhost:3000' has been blocked by CORS policy.. - person Cristian G; 08.12.2018
comment
да, но вы открываете ttttestdomain.com:3000 и оттуда тестируете? или все еще пользуетесь localhost:3000? - person Aritra Chakraborty; 08.12.2018
comment
Вы правы, я делал это неправильно. Открыл с ttttestdomain.com:3000 но выкидывает Access to fetch at 'https://api.imgur.com/3/image' from origin 'http://ttttestdomain.com:3000' has been blocked by CORS policy: Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response. :( - person Cristian G; 08.12.2018
comment
Я сдаюсь, я буду использовать хранилище firebase для хранения фотографий и покончить с этим. Большое вам спасибо за вашу помощь и время !! - person Cristian G; 08.12.2018
comment
Одно: можете ли вы просто использовать axios вместо node-fetch? Кроме того, вы можете попробовать ввести: jsonp (я имею в виду, прежде чем сдаться) - person Aritra Chakraborty; 08.12.2018

У меня есть несколько наблюдений в моем собственном приложении, которые помогли мне решить эту проблему. У меня есть приложение узла в качестве серверной службы api и интерфейс, созданный на VueJS. Я установил свое приложение узла с помощью cors со списком конечных точек, которым разрешен доступ к моему приложению узла. Работа на моем локальном компьютере не вызывает никаких ошибок, пока я не загружу его на свой сервер.

вот мои среды Локальная среда

  • Nodejs: 12.16.1
  • ОС: Windows 10
  • БД: MySQL
  • Фреймворк сервера NodeJS: ExpressJS
  • Модуль загрузки: Multer

Производственная среда

  • Nodejs: 12.19.0
  • ОС: Ubuntu 20.0.4
  • БД: MySQL
  • Фреймворк сервера NodeJS: ExpressJS
  • Модуль загрузки: Multer
  • nginx

Вот мои наблюдения, основанные на моем производственном приложении.

  1. Когда я загружаю форму с изображением [500kb и выше] [post or put], появляется ошибка cors, но меньше этого, все прошло нормально.
  2. Если я использую данные формы для отправки данных на сервер, я вижу 2 запроса на вкладке своей сети, ОПЦИИ и фактический запрос.
  3. Фактический запрос не удался, но я увидел, что длина моего содержимого очень велика, что приводит меня к выводу, что мой запрос отклонен из-за большого количества данных, отправленных клиентом, которые мой сервер мог ограничить. Я знаю, что это может вводить в заблуждение, но решение, которое я сделал, работает, поэтому я не знаю, почему возникает проблема cors, даже если проблема заключается в ограничении данных.

МОЕ РЕШЕНИЕ: В моем конфигурационном файле nginx я увеличил значение client_max_body_size до 100M. Я считаю, что nginx имеет значение по умолчанию 1MB

  1. Откройте /etc/nginx/sites-available/your-server-file, где your-server-file может быть как www.example.com или default.
  2. Добавьте следующую строку в серверный блок. Вы можете установить любое значение, кроме 100M.
server {
    client_max_body_size 100M;
    ...
}

  1. введите sudo systemctl restart nginx, чтобы перезапустить nginx.
  2. введите sudo nginx -t, чтобы проверить, успешно ли внесены изменения.
  3. Перезагрузите приложение, если вы используете pm2, и все готово.
person Arjorie Sotelo    schedule 06.12.2020