Использование Fetch API вместо Ajax для запросов Allow-Credentials + POST

-1

Этот сценарий использует Access-Control-Allow-Credentials вместе с методом POST для управления переменными сеанса PHP стороне сервера, которые должны оставаться неповрежденными.

Для справки, front-end представляет собой проект create-react-app работающее на http://localhost:3000 а на внутреннем сервере - PHP работающий на example.com.

$.ajax() этого с помощью $.ajax() легко и просто.

  UseAjax(incomingData) {
    return new Promise(function(resolve, reject) {
      $.ajax({
        url: 'http://example.com/api.php',
        type: 'post',
        data: incomingData,
        xhrFields: { withCredentials: true },
        success: function(data) {
          console.log(data)
        }
      })
      .then((data,status) => {
        // Get the result and transform into valid JSON
        if ( typeof data === typeof 'str' ) {
          try {
            data = JSON.parse(data);
          } catch(e) {
            reject(data,status);
            console.log('Exception: ', e);
            console.log('API Returned non-JSON result: ', data);
          }
        }
        return data;
      }).then((dataObject) => {
        console.log('dataObject:');
        console.log(dataObject);
        resolve(dataObject);
      });
    });
  }

Как ни странно, при использовании API fetch() создается впечатление, что я не разрешаю CORS. Конечно, у меня есть CORS как этот запрос отлично работает с Ajax и только сбой при использовании API fetch().

Вот посмотрите, что я пытался использовать API fetch().

  UseFetch(requestData) {
    return new Promise(function(resolve, reject) {
      console.log('Relay() called with data: ', requestData);
      fetch('http://example.com/api.php', {
        method: 'POST', // or 'PUT'
        body: JSON.stringify(requestData), // data can be 'string' or {object}!
        headers: new Headers({
          'Content-Type': 'application/json'
        })
      }).then((result) => {
        // Get the result
        return result.json();
      }).then((jsonResult) => {
        // Do something with the result
        if ( jsonResult.err )
          reject(jsonResult);
        console.log(jsonResult);
        resolve(jsonResult);
      });
    });
  }

Он обеспечивает эту ошибку.

Failed to load http://example.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request mode to 'no-cors' to fetch the resource with CORS disabled.

На стороне PHP я использую простой вывод, чтобы гарантировать, что ничего другого не будет, что приведет к ошибке на стороне сервера.

<?php
  header('Content-Type: application/json');
  header('Access-Control-Allow-Origin: http://example.com');
  header('Access-Control-Allow-Methods: POST');
  header('Access-Control-Allow-Headers: Content-Type, Authorization, x-requested-with');
  echo json_encode(['data'=>'result']);
?>

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

На данный момент я просто использую $.ajax() -and-true $.ajax() для выполнения этой задачи, но я хочу полностью понять API-интерфейс fetch() в той мере, в какой это необходимо для репликации этой функции, поскольку она кажется чем-то очень простым по моему опыту.

  • 0
    Возможно, вы захотите использовать панель Network вашего браузера devtools, чтобы просмотреть полную информацию о запросе и ответе для обоих случаев (случай $.ajax() случай fetch() ), включая полные заголовки запроса и метод запроса. и заголовки ответа и код состояния HTTP ответа - и затем используйте stackoverflow.com/posts/49712690/edit, чтобы вставить эти детали в вопрос.
  • 0
    Существует одно различие между вашим $ .ajax-кодом и кодом извлечения: в коде извлечения вы добавляете дополнительный заголовок ContentType, который не был установлен кодом $ .ajax, что заставило бы браузер отправлять предварительный запрос , Ваш php-код, похоже, написан не так, чтобы правильно обрабатывать предпечатную проверку. Однако .... ваше сообщение об ошибке не совсем соответствует этой проблеме. В сообщении об ошибке указывается, что заголовка управления доступом не было, что может быть связано с ошибкой PHP, в результате чего на вашей стандартной странице 500 ошибок не было заголовков CORS.
Теги:
fetch
cors

2 ответа

-1

В вашем PHP-коде вы указали header('Access-Control-Allow-Origin: http://example.com'); , Это неверно - вам нужно указать значение, переданное в заголовке запроса Origin (который в вашем случае будет http://localhost:3000):

header('Access-Control-Allow-Origin: http://localhost:3000');

В идеале вы не будете жестко кодировать его - вы просто извлечете заголовок запроса Origin и передадите его обратно.

Кстати, я считаю, что JQuery $.Ajax использует fetch() под обложками (точно так же, как XmlHTTPRequest()). В принципе, все использует выборку...

  • 0
    учитывая полученное сообщение об ошибке, я не думаю, что это текущая проблема, но потенциально может быть одна после того, как текущая проблема решена. Текущее сообщение об ошибке предполагает отсутствие заголовка контроля доступа. Если он был, но источник не совпадает, сообщение об ошибке будет другим.
  • 0
    Как @sideshowbarker предлагает в своем комментарии к вашему исходному сообщению, можете ли вы предоставить полный набор заголовков запросов и ответов? Ах, я вижу, ты не ОП. Извиняюсь.
Показать ещё 2 комментария
-2

Вам нужно, чтобы внутренний и внешний интерфейсы выполнялись на одном и том же сервере, см. Больше в этой ссылке, поэтому вам нужно запустить обе стороны с одним и тем же именем сервера, попытаться переместить фоновый код в папку localhost и использовать PHP file_get_contents или curl-метод для получения внешних данных из api.

  • 0
    Пожалуйста, прочитайте вопрос. Вопрос в том, как этого добиться с помощью fetch() вместо $.ajax() . Мы не хотим переделывать системную архитектуру, чтобы избежать недостатков плохо реализованного API fetch() .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню