wa0x6e/cal-heatmap

Heatmap is not rendered when mode no-cors is used

arturschulz opened this issue · 4 comments

Heatmap fails to render correctly(only the grid is visible, no data) when request mode: 'no-cors' is used.

To show that the issue is related to no-cors I've prepared two cases

  1. Data serving server has no cors configured, cal-heatmap uses no-cors
<!doctype html>
<html>
<head>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script src="https://unpkg.com/cal-heatmap/dist/cal-heatmap.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/cal-heatmap/dist/cal-heatmap.css">
    <title>Cors error</title>
</head>
<body>
<div id="cal-heatmap"></div>
<script>

const cal = new CalHeatmap();
cal.paint({
  data: {
      source: 'http://example.org/my/api.json',
      requestInit: {
        mode: 'no-cors',
      },
  },

});
</script>
</body>
</html>

Result: data is loaded(seen the data in dev tools), no data is rendered on the heatmap, no erros visible.

  1. Data serving server has cors configured to *, cal heatmap uses no request settings, just the url.
    Same code as before, just without the requestInit section.

Server has cors configured to all hosts(wildcard)
Headers from devtools:

access-control-allow-credentials: true
access-control-allow-origin: *
content-length: 2692
content-type: application/json
date: Tue, 28 Feb 2023 21:53:43 GMT

Result: heatmap is rendered correctly

Just tested without any requestInit, and without cors from the server, and data did load correctly.

Do you have a test api so I can see for myself

Here's an example api, /block endpoint has no CORS configured, so it should be blocked by the browser by default, and /allow has CORS configured to a wildcard so it should be generally accepted.

server.js

const express = require('express')
const app = express()
const cors = require('cors')

const port = 3000

const corsOptions = {
  origin: '*',
  optionsSuccessStatus: 200
}

const data = [
{"date": "2023-01-01", value: 1},
{"date": "2023-01-02", value: 2},
{"date": "2023-01-03", value: 3},
]

app.get('/block', (req, res) => {
  res.json(data)
})

app.get('/allow', cors(corsOptions), (req, res) => {
    res.json(data)
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
npm install express cors
node server.js

Cal-Heatmap is using the javascript built-in fetch API to fetch remote data

As per this stackoverflow post, CORS is indeed a requirement in order for the javascript to be able to read the fetched data, even though you can see it in the browser devtools, and mode: no-cors does not have any effect on it.

https://stackoverflow.com/questions/43262121/trying-to-use-fetch-and-pass-in-mode-no-cors

Only solution is to implement CORS headers on the server API, or to use a CORS proxy

Docs has been updated about CORS requirement