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

PHP 用 file_get_contents + stream_context_create 发 POST 并记日志
直接用 file_get_contents 发 POST 是最轻量、无依赖的方式,适合简单接口调用。但默认不记录请求体和响应头,必须手动拼装上下文并捕获错误。
关键点在于:请求体要转成 http_build_query(或 JSON 字符串),Content-Type 必须匹配;日志需在调用前后分别记录原始数据和返回值,不能只记 $result。
-
stream_context_create的http选项里必须设method、header、content,缺一不可 - 若服务端返回非 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_HEADERFUNCTION 和 CURLOPT_WRITEFUNCTION 分离捕获 header 与 body。
注意:CURLOPT_RETURNTRANSFER 必须为 true,否则输出直接刷到 stdout;CURLOPT_VERBOSE 虽可打印调试信息,但会干扰日志结构,不推荐生产使用。
立即学习“PHP免费学习笔记(深入)”;
- 用
curl_setopt_array统一设置,避免漏掉CURLOPT_TIMEOUT导致请求卡死 - 记录 header 时,
CURLOPT_HEADERFUNCTION回调函数接收两个参数:cURL 句柄和当前行字符串,需自行拼接 - 敏感字段如
Authorization、Cookie在日志中应做掩码处理,例如substr($value, 0, 4) . '***'
日志格式统一用 JSON,别用纯文本拼接
纯文本日志查起来痛苦,尤其是当 response body 是嵌套 JSON 时。直接把整个请求上下文序列化成一行 JSON,后续可用 jq 或 ELK 快速过滤。
不要手写 "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 空格。日志结构决定排查效率,而不是行数多少。











