Laravel 7中OPTIONS预检500错误无法被Handler.php拦截,如何追踪堆栈?
排查PHP中OPTIONS预检请求500错误的日志拦截方法
以下是几种能直接捕获OPTIONS请求错误的实用方法:
在入口文件最顶部添加全局错误捕获
预检请求可能在框架中间件或Handler执行前就触发了致命错误,因此直接在项目入口(如index.php)最顶部添加错误捕获逻辑,能覆盖框架启动前的错误:<?php // 开启全量错误报告并指定日志路径 error_reporting(E_ALL); ini_set('display_errors', 1); ini_set('log_errors', 1); ini_set('error_log', '/var/www/html/php_errors.log'); // 替换为可写的日志路径 // 捕获致命错误 register_shutdown_function(function() { $fatalError = error_get_last(); if ($fatalError && in_array($fatalError['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { $errorMsg = "OPTIONS请求致命错误: {$fatalError['message']} | 文件: {$fatalError['file']} | 行号: {$fatalError['line']}"; error_log($errorMsg); // 手动返回CORS头避免浏览器重复报错 header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); header("Access-Control-Allow-Headers: Content-Type"); http_response_code(500); } }); // 捕获非致命错误 set_error_handler(function($errno, $errstr, $errfile, $errline) { $errorMsg = "OPTIONS请求错误: [$errno] $errstr | 文件: $errfile | 行号: $errline"; error_log($errorMsg); return true; }); // 捕获未处理的异常 set_exception_handler(function($exception) { $errorMsg = "OPTIONS请求异常: {$exception->getMessage()} | 文件: {$exception->getFile()} | 行号: {$exception->getLine()}"; error_log($errorMsg); error_log($exception->getTraceAsString()); // 返回CORS头 header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); header("Access-Control-Allow-Headers: Content-Type"); http_response_code(500); }); // 后续加载框架初始化代码 require __DIR__.'/vendor/autoload.php'; // ... 其他框架启动逻辑直接查看Web服务器日志
- Apache:检查默认日志路径(如
/var/log/apache2/error.log),里面会记录PHP致命错误、权限问题等底层错误。 - Nginx:查看Nginx错误日志(如
/var/log/nginx/error.log),同时确保PHP-FPM日志开启(在php-fpm.conf或pool.d/www.conf中设置error_log = /var/log/php-fpm.log),PHP-FPM日志会详细记录PHP层面的执行错误。
- Apache:检查默认日志路径(如
用curl手动模拟OPTIONS请求
绕过浏览器的CORS限制,直接向目标路由发送OPTIONS请求,查看原始响应内容:curl -X OPTIONS -v http://your-domain.com/[[route URL]]命令输出会显示服务器返回的500响应详情,若返回空白,结合Web服务器日志定位问题。
检查Web服务器对OPTIONS请求的放行配置
部分服务器可能在请求到达PHP前就拦截了OPTIONS请求,可通过配置放行:- Apache(
.htaccess):<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_METHOD} OPTIONS RewriteRule ^(.*)$ $1 [R=200,L] </IfModule> Header always set Access-Control-Allow-Origin "*" Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS" Header always set Access-Control-Allow-Headers "Content-Type" - Nginx(server块内):
location / { if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'Content-Type'; return 204; } # 其他路由配置 }
- Apache(
内容的提问来源于stack exchange,提问作者Sagefire
相关产品推荐
相关产品推荐

