You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pino(pinojs)仅记录部分HTTP请求:Safari下POST重定向无日志

Pino HTTP日志在Safari下不记录返回重定向的POST请求(关联connect-pg-simple)

问题现象

基于Node.js + Express + PostgreSQL的Web应用中,添加pino-http日志后出现以下异常:

  • 仅Safari浏览器中,返回重定向的HTTP POST请求不会被pino记录;
  • 使用Chrome或curl发起相同请求时,日志正常生成;
  • 移除connect-pg-simple作为express-session的存储后端后,问题完全消失;
  • 全程无任何报错信息,仅表现为日志缺失。

复现代码如下:

import { default as express } from 'express'
import { default as pinoHttp } from 'pino-http'
import { default as session } from 'express-session';
import { default as sessionStore } from 'connect-pg-simple';

import { default as pg } from 'pg';
const Pool = pg.Pool
const pool = new Pool()

const reqLogger = pinoHttp({
    level: 'info',
    enabled: true
})

const app = express()

app.use(session({
    secret: 'secret',
    name: 'sessionId',
    resave: false,
    rolling: true,
    saveUninitialized: true,
    store: new (sessionStore(session))({
        pool: pool
    }),
    cookie: {
        secure: 'auto',
        maxAge: 30 * 24 * 60 * 60 * 1000
    }
}))

app.use(reqLogger)

app.get('/', (req, res, next) => {
    const html = `
        <form method="POST" action="/">
            <div>
                <label for="floatingInput">Username</label>
                <input name="username" type="text" id="floatingInput">
            </div>
            <div>
                <label for="floatingPassword">Password</label>
                <input name="password" type="password" id="floatingPassword">
            </div>

            <button type="submit">Log in</button>
        </form>`
    res.send(html)
})

app.post('/', (req, res, next) => {
    res.redirect('/')
})

app.listen(8081, () => {
    console.log('Server running')
})

原因分析

核心冲突来自组件异步时机与Safari的重定向处理逻辑:

  1. pino-http默认依赖响应的finish事件生成日志,该事件需等待响应完全发送到客户端后触发;
  2. 开启rolling: true时,express-session会通过connect-pg-simple异步更新session的过期时间(写入PostgreSQL);
  3. Safari收到重定向响应后会立即断开连接,导致Node.js端的finish事件未触发,pino因此无法生成日志;
  4. Chrome/curl的重定向处理会等待响应完全结束,所以finish事件能正常触发。

解决方案

方案1:手动等待Session保存完成后再重定向

在POST路由中,先等待session的异步保存操作完成,再发送重定向响应,确保finish事件能被pino捕获:

app.post('/', async (req, res, next) => {
    // 等待session保存到PostgreSQL完成
    await new Promise(resolve => req.session.save(resolve));
    res.redirect('/');
})

方案2:调整Pino的日志触发时机

修改pino-http配置,强制在响应发送时记录日志,不依赖finish事件:

const reqLogger = pinoHttp({
    level: 'info',
    enabled: true,
    onResponse: (req, res) => {
        req.log.info({
            method: req.method,
            url: req.url,
            statusCode: res.statusCode
        }, 'Request handled');
    }
})

方案3:临时调整Express-Session配置(验证用)

如果业务允许,可临时关闭rolling配置,避免每次请求触发session异步更新,验证问题是否消失:

app.use(session({
    // ...其他配置
    rolling: false, // 关闭每次请求更新session过期时间
    // ...其他配置
}))

验证步骤

  1. 应用上述任一方案后重启服务;
  2. 使用Safari访问页面并提交POST表单;
  3. 查看pino日志,确认POST请求已被正常记录。

内容的提问来源于stack exchange,提问作者rlp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 14:35:12