Skip to content

Commit 88c09c2

Browse files
refactor: Enhance CurlException to include response body and update error handling in cURL classes
1 parent f8e27ce commit 88c09c2

3 files changed

Lines changed: 81 additions & 48 deletions

File tree

shared/curlException.hpp

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,74 @@
1818

1919
namespace Curl
2020
{
21+
/**
22+
* @brief Custom exception for Curl wrapper.
23+
*
24+
*/
25+
class CurlException : public std::exception
26+
{
27+
public:
28+
/**
29+
* @brief Returns HTTP response code ID.
30+
*
31+
* @return long HTTP response code ID.
32+
*/
33+
long responseCode() const noexcept
34+
{
35+
return m_responseCode;
36+
}
37+
2138
/**
22-
* @brief Custom exception for Curl wrapper.
39+
* @brief Returns HTTP response body.
2340
*
41+
* @return const std::string& HTTP response body.
2442
*/
25-
class CurlException : public std::exception
43+
const std::string& responseBody() const noexcept
2644
{
27-
public:
28-
/**
29-
* @brief Returns HTTP response code ID.
30-
*
31-
* @return long HTTP response code ID.
32-
*/
33-
long responseCode() const noexcept
34-
{
35-
return m_responseCode;
36-
}
45+
return m_responseBody;
46+
}
3747

38-
/**
39-
* @brief Return error message.
40-
*
41-
* @return const char* Error message.
42-
*/
43-
const char* what() const noexcept override
44-
{
45-
return m_error.what();
46-
}
48+
/**
49+
* @brief Return error message.
50+
*
51+
* @return const char* Error message.
52+
*/
53+
const char* what() const noexcept override
54+
{
55+
return m_error.what();
56+
}
4757

48-
/**
49-
* @brief Construct a new Curl Exception object
50-
*
51-
* @param errorMessage Error message to show.
52-
* @param responseCode HTTP response code ID.
53-
*/
54-
CurlException(const std::string& errorMessage, const long responseCode)
55-
: m_error {errorMessage}
56-
, m_responseCode {responseCode}
57-
{}
58+
/**
59+
* @brief Construct a new Curl Exception object
60+
*
61+
* @param errorMessage Error message to show.
62+
* @param responseCode HTTP response code ID.
63+
* @param responseBody HTTP response body (optional).
64+
*/
65+
CurlException(const std::string& errorMessage, const long responseCode, std::string responseBody = "")
66+
: m_error {errorMessage}
67+
, m_responseCode {responseCode}
68+
, m_responseBody {std::move(responseBody)}
69+
{
70+
}
5871

59-
/**
60-
* @brief Construct a new Curl Exception object
61-
*
62-
* @param curlException Pair object with an error message and a response code ID.
63-
*/
64-
explicit CurlException(const std::pair<const std::string&, const long>& curlException)
65-
: m_error {curlException.first}
66-
, m_responseCode {curlException.second}
67-
{}
72+
/**
73+
* @brief Construct a new Curl Exception object
74+
*
75+
* @param curlException Pair object with an error message and a response code ID.
76+
*/
77+
explicit CurlException(const std::pair<const std::string&, const long>& curlException)
78+
: m_error {curlException.first}
79+
, m_responseCode {curlException.second}
80+
, m_responseBody {}
81+
{
82+
}
6883

69-
private:
70-
std::runtime_error m_error;
71-
const long m_responseCode;
72-
};
73-
}
84+
private:
85+
std::runtime_error m_error;
86+
const long m_responseCode;
87+
const std::string m_responseBody;
88+
};
89+
} // namespace Curl
7490

7591
#endif // _CURL_EXCEPTION_HPP

src/curlSingleHandler.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class cURLSingleHandler final : public ICURLHandler
5353
long responseCode;
5454
const auto resGetInfo {curl_easy_getinfo(m_curlHandler.get(), CURLINFO_RESPONSE_CODE, &responseCode)};
5555

56-
curl_easy_reset(m_curlHandler.get());
56+
// DON'T reset here anymore
57+
// curl_easy_reset(m_curlHandler.get());
5758

5859
if (resPerform != CURLE_OK)
5960
{
@@ -63,10 +64,14 @@ class cURLSingleHandler final : public ICURLHandler
6364
{
6465
throw std::runtime_error("cURLSingleHandler::execute() failed: Couldn't get HTTP response code");
6566
}
67+
// Throw exception WITHOUT resetting - response data is still available
6668
throw Curl::CurlException(curl_easy_strerror(resPerform), responseCode);
6769
}
6870
throw std::runtime_error(curl_easy_strerror(resPerform));
6971
}
72+
73+
// Only reset on success
74+
curl_easy_reset(m_curlHandler.get());
7075
}
7176
};
7277

src/curlWrapper.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ class cURLWrapper final : public IRequestImplementator
117117

118118
this->setOptionPtr(OPT_WRITEDATA, &m_response);
119119

120-
this->setOptionLong(OPT_FAILONERROR, 1l);
120+
// this->setOptionLong(OPT_FAILONERROR, 1l);
121+
122+
// Note: The OPT_FAILONERROR option makes cURL fail on HTTP response codes >= 400.
123+
// However, in such cases we want to capture the response body, so we don't set it.
124+
// Instead, we handle HTTP errors in the execute() method.
121125

122126
this->setOptionLong(OPT_FOLLOW_REDIRECT, 1l);
123127

@@ -216,7 +220,15 @@ class cURLWrapper final : public IRequestImplementator
216220
throw std::runtime_error("cURLWrapper::execute() failed: Couldn't set HTTP headers");
217221
}
218222

219-
m_curlHandler->execute();
223+
try
224+
{
225+
m_curlHandler->execute();
226+
}
227+
catch (Curl::CurlException& ex)
228+
{
229+
// Note: m_returnValue contains the response body, even for errors
230+
throw Curl::CurlException(ex.what(), ex.responseCode(), m_returnValue);
231+
}
220232
}
221233
};
222234

0 commit comments

Comments
 (0)