Когда можно использовать mode no-cors в fetch

Когда я занимался разработкой на frontend, сталкивался с ошибкой CORS при попытке отправить fetch запрос на сервер с адресом отличным от текущего. Меня не никак не приводило в нужный раздел документации и я долго не мог сформулировать для себя, как же решается эта проблема на фронтенде. Позже я научился выставлять разрешения на сервере, а почему mode не работает так и не понял.

В конце концов, возникла снова эта ситуация и решил докопаться до сути, почему же, mode есть, а эффекта нет. Чтобы не забыть сохранил как памятку, может кому то пригодиться.

Режим no-cors в fetch используется для отправки запросов на серверы, которые не поддерживают CORS (Cross-Origin Resource Sharing). Однако у этого режима есть серьезные ограничения, и он работает не во всех случаях. Вот основные ситуации, когда no-cors не работает или работает с ограничениями:


1. Запросы с методами, отличными от GET, HEAD или POST

  • В режиме no-cors можно использовать только методы GET, HEAD и POST.
  • Если вы попытаетесь использовать другие методы (например, PUT, DELETE, PATCH), браузер заблокирует запрос.

Пример:

fetch('https://example.com/api', {
    method: 'PUT', // Не поддерживается в no-cors
    mode: 'no-cors'
});
// Браузер выдаст ошибку

2. Заголовки запроса ограничены

  • В режиме no-cors вы не можете устанавливать произвольные заголовки запроса.
  • Разрешены только "простые" заголовки:
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type (с ограниченными значениями: application/x-www-form-urlencoded, multipart/form-data, text/plain).

Пример:

fetch('https://example.com/api', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer token', // Заголовок запрещен в no-cors
        'Content-Type': 'application/json' // Заголовок запрещен в no-cors
    },
    mode: 'no-cors'
});
// Браузер выдаст ошибку

3. Невозможно прочитать ответ

  • В режиме no-cors ответ сервера становится "непрозрачным" (opaque). Это означает, что вы не можете получить доступ к данным ответа, включая статус код, заголовки и тело ответа.
  • Вы можете только проверить, успешно ли выполнен запрос.

Пример:

fetch('https://example.com/api', {
    mode: 'no-cors'
})
.then(response => {
    console.log(response.status); // Всегда 0
    console.log(response.headers); // Пустой объект
    return response.text(); // Не сработает
})
.catch(error => {
    console.error('Ошибка:', error);
});

4. Запросы с учетными данными (credentials)

  • В режиме no-cors вы не можете отправлять запросы с учетными данными (например, cookies или авторизационные заголовки).
  • Если вы попытаетесь установить credentials: 'include', браузер заблокирует запрос.

Пример:

fetch('https://example.com/api', {
    mode: 'no-cors',
    credentials: 'include' // Запрещено в no-cors
});
// Браузер выдаст ошибку

5. Запросы к ресурсам, которые блокируют no-cors

  • Некоторые серверы могут блокировать запросы, отправленные в режиме no-cors, если они не поддерживают такие запросы.
  • Например, сервер может проверять заголовок Origin и отклонять запросы, если они не соответствуют его политике CORS.

6. Ограничения на использование ответа

  • Даже если запрос в режиме no-cors выполнен успешно, вы не сможете использовать ответ для дальнейшей обработки.
  • Например, вы не сможете:
  • Отобразить изображение, загруженное через no-cors.
  • Прочитать JSON-ответ от сервера.
  • Использовать данные ответа в JavaScript.

Пример:

fetch('https://example.com/image.png', {
    mode: 'no-cors'
})
.then(response => response.blob())
.then(blob => {
    const imageUrl = URL.createObjectURL(blob);
    const img = document.createElement('img');
    img.src = imageUrl;
    document.body.appendChild(img);
})
.catch(error => {
    console.error('Ошибка:', error);
});
// Изображение не отобразится из-за ограничений no-cors

7. Ограничения на кэширование

  • Ответы, полученные в режиме no-cors, не кэшируются стандартными механизмами браузера (например, Cache-Control или Service Worker).

Когда использовать no-cors?

Режим no-cors полезен только в очень ограниченных сценариях, например: - Когда вам нужно отправить данные на сервер, и вам не важен ответ. - Когда вы работаете с сервером, который не поддерживает CORS, и вы не можете изменить его конфигурацию.


Альтернативы no-cors

Если вам нужно обойти ограничения no-cors, рассмотрите следующие варианты: 1. Настройка CORS на сервере: Добавьте заголовок Access-Control-Allow-Origin на сервере. 2. Использование прокси-сервера: Создайте прокси на своем домене, который будет обрабатывать запросы. 3. Использование JSONP (только для GET-запросов): JSONP позволяет обойти CORS, но работает только для GET-запросов. 4. Использование <img>, <script> или <link>: Эти теги не подвержены ограничениям CORS, но их использование ограничено конкретными сценариями.


Итог

Режим no-cors работает только для простых запросов (GET, POST, HEAD) и не позволяет читать ответ или использовать сложные заголовки. Если вам нужно получить данные или выполнить сложный запрос, используйте другие методы, такие как прокси или настройка CORS на сервере.