Search code examples
javascriptphpcorscross-domain

Getting Error When Trying to Fetch Json Data Using PHP on cPanel Server Setup


I have an index.html file that includes a javascript:

async function fetchCelebritiesData() {
  try {
    const response = await fetch('/data.php');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching data:', error);
    return [];
  }
}

The PHP file connects the data with the application and fetches data from names.json file.

<?php
// Check if the request is coming from an allowed domain
$allowedOrigins = array("example.com", "www.example.com");

$origin = $_SERVER['HTTP_ORIGIN'] ?? ''; // Get the HTTP_ORIGIN from the request

if (in_array($origin, $allowedOrigins)) {
    header("Access-Control-Allow-Origin: $origin");
} else {
    header("HTTP/1.1 403 Forbidden");
    exit;
}

// Read and output the JSON data
$data = file_get_contents("data.json");
header("Content-Type: application/json");
echo $data;
?>

This setup gives me an error in the console that reads like this:

ET https://example.com.com/data.php 403
fetchCelebritiesData @ (index):291
(anonymous) @ (index):375
load (async)
(anonymous) @ (index):373
(index):295 Error fetching data: SyntaxError: Unexpected end of JSON input
    at fetchCelebritiesData ((index):292:33)
    at async (index):375:30
fetchCelebritiesData @ (index):295
await in fetchCelebritiesData (async)
(anonymous) @ (index):375
load (async)
(anonymous) @ (index):373

Need help in understanding what could be the issue. I have checked the file permission for PHP and JSON and the folder itself it looks fine. --6 4 4--

There's a log generated which shows this error repeatedly.

[11-Aug-2023 09:08:58 UTC] PHP Notice: Undefined index: HTTP_ORIGIN in /home/pixellic/public_html/web-applications/celebrities-age-finder/get_secure_data.php on line 4

Appreciate your help. I'm a coding novice.

Thankyou.

I tried getting json data securedly using php file. But I got a 403 error.


Solution

  • const response = await fetch('/data.php');
    

    You are making a same origin request.

    Browsers will only include an Origin request header for a cross origin request.

    Substituting a missing origin with an empty string and then testing that value which can never be an origin in your list against all the rest of your logic is pointless.

    Say what you mean instead. Test for the presence of the Origin header before trying to do anything with the value:

    if (isset($_SERVER['HTTP_ORIGIN'])) {                   # This is a cross-origin request
        $origin = $_SERVER['HTTP_ORIGIN'];               
        if (in_array($origin, $allowedOrigins)) {           # Test the origin against a list of allowed origins
            header("Access-Control-Allow-Origin: $origin"); # Tell the browser the origin is allowed if it is on the list
        }
    }
    

    } else {
        header("HTTP/1.1 403 Forbidden");
        exit;
    }
    

    Do not use the Origin header for authn/authz.

    As mentioned, it isn't set same origin requests, and it can easily be spoofed in hostile requests from outside a browser.

    If the Origin header is not present then simply don't include the Access-Control-Allow-Origin header. The user's browser will block the JavaScript of the unauthorised origin from reading the response body. (Same origin requests, like yours, won't be blocked by the browser, so don't need the Access-Control-Allow-Origin header, which is why the Origin header isn't sent).

    Remove the else branch which spits out a 403 Forbidden response.


    $allowedOrigins = array("example.com", "www.example.com");
    

    Not directly relevant to your problem (because you're making a same origin request) but those are not valid origins.

    An origin is either null or it is a scheme + hostname + optional port. You are omitting the schemes.

    e.g.:

    $allowedOrigins = array("https://example.com", "https://www.example.com");