fetch делает запрос с неверным content-type

Знаю, что на форуме много любителей «современного» javascript
Может кому умная мысль прийдет в голову. Много раз уже работал с fetch в javascript но впервые столкнулся с тем, что при post запросе, в котором передается json в body, запрос на сервер приходит с некоректным заголовком
Content-Type:text/html; charset=UTF-8
async function test() {
      const user = {
        phone: '+0000000000',
        password: '76c4a096d14',
      };

      const response = await fetch('http://development/employee/auth', {
        method: 'POST',
        mode: 'no-cors',
        headers: {
          'Content-Type': 'application/json;charset=utf-8',
        },
        body: JSON.stringify(user),
      });

      const result = await response.json();
      console.log(result);
    }
    test();
Передаю заголовок Content-Type корректный, передаю в body json, но при получении на сервере
Content-Type:text/html; charset=UTF-8
Александр Мельник
18 июля 2023, 17:12
modx.pro
584
0

Комментарии: 6

Александр Мельник
18 июля 2023, 17:17
0
Если делаю этот же запрос, но через postman, выбрав body->row-json
то запрос на сервер приходит с корретным Content-Type.

Так же проверил, что fetch автодектит тип данных и если совсем удалить заголовок и передать в запросе FormData, то он подставит заголовок корректный.
И я даже согласен с тем, что json по своей сути это текст, а значит можно сказать что fetch передал по умолчанию заголовок Content-Type:text/html, но почему он игнорирует заданный в парметрах заголовок, пока для меня загадка.
    Александр Мельник
    18 июля 2023, 17:46
    0
    я понял, это наверное изза
    mode: 'no-cors',
      Артур Шевченко
      18 июля 2023, 18:24
      +1
      Можешь вообще эту оцию не использовать, она, по-моему, бесполезная. CORS запрос сделать не поможет, а для чего ещё её можно использовать непонятно.
    Баха Волков
    18 июля 2023, 22:01
    +1
    Возможно у тебя какой-то прикол в настройках сервера.

    // index.js
    
    const btn = document.querySelector('#send')
    
    btn.addEventListener('click', async () => {
      const user = {
        phone: '+0000000000',
        password: '76c4a096d14',
      }
    
      const response = await fetch('/test.php', {
        method: 'POST',
        mode: 'no-cors',
        headers: {
          'Content-Type': 'application/json;charset=utf-8',
        },
        body: JSON.stringify(user),
      })
    
      const result = await response.json()
      console.log(result)
    })

    // test.php
    
    <?php
    
    echo json_encode([
      'CONTENT_TYPE' => $_SERVER['CONTENT_TYPE'],
      'Content-Type' => getallheaders()['Content-Type']
    ]);

    // Ответ сервера
    
    {"CONTENT_TYPE":"application/json","Content-Type":"application/json"}
      Александр Мельник
      18 июля 2023, 22:40
      +1
      Не знаю почему у вас работает. Я отрыл в документации (и даже по той ссылке что вы дали на mdn это тоже написано), что включение mode no-cors позволяет использовать только простые запросы.
      Кстати до сегоднешнего дня не знал, что запросы делятся на простые и сложные. Но как оказалось, если запрос содержит content-type — aplication/json он уже считается сложным.
      Простой запрос – это запрос, удовлетворяющий следующим условиям:

      Простой метод: GET, POST или HEAD
      Простые заголовки – разрешены только:
      Accept,
      Accept-Language,
      Content-Language,
      Content-Type со значением application/x-www-form-urlencoded, multipart/form-data или text/plain.

      Любой другой запрос считается «непростым». Например, запрос с методом PUT или с HTTP-заголовком API-Key не соответствует условиям.
      If mimeType’s essence is not «application/x-www-form-urlencoded», «multipart/form-data», or «text/plain», then return false.

      Поэтому насколько я понял, fetch принудительно меняет заголовок на text, если я указал mode no-cors.
      Хотя у вас работает.
      Я тоже грешил на сервер, потому что это мной построенные на docker целый кластер из контейнеров, с двойным проксирование запросов и напартачить там можно было во многих местах. Но запросы с postamn, curl — проходили правильно, с корректным content-type.
      Пришлось более глубоко вникнуть в работу cors. Убрал из fetch no-cors и реализовал у себя в приложении обработку предзапроса по методу options. Полнейшее для меня открытие, но оказалось что как только мы хотим сделать «сложный» запрос на «не свой домен», перед основным запросом браузер отсылает предварительный запрос на тот же url но только методом options и просит разрешения на основной запрос.
      Как только я организовал у себя обработку этих предзапросов и возврат корректных (по документации заголовков), у меня все заработало.

      Прекрасно, что удалось открыть что то новое для себя и спасибо за подсказки.
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      6