POSTing with cURL

POSTing Data, Headers, Authentication and Share Handles

CURLOPT_POSTFIELDS makes a POST. An array would be sent as multipart form data, so encode JSON yourself. CURLOPT_USERPWD handles HTTP Basic authentication.

Three orders: no token, invalid data, and a valid orderPHP
<?php
$token = ['Authorization: Bearer shop-demo-token'];
foreach ([[[], 1, 2], [$token, 9, 0], [$token, 1, 2]] as [$auth, $id, $qty]) {
  $ch = curl_init('http://127.0.0.1:8218/orders');
  curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true,
    CURLOPT_POSTFIELDS => json_encode(['product_id' => $id, 'qty' => $qty]),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json', ...$auth]]);
  $response = curl_exec($ch);                              // headers, blank line, body
  preg_match('/^(Location|WWW-Authenticate): .*$/mi', $response, $header);
  echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), ' ', trim($header[0] ?? '-'), ' ',
    substr($response, curl_getinfo($ch, CURLINFO_HEADER_SIZE));
}
Output
401 WWW-Authenticate: Bearer {"title":"Missing or wrong token"}
422 - {"title":"Invalid order","errors":{"product_id":"unknown","qty":"1 to 10"}}
201 Location: /orders/5001 {"id":5001,"product_id":1,"qty":2}

Each new handle opens its own connection. A share handle from curl_share_init_persistent() (PHP 8.5) outlives the request, so later requests on the same FPM or Apache 129 worker reuse its DNS cache and connections. It refuses cookies, which would leak between users.

shared.php, requested three times on one keep-alive connectionPHP
<?php
$ch = curl_init('http://127.0.0.1:8218/products/1');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true,
  CURLOPT_SHARE => curl_share_init_persistent([CURL_LOCK_DATA_DNS, CURL_LOCK_DATA_CONNECT])]);
curl_exec($ch);
printf("worker %d: %d new connection(s)\n", getmypid(), curl_getinfo($ch, CURLINFO_NUM_CONNECTS));
Output
worker 187725: 1 new connection(s)
worker 187725: 0 new connection(s)
worker 187725: 0 new connection(s)

With plain curl_share_init(), all three requests connected anew. Apache passes Authorization to $_SERVER only with CGIPassAuth On, and without it every order failed with 401.