0

I've very simple setup for testing my PHP / JS interface. But the POST parameters are not set by the fetch request.

Client (JS):

function request(url, data, options) {
      const fetchOptions = options;
      // Add data to options
      fetchOptions['body'] = JSON.stringify(data);
      return fetch(url, fetchOptions);
}

function getUsers() {
      const url = 'http://127.0.0.1:8200/api.php';
      const data = { 'api': 'GET_USERS' };
      const options = {
        method: 'POST',
        mode: 'cors',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
      };
      request(url, data, options)
        .then(response => response.json())
        .then(data => console.log(data));
}

All I want to test is to send the POST parameter api with the value GET_USERS and recieve the server response (json) that checks if the POST parameter was set properly.

Server(php):

$response = array();
$meta = array();

if (isset($_POST['api'])) {
    $meta['api'] = $_POST['api'];
} else {
    $meta['api'] = null;
}

$response['meta'] = $meta;


header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Authorization, X-Requested-With");

// Send data to client
echo json_encode($response, JSON_UNESCAPED_UNICODE);

But the POST paramter api is not set - so I always recieve `{api: null;}' from the server. I already tried the following things:

  • Use body: data instead of body: JSON.stringify(data)
  • Initialize the data as new FormData() and add the api key-value pair by data.append('api', 'GET_USERS')

Setup:

  • PHP: 8.1.2
  • Webserver: Apache 2.4.52
ADyson
  • 57,178
  • 14
  • 51
  • 63
michaelT
  • 1,533
  • 12
  • 41
  • What have you tried to resolve the problem? Inspecting the request in your browser could help to check what is sent - I would assume that your request doesn't contain any `POST`parameters, as you are putting them into the body of your request – Nico Haase Feb 04 '22 at 13:05
  • Does https://stackoverflow.com/questions/18866571/receive-json-post-with-php help? – Nico Haase Feb 04 '22 at 13:06
  • `$data = json_decode(file_get_contents('php://input'), true);` this works but seems not a valid way to solve this for me. So how can I add POST parameters to the fetch? – michaelT Feb 04 '22 at 13:09
  • 1
    From [the `$_POST` documentation](https://www.php.net/manual/en/reserved.variables.post): *"An associative array of variables passed to the current script via the HTTP POST method **when using `application/x-www-form-urlencoded` or `multipart/form-data` as the HTTP Content-Type in the request**."* *(my emphasis)* You're sending straight JSON instead. – T.J. Crowder Feb 04 '22 at 13:09
  • 1
    @michaelT - Why does it seem "not valid"? – T.J. Crowder Feb 04 '22 at 13:10
  • Changing `'Content-Type': 'application/x-www-form-urlencoded'` does not work. Do I always have to stringify the JSON data? I tried it as object and string but does not work. – michaelT Feb 04 '22 at 13:13
  • 2
    @michaelT - You can't *just* change the content type, you have to also send data in that format. But again: What makes you think receiving the JSON as showni in the linked question is "not valid"? – T.J. Crowder Feb 04 '22 at 13:13
  • Use this to see what you are sending to the server`$client_data = file_get_contents("php://input"); print_r($client_data);` – Nicholas Mberev Feb 04 '22 at 13:16
  • 1
    If you don't want to send JSON directly, you can embed it in a `application/x-www-form-urlencoded` POST field by removing the `Content-Type` request header and sending the JSON in a named POST field. For instance, `fetchOptions.body = new FormData(); fetchOptions.body.append("json", JSON.stringify(data));` But the double-encoding (first as JSON, then as URL-encoded data) seems unnecessary and wasteful vs. just doing what the linked answers show. – T.J. Crowder Feb 04 '22 at 13:17
  • I think I am going to use `json_decode(file_get_contents('php://input')`. For me it *feels* like not valid because I am not sending POST parameters actually, its *fells* more like a workaround. But if you say that this is a common way for JS / PHP communication, I am fine. – michaelT Feb 04 '22 at 13:20
  • 1
    POST parameters only makes sense when you send form-url-encoded data. It doesn't make any sense for a single JSON dataset, because it's one piece of string data (possibly with some sub-properties, once you decode it, but not when it's serialised), not a series of separate parameters. So it's not a workaround, it's just a different way of getting the input, because you're dealing with a different content type. Just like if you send a file, it goes into $_FILES because it's a different type of content. It's entirely sensible. – ADyson Feb 04 '22 at 13:26
  • 2
    @michaelT - It's not a workaround, nothing says POST bodies have to be form data, that's just one common format (well, two). The POST body can be in any format you say it's in via the `Content-Type` request header (though I'd stick to standard ones :-) ). `application/json` is a standard body format. `application/x-www-form-urlencoded` and `multipart/form-data` are two other standard ones, and PHP has some automatically handling for them via `$_POST`, but that's all that's special about them. Absolutely normal to have a JSON POST body. Happy coding! – T.J. Crowder Feb 04 '22 at 13:28
  • 2
    You could also have XML, or plain text, or HTML, or anything else you choose to define, in fact. None of that would be placed into $_POST either. $_POST is a convenience special case provided by PHP for the common form-data format. That one is the special case, not the JSON! – ADyson Feb 04 '22 at 13:30

0 Answers0