使用axios并期待413响应时如何处理EPIPE?

问题描述 投票:0回答:1

当向 API 发送太大的文件时,我得到:

Error: write EPIPE
    at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:94:16) {
  errno: -32,
  code: 'EPIPE',
  syscall: 'write'
}

服务器停止接收流并给出代码 413。我的应用程序崩溃,忽略任何 try catch 块。据我了解,这不是尝试可以捕获的。有没有其他方法可以使用 axios 处理这些错误? 这是我的代码:

import axios from "axios"
import { sleep } from "./utils/sleep"

export const debugEpipe = async (event) => {
  // Fake a big file
  const fileSizeInMb = event.fileSizeInMb
  const fileContent = Buffer.alloc(fileSizeInMb * 1024 * 1024, 'a')
    .toString('base64')

  try {
    const response = await axios.post(
      '/some-endpoint',
      {
        attachments: [
          {
            filename: 'bigfakefile.pdf',
            filetype: 'application/pdf',
            data: fileContent,
          }
        ],
      }
    )
  } catch(e) {
    console.log("This will show.")
    await sleep(1000)
    console.log("This will not show. The EPIPE error halts execution.")
  }
}
node.js axios
1个回答
0
投票

当 Node.js 进程尝试写入另一端已关闭的流时,会发生

EPIPE
错误:在这种情况下,当服务器确定有效负载太大并关闭连接时。

您需要在 Node.js 应用程序的不同级别实现错误处理机制,以处理使用

Axios
时出现的 EPIPE 错误,并期望得到类似 413 状态代码 (
Payload Too Large
)
之类的响应。

由于 Axios 是 基于 Promise 的,因此使用 try/catch 块捕获错误应该适用于大多数与 HTTP 相关的错误。

但是,由于

EPIPE
是系统级错误,因此 Axios 中基于 Promise 的错误处理可能并不总是能捕获它(
try/catch
.then().catch()
):它可能发生在 HTTP 生命周期之外请求由 Axios 管理。 为了确保您的应用程序能够优雅地处理此类错误,您可以在 Node.js 中实现全局错误处理,在流程级别捕获未处理的异常和未处理的 Promise 拒绝:

process.on('uncaughtException', (error) => { console.error('Unhandled Exception:', error); }); process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection:', reason); });

Axios拦截器可用于集中管理HTTP请求错误,包括在到达.catch()

块或被抛出到
async/await
上下文中之前重试逻辑或错误转换:

axios.interceptors.response.use(response => { // Handle successful response return response; }, error => { console.error("Intercepted error:", error); // Handle error // Optionally, tailor handling based on error specifics return Promise.reject(error); });
这不会阻止 

EPIPE

 错误,但可以确保您的应用程序可以记录它们并继续运行而不会崩溃。

完整的代码是:

import axios from 'axios'; import { sleep } from './utils/sleep'; const axiosInstance = axios.create(); // Add a response interceptor axiosInstance.interceptors.response.use( function (response) { // Any status code that lie within the range of 2xx cause this function to trigger // Do something with response data return response; }, function (error) { // Any status codes that falls outside the range of 2xx cause this function to trigger // Do something with response error console.error('Axios response error:', error); return Promise.reject(error); } ); // Add a request interceptor axiosInstance.interceptors.request.use( function (config) { // Do something before request is sent console.log('Sending request to:', config.url); return config; }, function (error) { // Do something with request error console.error('Axios request error:', error); return Promise.reject(error); } ); export const debugEpipe = async (event) => { const fileSizeInMb = event.fileSizeInMb; const fileContent = Buffer.alloc(fileSizeInMb * 1024 * 1024, 'a').toString('base64'); try { const response = await axiosInstance.post( '/some-endpoint', { attachments: [ { filename: 'bigfakefile.pdf', filetype: 'application/pdf', data: fileContent, } ], } ); console.log('Response status:', response.status); } catch (e) { console.error("Local error caught:", e); await sleep(1000); } }; // Global error handling process.on('uncaughtException', (error) => { console.error('Unhandled Exception:', error); }); process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection:', reason); });
该代码为 Axios 实例定义了请求和响应拦截器。

    请求拦截器会在发出请求之前记录请求发送到的 URL。
  • 响应拦截器记录响应处理过程中发生的错误。这些拦截器提供了钩子来在配置的 Axios 实例的所有使用中全局处理或记录请求和响应。
对于使用

await axiosInstance.post(...)

 发出的每个请求,都会使用 
try/catch
 块来处理特定于该请求的错误。这允许您处理可能特定于该请求的逻辑或上下文的错误,例如以不同的方式处理不同类型的 HTTP 响应错误。

它还包括用于未捕获的异常和未处理的承诺拒绝的全局错误处理程序。这些处理程序确保您的应用程序可以记录错误并对其做出反应,这些错误可能与 Axios 请求不直接相关,或者超出本地

try/catch

 块和 Axios 拦截器的控制范围。

© www.soinside.com 2019 - 2024. All rights reserved.