I'm sending data to test.php page with fetch on my page and it can't pass the if check shown below on the test.php page, so the error "Uncaught exception 'Exception' with message 'Only POST requests are allowed" comes up. What could I be doing wrong?
fetch("test.php", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify({
value: valueToSend
})
})
.then(
function(response) {
if (response.ok) {
console.log("ok")
window.location.href = "/test.php";
} else {
console.log("There was an error sending the message.", response);
}
}
)
my test.php page
if (strtoupper($_POST['REQUEST_METHOD']) != "POST") {
throw new Exception('Only POST requests are allowed');
}
// Make sure Content-Type is application/json
$content_type = isset($_POST['CONTENT_TYPE']) ? $_POST['CONTENT_TYPE'] : '';
if (stripos($content_type, 'application/json') === false) {
throw new Exception('Content-Type must be application/json');
}
// Read the input stream
$body = file_get_contents("php://input");
// Decode the JSON object
$object = json_decode($body, true);
var_dump($object);
CodePudding user response:
It's simply that you are reading the bad global var.
It's not $_POST['REQUEST_METHOD']
but it's $_SERVER['REQUEST_METHOD']
which should be tested in your if
statement.
Same problem for the content type. Use $_SERVER['CONTENT_TYPE']
instead.
$_POST
is the array of posted values.
Proof of concept
As you asked if it works or not: yes, it does work.
Just paste this PHP code in a file and view it. It contains a button which will trigger the Ajax request to itself. It displays the response directly in an alert window.
I simply took the posted JSON object and added an attribute with the current time to show that the echoed object has been altered by the PHP.
<?php
if (strtoupper($_SERVER['REQUEST_METHOD']) != "POST") {
print <<<END_OF_HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>$_SERVER[PHP_SELF]</title>
</head>
<body>
<button id="post-to-server">POST JSON data to $_SERVER[PHP_SELF] and echo the output</button>
<script>
document.getElementById('post-to-server').addEventListener('click', (e) => {
fetch('$_SERVER[PHP_SELF]', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify({
value: {
firstname: 'James',
lastname: 'Bond',
permitToKill: true
}
})
})
.then((response) => {
if (response.ok) {
console.log('ok');
// Decode the JSON (it's a promise also).
response.json().then((data) => {
console.log('JSON data', data);
alert('Server response:\\n' JSON.stringify(data, null, 2));
})
.catch((error) => {
console.log('Could not decode the JSON response!', error);
});
} else {
console.log('There was an error sending the message.', response);
}
}
)
});
</script>
</body>
</html>
END_OF_HTML;
exit;
//throw new Exception('Only POST requests are allowed');
}
// Make sure Content-Type is application/json
$content_type = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
if (stripos($content_type, 'application/json') === false) {
throw new Exception('Content-Type must be application/json');
}
// Read the input stream
$body = file_get_contents("php://input");
// Decode the JSON object
$object = json_decode($body, null);
// Alter the echoed data by adding an attribute to the object.
$object->response_time = date('c');
header('Content-Type: application/json; charset=utf-8');
echo json_encode($object, JSON_PRETTY_PRINT);
CodePudding user response:
I suggest
<form action="test1.php" method="post">
<input type="text" name="value" value="valueToSend" />
<input type="submit" />
</form>
and test1.php
if (strtoupper($_SERVER['REQUEST_METHOD']) != "POST") {
throw new Exception('Only POST requests are allowed');
}
// Read the value
$body = $_POST["value"];
if ($body === "valueToSend") header("location: test2.php");
else header("location: error.html");