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
- 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.
- Data serving server has cors configured to
*
, cal heatmap uses no request settings, just the url.
Same code as before, just without therequestInit
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