0

I have an application in PHP, which receives data from the client that is in another domain. Data arrives from the fetch API via the POST method, but PHP doesn't send a response to the fetch API.

foo.com/endpoint.php:

<?php
include_once('database/connection.php');
header('Content-Type: application/json');

$ip = $_POST["ip"];
$city = $_POST["city"];
$state = $_POST["state"];
$country = $_POST["country"];
$category = $_POST["category"];
// Checking if the req ip already have registered other req
$ip_query = "SELECT * FROM registers WHERE `ip` = '$ip'";
$ip_result = mysqli_query($conn, $ip_query);
$ip_check = mysqli_fetch_assoc($ip_result);
if (!$ip_check) {
    // registering data after validation
    $new_query = "INSERT INTO `registers` (`ip`, `city`, `state`, `country`, `category`, `created`) VALUES ('$ip', '$city', '$state', '$country', '$category', '2022-07-21 00:00:01')";
    $new_create = mysqli_query($conn, $new_query);
    $result = array(
        'ok' => true,
        'status' => 200
    );
    // sending response
    http_response_code(200);
    echo json_encode($result);
} else {
    // sending response if already registered
    http_response_code(503);
}

Client side fetch code:

fetch(this.url, {
                method: 'POST',
                mode: 'no-cors',
                body: this.getFormValues(),
                headers: {
                    "Accept": "application/json",
                    'Content-Type': 'application/json'
                  }
            })
            .then(resp => resp.json())
            .then(data => {
                console.log(data)
                if (data.ok) {
                    this.Metrics.setSent()
                } else {
                    throw Error(r.statusText)
                }
            })
            .then(() => {
                this.Metrics.setSent()
                this.Metrics.dismiss()
            })
            .catch(erro => {
                console.log("Erro: ",erro)
                this.Metrics.dismiss()
            });

It's all right about storing data, my problem is just sending the response :(

  • `echo json_encode($result);` is how you send the response. – Barmar Jul 22 '22 at 20:17
  • You don't need `http_response_code(200);` that's the default. – Barmar Jul 22 '22 at 20:17
  • PHP won't convert JSON parameters into `$_POST`. So I don't see how it can be storing the data properly. – Barmar Jul 22 '22 at 20:19
  • Check the raw response in the Network tab of DevTools to see if there's a problem with the JSON response. – Barmar Jul 22 '22 at 20:20
  • I'm getting something like this as response: "Response {type: 'opaque', url: '', redirected: false, status: 0, ok: false, …} body: (...) bodyUsed: false headers: Headers {} ok: false redirected: false status: 0 statusText: "" type: "opaque" url: "" [[Prototype]]: Response" – Luiz Cavalcante Jul 22 '22 at 20:36
  • **Warning!** You're open to [SQL injection attacks](https://owasp.org/www-community/attacks/SQL_Injection)! Read [how to prevent SQL injection in PHP](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) by using prepared statements with bound parameters instead of injecting variables directly into your queries. It's not just about security. If your data contains, for example, a single quote `'`, your query will break. – M. Eriksson Jul 22 '22 at 20:41
  • _Side note:_ A word of warning... never use IP addresses to identify users/sessions or expect them to be unique (or static) for each user. Not only can a single user get a new IP address during a single session, but multiple users can also share a single IP (people on the same network, VPN's, proxies etc). – M. Eriksson Jul 22 '22 at 20:46
  • Thank you for the warning!!! I'll be careful with SQL Injections from now on – Luiz Cavalcante Jul 22 '22 at 20:54

2 Answers2

0

PHP does not parse the POST body into JSON automatically. To fix this, you have to add json_decode() to your code like this:

$ip = json_decode($_POST, true)["ip"];
brrrrrrr
  • 13
  • 7
0

I hadn't noticed that when making a request using the "no-cors" mode i'd get an opaque response.

I just added the code below to the beginning of my PHP file, changed the fetch mode to "cors" and everything worked as it was supposed to work:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization');
header("Access-Control-Allow-Credentials: true");
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
     header('Access-Control-Allow-Origin: *');
     header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method,Access-Control-Request-Headers, Authorization") ;
     header("HTTP/1.1 200 OK");
     die();
}

I made the adaptations suggested by @brrrrrrr and updated the queries to prevent SQL injections.

Thx everyone.