83 lines
3.0 KiB
PHP
83 lines
3.0 KiB
PHP
<?php
|
|
|
|
// pp_fetch_debug.php — drop-in pour diagnostiquer les endpoints appelés par fetch
|
|
if (defined('PP_FETCH_DEBUG_BOOTSTRAP')) {
|
|
return;
|
|
}
|
|
define('PP_FETCH_DEBUG_BOOTSTRAP', true);
|
|
|
|
// Activer le mode debug par ?ppdebug=1 OU header HTTP_X_PP_DEBUG: 1
|
|
$PP_DEBUG = (
|
|
(isset($_GET['ppdebug']) && $_GET['ppdebug'] === '1') ||
|
|
(isset($_SERVER['HTTP_X_PP_DEBUG']) && $_SERVER['HTTP_X_PP_DEBUG'] === '1')
|
|
);
|
|
|
|
// Correlation ID pour lier log <-> réponse
|
|
try {
|
|
$CID = bin2hex(random_bytes(6));
|
|
} catch (\Throwable $e) {
|
|
$CID = uniqid();
|
|
}
|
|
if (!headers_sent()) {
|
|
header('X-PP-CID: ' . $CID);
|
|
// Exposer les entêtes aux scripts front (même si cross-origin CORS le permet)
|
|
header('Access-Control-Expose-Headers: X-PP-CID, X-PP-Error, X-PP-Error-Code');
|
|
}
|
|
|
|
// Chemin du log (modifiable)
|
|
$logFile = __DIR__ . '/logs/pp_fetch.log';
|
|
@is_dir(dirname($logFile)) || @mkdir(dirname($logFile), 0775, true);
|
|
|
|
$pp_log = function (string $level, string $message, array $ctx = []) use ($logFile, $CID) {
|
|
$line = date('c') . "\t" . $CID . "\t" . $level . "\t" . $message . "\t" .
|
|
json_encode($ctx, JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
|
// 3 = fichier
|
|
error_log($line, 3, $logFile);
|
|
};
|
|
|
|
// Optionnel : fonction globale de log manuel
|
|
if (!function_exists('pp_debug_log')) {
|
|
function pp_debug_log(string $label, $data = null)
|
|
{
|
|
global $pp_log;
|
|
if (isset($pp_log) && is_callable($pp_log)) {
|
|
$pp_log('NOTE', $label, ['data' => $data]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handler erreurs PHP (non fatales)
|
|
set_error_handler(function ($severity, $message, $file, $line) use ($pp_log, $PP_DEBUG) {
|
|
$pp_log('PHP_ERROR', $message, ['file' => $file, 'line' => $line, 'severity' => $severity]);
|
|
if ($PP_DEBUG && !headers_sent()) {
|
|
header('X-PP-Error: ' . $message);
|
|
header('X-PP-Error-Code: ' . (string)$severity);
|
|
}
|
|
return false; // laisser PHP continuer son flux normal
|
|
});
|
|
|
|
// Exceptions non catchées
|
|
set_exception_handler(function ($ex) use ($pp_log, $PP_DEBUG) {
|
|
$pp_log('EXCEPTION', $ex->getMessage(), [
|
|
'file' => $ex->getFile(), 'line' => $ex->getLine(), 'trace' => $ex->getTraceAsString()
|
|
]);
|
|
if ($PP_DEBUG && !headers_sent()) {
|
|
header('X-PP-Error: ' . $ex->getMessage());
|
|
header('X-PP-Error-Code: EXCEPTION');
|
|
}
|
|
http_response_code(500); // status utile pour le front, le body reste inchangé
|
|
});
|
|
|
|
// Fatales (parse, compile, etc.) — typiquement ce qui laisse un body vide et casse le JSON
|
|
register_shutdown_function(function () use ($pp_log, $PP_DEBUG) {
|
|
$e = error_get_last();
|
|
if ($e && in_array($e['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR], true)) {
|
|
$pp_log('FATAL', $e['message'], ['file' => $e['file'], 'line' => $e['line'], 'type' => $e['type']]);
|
|
if ($PP_DEBUG && !headers_sent()) {
|
|
header('X-PP-Error: ' . $e['message']);
|
|
header('X-PP-Error-Code: ' . (string)$e['type']);
|
|
}
|
|
http_response_code(500);
|
|
}
|
|
});
|