使用Fetch API而不是Ajax进行Allow-Credentials + POST请求

时间:2018-04-07 22:43:17

标签: php ajax reactjs cors fetch

此方案使用Access-Control-Allow-CredentialsPOST方法来管理必须保持不变的服务器端PHP会话变量。

作为参考,前端是在create-react-app运行的http://localhost:3000项目,PHP上运行的后端是example.com

使用$.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);
      });
    });
  }

但奇怪的是,在使用fetch() API时,我认为我不允许CORS。当然,我已启用CORS,因为此请求适用于Ajax,并且仅在使用fetch() API时失败。

以下是我在使用fetch() API时尝试过的内容。

  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's 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']);
?>

我已经回答了很多问题,但最值得注意的是this question with a very thorough explanation of the issue and possible solutions

目前,我只是使用经过验证的$.ajax()来完成此任务,但我希望在复制此功能所需的范围内完全理解fetch() API,因为它从我的经历来看,这似乎是非常基本的东西。

2 个答案:

答案 0 :(得分:-1)

您需要在同一服务器源上运行后端和前端,请参阅此link中的更多内容,因此您需要在同一服务器名称中运行双方,尝试移动后端 - 结束localhost文件夹并使用PHP file_get_contents或curl方法从api获取外部数据。

答案 1 :(得分:-2)

在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())。基本上,一切都使用fetch ...