'Unauthorized']); exit; } use Dotenv\Dotenv; header('Content-Type: text/plain; charset=utf-8'); ini_set('display_errors', '1'); error_reporting(E_ALL); $dotenv = Dotenv::createImmutable(dirname(__DIR__, 2)); $dotenv->load(); $baseUrl = $_ENV['API_BASE_URL']; $username = $_ENV['API_USERNAME']; $password = $_ENV['API_PASSWORD']; $scriptStart = microtime(true); // ── 1. Autenticazione (stessa logica della classe originale) ────────────── $ch = curl_init("{$baseUrl}/api/authentication/authenticate"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'Username' => $username, 'Password' => $password ])); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Accept: application/json' ]); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $authResponse = curl_exec($ch); $authHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($authHttpCode !== 200) { echo "AUTH FAILED: HTTP {$authHttpCode}\n{$authResponse}\n"; exit; } $tokenData = json_decode($authResponse, true); $token = null; if (is_array($tokenData) && isset($tokenData['token'])) { $token = $tokenData['token']; } elseif (is_string($tokenData)) { $token = trim($tokenData, '"'); } else { $token = trim($authResponse, '"'); } if (empty($token)) { echo "TOKEN NOT RECEIVED\n{$authResponse}\n"; exit; } $authElapsed = microtime(true) - $scriptStart; // ── 2. Richiesta $metadata (XML, non JSON) ───────────────────────────────── // Cache-buster nell'URL: alcuni server/reverse-proxy potrebbero cachare per URL esatto. $cacheBuster = uniqid('cb_', true); $metadataUrl = "{$baseUrl}/api/odata/\$metadata?_cb={$cacheBuster}"; $metadataStart = microtime(true); $ch = curl_init($metadataUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer {$token}", "Accept: application/xml" ]); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HEADER, true); // includi header risposta per ispezione $rawResponse = curl_exec($ch); $curlInfo = curl_getinfo($ch); $httpCode = $curlInfo['http_code']; $curlTotalTime = $curlInfo['total_time']; $curlError = curl_error($ch); $headerSize = $curlInfo['header_size']; curl_close($ch); $metadataElapsed = microtime(true) - $metadataStart; if ($rawResponse === false || $httpCode !== 200) { echo "METADATA REQUEST FAILED: HTTP {$httpCode}\nError: {$curlError}\n{$rawResponse}\n"; exit; } $responseHeaders = substr($rawResponse, 0, $headerSize); $xml = substr($rawResponse, $headerSize); echo "==================== TIMING (prova che NON è cache) ====================\n"; echo "Tempo autenticazione: " . round($authElapsed * 1000, 1) . " ms\n"; echo "Tempo chiamata \$metadata (curl total_time): " . round($curlTotalTime * 1000, 1) . " ms\n"; echo "Tempo chiamata \$metadata (wall clock PHP): " . round($metadataElapsed * 1000, 1) . " ms\n"; echo "Cache-buster usato: {$cacheBuster}\n"; echo "Dimensione XML ricevuto: " . strlen($xml) . " bytes\n\n"; echo "==================== HEADER RISPOSTA (controlla se c'è Cache-Control/Age/X-Cache) ====================\n"; echo $responseHeaders . "\n"; // ── 3. Estrai tutti gli EntitySet disponibili ────────────────────────────── echo "==================== ENTITY SETS DISPONIBILI ====================\n"; if (preg_match_all('/]*>(.*?)<\/EntityType>/s', $xml, $entityMatches, PREG_SET_ORDER)) { foreach ($entityMatches as $entity) { $entityName = $entity[1]; $entityBody = $entity[2]; echo "\n--- EntityType: {$entityName} ---\n"; if (preg_match_all('/