否 Access-Control-Allow-Origin 使用 OneSignal 设置

No Access-Control-Allow-Origin using OneSignal setup

我正在使用 OneSignal for web push messaging for a client website. I've followed the HTTPS setup。我检查了几次以确保一切都正确完成。

当我加载页面时,我得到:

Fetch API cannot load https://onesignal.com/api/v1players. 
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://example.com' is therefore not allowed access. 
The response had HTTP status code 404. If an opaque response serves your needs, 
set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

我直接联系了团队,但他们只是复制粘贴了文档的一部分。没有提供进一步的帮助。

使用 Chrome 版本 58 / Windows 10

我做错了什么?

https://onesignal.com/api/v1players 响应显然不包括 Access-Control-Allow-Origin 响应 header,因为它们不包含,您的浏览器会阻止您的前端 JavaScript 代码访问响应.

您无法对自己的前端 JavaScript 代码或后端配置设置进行任何更改,以允许您的前端 JavaScript 代码以您尝试直接向 https://onesignal.com/api/v1players 并成功获得响应。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 解释得更详细,但要点是对于 CORS,请求发送到的服务器必须配置为发送 Access-Control-Allow-Origin 响应 header。

无论如何 https://documentation.onesignal.com/docs/web-push-sdk-setup-https 有解释他们支持的 SDK 的官方文档,这显然需要你做更多类似这样的事情:

<head>
  <link rel="manifest" href="/manifest.json">
  <script src="https://cdn.onesignal.com/sdks/OneSignalSDK.js" async></script>
  <script>
    var OneSignal = window.OneSignal || [];
    OneSignal.push(["init", {
      appId: "YOUR_APP_ID",
      autoRegister: false,
      notifyButton: {
        enable: true /* Set to false to hide */
      }
    }]);
  </script>
</head>

接受的答案还可以,你可以使用标签解决大部分需求:

OneSignal.push(function() {
  /* These examples are all valid */
  OneSignal.sendTag("key", "value");

  OneSignal.sendTag("key", "value", function(tagsSent) {
    // Callback called when tags have finished sending
  });

  OneSignal.sendTag("key", "value").then(function(tagsSent) {
    // Callback called when tags have finished sending
  });  
});

但是如果你想编辑设备信息,(截至今天)无法使用 WebPush SDK 编辑设备元数据。我需要定期更新位置,而且我不想使用标签。所以,我像这样将 PUT 请求发送到 https://onesignal.com/api/v1players

function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {
    xhr.open(method, url, true);
  } else if (typeof XDomainRequest != "undefined") { //ie8 ie9
    xhr = new XDomainRequest();
    xhr.open(method, url);
  } else {
    xhr = null;
  }
  return xhr;
};

//then every time I needed to update the device
var url = 'https://onesignal.com/api/v1/players/' + playerId;
var xhr = createCORSRequest('PUT', url);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");

xhr.onload = function() {}; //success
xhr.onerror = function() {}; //error

var deviceInfo = {
  "app_id": oneSignalAppId,
  "timezone": (currentDateTime.getTimezoneOffset()) * -60, //offset from utc
  //whatever fields you need to update
};

xhr.send(JSON.stringify(deviceInfo));