I am trying to post JSON data from JavaScript to PHP. You can do that with either
Content-Type: application/json
or
Content-Type: application/x-www-form-urlencoded
Both works, but I had a hard time getting the first one to work. The reason is that I missed that the PHP script seems to be running 2 times when the content type is application/json
.
I am quite surprised and wonder what is going on. Can anyone explain what is going on and how to handle it? (There are some related questions, but none of the answers seems to observe this behaviour.)
Here is my test code. First start PHP builtin server:
php.exe -S localhost:7000
Then in that directory create the file test1.php
with the following code:
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type");
header("Content-Type: application/json");
function writeStdErr($msg) { $fh = fopen('php://stderr','a'); fwrite($fh, $msg); fclose($fh); }
writeStdErr("\n\nI am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
$e = stripslashes(file_get_contents("php://input"));
writeStdErr("e=".$e."\n");
if (strlen($e) > 0) echo $e;
Now from a web browser console (I am using Google Chrome) make an ajax call:
function test1(j) {
url = "http://localhost:7000/test1.php";
type = "application/x-www-form-urlencoded";
if (j) type = "application/json";
xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", type);
xhr.addEventListener("readystatechange", function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var json = JSON.parse(xhr.responseText);
console.log(json.email + ", " + json.password)
}
});
var data = JSON.stringify({"email":"hey@mail.com","type":type});
xhr.send(data);
console.log("now sending >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", url, type);
}
test1(false)
The output in the console is just what I expect:
I am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
e={"email":"hey@mail.com","type":"application/x-www-form-urlencoded"}
Now instead do the ajax call with applicaion/json
, i.e. test1(true)
. The output is now:
I am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
e=
I am here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
e={"email":"hey@mail.com","type":"application/json"}
As you can see the PHP code has been run two times. And the first time there is no input on php://input
.
Why??? And how is this supposed to be handled in PHP?
Borrowed some of the code here: Sending a JSON to server and retrieving a JSON in return, without JQuery
Here are some related questions: Code to be run twice in Ajax request, Running curl twice in php, https://stackoverflow.com/questions/24373623/ajax-request-help-code-gets-created-twice, Ajax form submitting twice with Yii 2
And this question (one of the highest voted here) is of course relevant, but has nothing to say about why the PHP code is run twice: