如何在CURLOPT_READFUNCTION函数中写入curl的ERRORBUFFER?

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

我在 C++ 项目中使用curl 将文件上传到服务。由于我们使用内部公司框架类来读取文件,因此我们为此定义了 READFUNCTION。内部函数可能会抛出异常,所以我想捕获它。

我的第一个想法是放置一个 try-catch

curl_easy_perform
,但我不确定这是否有效。

相反,我阅读了curl如何处理错误,并找到了ERRORBUFFER。但如何访问它?

// inside some other function
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, (char*) curlErrorBuffer);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file);


// the READFUNCTION
size_t read_data_from_file(char* buffer, size_t size, size_t nitems, File* file) {
  size_t nread = 0;
  try {
    nread = file->read(buffer, size * nitems);
  }
  catch (ReadError &e) {
    nread = CURL_READFUNC_ABORT;
    // How to write to ERRORBUFFER?
    // strncpy(ERRORBUFFER, "Failed to read file, " + e.msg, BUF_SIZE);
  }
  return nread;
}

有没有办法在不将其设为全局的情况下访问 ERROBUFFER?在

curl_easy_perform
周围使用 try-catch 也可以吗?

c++ curl
1个回答
0
投票

在处理 libcurl 及其与使用异常的系统(例如 C++ 框架)的集成时,需要牢记一些注意事项。

使用 Try-Catch 周围

curl_easy_perform

curl_easy_perform()
周围放置一个 try-catch 块确实会捕获从 read 函数抛出的异常,假设你的库通过外部 C 风格的回调传播异常(这不是典型的或简单的)。如果您的 read 函数抛出一个未在函数本身内处理的异常,并且您的设置允许异常从 C 风格的回调中传播,那么它可以被这样的 try-catch 捕获。然而,这通常是不安全或不推荐的,因为像 libcurl 这样的 C 库并不是设计来通过回调处理异常的,如果库不支持异常,这样做可能会导致资源泄漏或未定义的行为。

访问错误缓冲区

关于

ERRORBUFFER
,libcurl 使用此缓冲区来存储其操作期间发生的错误消息。使用方法如下:

  1. 分配缓冲区:分配curl将用于存储错误消息的缓冲区。

       char curlErrorBuffer[CURL_ERROR_SIZE];
       curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlErrorBuffer);
       ```
    
    
  2. 设置选项:在调用

    curl_easy_perform
    之前,设置
    CURLOPT_ERRORBUFFER
    指向该缓冲区。

  3. 失败后检查:如果

    curl_easy_perform
    返回错误,您可以检查
    curlErrorBuffer
    以获取描述性错误消息。

关于在读取函数中设置错误消息,不幸的是,您无法直接写入

ERRORBUFFER
,因为它无法在
READFUNCTION
等回调函数中访问。相反,回调必须通过适当的返回代码(
CURL_READFUNC_ABORT
CURL_READFUNC_PAUSE
等)传达失败信息。

最佳实践

稳健地处理错误:

  • 在回调中设置返回代码:使用

    CURL_READFUNC_ABORT
    或类似功能从读取函数发出错误情况信号。

  • 使用附加状态:如果您需要传回详细的错误消息,您可以考虑设置一个附加状态对象,通过

    CURLOPT_READDATA
    选项传递给读取函数。此状态对象可以存储详细的错误消息或代码,您可以在
    curl_easy_perform
    完成后检查这些消息或代码。

    ```cpp
      struct TransferState {
          char* errorBuffer;  // Custom error buffer for storing messages
          File* file;
      };
    
      TransferState state = {curlErrorBuffer, &file};
      curl_easy_setopt(curl, CURLOPT_READDATA, &state);
      ```
    
      Then in your callback:
      ```cpp
      size_t read_data_from_file(char* buffer, size_t size, size_t nitems, TransferState* state) {
          try {
              return state->file->read(buffer, size * nitems);
          }
          catch (ReadError &e) {
              strncpy(state->errorBuffer, "Failed to read file", CURL_ERROR_SIZE);
              return CURL_READFUNC_ABORT;
          }
      }
      ```
    

此设置保持干净的错误处理,而不会跨 C 和 C++ 库的边界混合异常处理,从而更严格地遵循安全和可预测的编程实践。

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