php模拟post请求日志记录_phppost请求日志教程【技巧】

11次阅读

php用file_get_contents+stream_context_create发POST最轻量,需手动设method/header/content、ignore_errors=true捕获非200响应,并用jsON格式记全请求响应日志,避免纯文本拼接。

php模拟post请求日志记录_phppost请求日志教程【技巧】

PHP 用 file_get_contents + stream_context_create 发 POST 并记日志

直接用 file_get_contents 发 POST 是最轻量、无依赖的方式,适合简单接口调用。但默认不记录请求体和响应头,必须手动拼装上下文并捕获错误。

关键点在于:请求体要转成 http_build_query(或 json 字符串),Content-Type 必须匹配;日志需在调用前后分别记录原始数据和返回值,不能只记 $result

  • stream_context_createhttp 选项里必须设 methodheadercontent,缺一不可
  • 若服务端返回非 200 状态码file_get_contents 默认返回 false,需开启 ignore_errors => true 才能拿到响应体
  • 日志建议写入文件时加 date('c') 和唯一 microtime(true),避免并发覆盖
log: [2024-06-15T14:22:33+08:00] POST to https://api.example.com/v1/login data: {"username":"test","password":"123"} response_code: 401 body: {"error":"invalid credentials"}

curl 记完整请求/响应(含 header、cookie、重定向)

需要调试鉴权、跳转、多段响应或上传文件时,cURL 是唯一靠谱选择。它能精确控制每个环节,并通过 CURLOPT_HEADERFUNCTIONCURLOPT_WRITEFUNCTION 分离捕获 header 与 body。

注意:CURLOPT_RETURNTRANSFER 必须为 true,否则输出直接刷到 stdout;CURLOPT_VERBOSE 虽可打印调试信息,但会干扰日志结构,不推荐生产使用。

立即学习PHP免费学习笔记(深入)”;

  • curl_setopt_array 统一设置,避免漏掉 CURLOPT_TIMEOUT 导致请求卡死
  • 记录 header 时,CURLOPT_HEADERFUNCTION 回调函数接收两个参数:cURL 句柄和当前行字符串,需自行拼接
  • 敏感字段如 Authorizationcookie 在日志中应做掩码处理,例如 substr($value, 0, 4) . '***'

日志格式统一用 JSON,别用纯文本拼接

纯文本日志查起来痛苦,尤其是当 response body 是嵌套 JSON 时。直接把整个请求上下文序列化成一行 JSON,后续可用 jqelk 快速过滤。

不要手写 "url:".$url.", data:".$data 这种格式——引号、逗号、换行全会错乱,json_encode 自动处理转义和结构。

  • 必录字段:时间戳(microtime(true))、URL、HTTP 方法、请求头(只录 key/value,排除 User-Agent 等固定值)、请求体(限长截断,如前 1024 字节)、状态码、响应头(同上)、响应体(同样截断)
  • JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES 避免日志里出现 uXXXX 或 /
  • 日志文件按天轮转,例如 post_log_20240615.json,用 file_put_contents($file, $line.PHP_EOL, FILE_appEND)

线上禁用 display_errors,但要确保错误进日志

开发时开 display_errors 看报错很爽,但上线后暴露 curl_exec(): ssl certificate problem 这类信息等于送情报。所有错误必须收敛到日志,且区分「请求失败」和「业务异常」。

  • curl_error($ch)curl_errno($ch) 必须记录,它们比 HTTP 状态码更底层(比如 dns 解析失败、连接超时)
  • set_error_handler 拦住 E_WARNING 级别的 cURL 警告,防止被忽略
  • 如果用了 Guzzle 等封装库,务必关掉其默认的 debug => true,否则会把整个 socket 流打到日志里

真正难的不是发一次 POST,而是当 100 个并发请求里有 3 个超时、2 个证书错误、1 个返回了空 body 时,你能从日志里 5 秒内定位出是哪台机器、哪个证书过期、哪个字段没 trim 空格。日志结构决定排查效率,而不是行数多少。

text=ZqhQzanResources