Ошибки отправки запроса на сервер через fetch()

Рейтинг: 0Ответов: 2Опубликовано: 25.05.2023

На странице формы подключен скрипт js, который отправляет запрос на сервер при клике пользователя на одной из двух кнопок. Затем сервер возвращает ответ и браузер выводит сообщение с полученными данными.

js:

let element = document.querySelector('.button');

element.addEventListener('click', function(event) {
    fetch("http://my_site/test", {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json;charset=utf-8'
        },
        body: JSON.stringify({"key": event.target.value})
    })
    .then(response => response.json())
    .then(data => alert(data));
});

серверный скрипт Laravel:

Route::post('/test', function (Request $request) {

    $data = $request->input('key');
    return json_encode($data);

});

В результате при клике по любой из кнопок в консоль выводятся следующие сообщения об ошибках:

POST http://my_site/test 419 (unknown status)

POST http://my_site/test 419 (unknown status)

Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

Как я понял первые две ошибки говорят о проблеме с csrf-токеном. Попытался вылечить это добавив в разметку тег <meta name="csrf-token" content="{{ csrf_token() }}">, но ошибка не ушла.

Две последние, как я прочитал говорят о том, что скрипт js отправляет не json, а html. Здесь я вообще не нашел, что можно предпринять.

Как устранить эти ошибки? Почему они задублированы? Спасибо!

Ответы

▲ -1Принят

Ошибки возникают из-за того, что сервер возвращает ошибку 419, которая указывает на проблему с CSRF-токеном. Для решения этой проблемы необходимо добавить CSRF-токен в заголовок запроса. Для этого можно использовать следующий код:

let element = document.querySelector('.button');
let csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

element.addEventListener('click', function(event) {
    fetch("http://my_site/test", {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json;charset=utf-8',
            'X-CSRF-TOKEN': csrfToken
        },
        body: JSON.stringify({"key": event.target.value})
    })
    .then(response => response.json())
    .then(data => alert(data));
});

Чтобы скрипт отправлял данные в формате JSON, необходимо убедиться, что сервер возвращает данные в формате JSON. В данном случае сервер возвращает HTML, что вызывает ошибку. Чтобы решить эту проблему, необходимо изменить серверный скрипт Laravel, чтобы он возвращал данные в формате JSON. Для этого можно использовать следующий код:

Route::post('/test', function (Request $request) {

    $data = $request->input('key');
    return response()->json($data);

});

Если эти изменения не помогут, то возможно, что проблема заключается в другом месте кода.

▲ 0

Отметьте, пожалуйста, мой предыдущий ответ как правильный.)

  1. Если сервер присылает ответ дважды, возможно, что проблема действительно связана с тем, что у вас две кнопки, слушающие одно и то же событие. Попробуйте добавить условие, чтобы запрос отправлялся только при клике на нужную кнопку:
let elements = document.querySelectorAll('.button');
let csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

elements.forEach(element => {
    element.addEventListener('click', function(event) {
        if (event.target.value === 'value') {
            fetch("http://my_site/test", {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json;charset=utf-8',
                    'X-CSRF-TOKEN': csrfToken
                },
                body: JSON.stringify({"key": event.target.value})
            })
            .then(response => response.json())
            .then(data => alert(data));
        }
    });
});

  1. Ошибка Not allowed to load local resource возникает, когда вы пытаетесь загрузить файлы из локального диска напрямую в браузере. Для исправления этой ошибки необходимо запустить сервер на локальном хосте и загружать файлы через него. Вам необходимо изменить путь к файлу таким образом, чтобы он загружался через сервер. Например, если вы используете сервер Laravel, то можно изменить путь следующим образом:
<link rel="stylesheet" href="{{ asset('assets/css/home.css') }}">

Если вы используете сборщик Vite, то можно использовать следующий код:

<link rel="stylesheet" href="{{ mix('css/app.css') }}">

В этом случае, файл CSS будет загружаться через сервер, который запущен на локальном хосте. <insert-here/>