Search code examples
javascriptjquerycanvasjscross-origin-read-blocking

CORB error with canvasJS with $.getJSON()


I am getting a CORB error with the following script, and I cant seem to figure out why.

<script>

var chart = null;
var dataPoints = [];

window.onload = function() {

chart = new CanvasJS.Chart("chartContainer", {
    animationEnabled: true,
    theme: "light2",
    title: {
        text: "Daily Sales Data"
    },
    axisY: {
        title: "Sold For",
        titleFontSize: 24
    },
    data: [{
        type: "line",
        yValueFormatString: "$#,##0.00",
        dataPoints: dataPoints
    }]
});


$.getJSON("https://www.hostname.com/test/examples/01-overview/test.php?callback=?", callback);

}

function callback(data) {
    console.log(data.dps);
    for (var i = 0; i < data.dps.length; i++) {
        dataPoints.push({
            x: new Date(data.dps[i].date),
            y: data.dps[i].units
        });
    }
    chart.render();
}
</script>

I noticed that the format from the example is

callback({
   "dps":[
      {
         "date":"08/18/2020",
         "units":1550.00
      } //more here
   ]
})

my PHP file returns this..

{"callback":[
    {"dps":[
        {
            "date":"08\/18\/2020",
            "units":"1550.00"
         }, {...}
    ]}
 ]}

Im not sure if thats why...


Solution

  • You have three basic problems here:

    1. You aren't overriding the default Content-Type, so PHP is claiming that it is outputting HTML. When the browser gets the response it sees that it claims to be HTML and doesn't execute it as JavaScript as a consequence. (This is what is triggering the error you are seeing, but fixing it will just expose the other two errors).
    2. Your JSONP is improperly formatted (as you suspected). It looks like you are create an associative array with a callback key and then running the whole thing through json_encode instead of just encoding the JSON portion of the JSONP.
    3. You aren't using the callback name passed by the request, but have hardcoded callback

    Well, three if you don't count using JSONP in 2020 a problem.


    The correct way to do JSONP is something like this:

    <?php
        $data = do_stuff_to_get_the_data();
        if (!test_if_callback_is_safe($_GET['callback'])) {
           die();
        }
        header("Content-Type: application/javascript");
        echo $_GET('callback');
        echo "(";
        echo json_encode($data);
        echo ");";
        exit;
    

    However. You should not use JSONP. It has some security risks. It only allows you to make GET requests. It doesn't enable good client-side error handling. It can't be used to restrict the origin that can read the response: It is all or nothing.

    Output JSON instead. Use CORS to provide permission to the browser to allow JS running on other sites to read it:

    <?php
        $data = do_stuff_to_get_the_data();
        header("Content-Type: application/json");
        header("Access-Control-Allow-Origin: *"); # Don't use a global wildcard if you can restrict this 
        echo json_encode($data); 
        exit;
    

    And on the client, do not include ?callback=? in the URL since that will trigger JSONP mode in jQuery.