Modern C++20 SDK targeting CMake 3.20+. Library is RAII / move-only, backed by a libcurl easy handle per Client. Public surface is throwing; exception hierarchy under clawdforge::Error covers AuthError, APIError (carries status_code + body), TransportError, and ProtocolError. Dependencies: libcurl + nlohmann/json (FetchContent or find_package). Tests use cpp-httplib's in-process server + doctest. 12 test cases / 70 assertions cover healthz, run with JSON / text / 502 / files, multipart upload, full token CRUD, transport failure, URL normalization, and bad-input rejection. Clean under -Wall -Wextra -Wpedantic -Werror, ASan + UBSan clean (no leaks, no UB). upload_file streams via curl_mime_filedata — no in-memory buffering. Install path produces clawdforge::clawdforge target consumable via target_link_libraries; FetchContent path mirrors the existing Rust / Go SDK ergonomics. MIT licensed.
79 lines
2.2 KiB
C++
79 lines
2.2 KiB
C++
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Exception hierarchy for the clawdforge C++ SDK.
|
|
//
|
|
// All exceptions thrown by `clawdforge::Client` derive from `clawdforge::Error`,
|
|
// which itself derives from `std::runtime_error`. Catch `Error` for the
|
|
// catch-all path; catch the more specific subclasses when you need to branch.
|
|
|
|
#pragma once
|
|
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
namespace clawdforge {
|
|
|
|
/// Abstract base for every exception this SDK throws.
|
|
///
|
|
/// Inherits from `std::runtime_error`, so a top-level `catch (const std::exception&)`
|
|
/// will pick these up too.
|
|
class Error : public std::runtime_error {
|
|
public:
|
|
using std::runtime_error::runtime_error;
|
|
|
|
protected:
|
|
// Marker to keep this class abstract — instantiate one of the subclasses.
|
|
virtual void anchor_() const = 0;
|
|
};
|
|
|
|
/// Thrown for HTTP 401 / 403 responses or when a required token is missing on
|
|
/// the client side.
|
|
class AuthError final : public Error {
|
|
public:
|
|
using Error::Error;
|
|
|
|
private:
|
|
void anchor_() const override {}
|
|
};
|
|
|
|
/// Thrown for any non-2xx HTTP response that isn't an auth failure.
|
|
///
|
|
/// `status_code` is the HTTP status. `body` is the raw response body (already
|
|
/// truncated to a reasonable size by the SDK to keep error logs sane).
|
|
class APIError final : public Error {
|
|
public:
|
|
APIError(int status_code, std::string body, const std::string& msg)
|
|
: Error(msg), status_code_(status_code), body_(std::move(body)) {}
|
|
|
|
[[nodiscard]] int status_code() const noexcept { return status_code_; }
|
|
[[nodiscard]] const std::string& body() const noexcept { return body_; }
|
|
|
|
private:
|
|
int status_code_;
|
|
std::string body_;
|
|
|
|
void anchor_() const override {}
|
|
};
|
|
|
|
/// Thrown for libcurl-level transport problems (connect refused, DNS failure,
|
|
/// timeout, TLS handshake error, etc.).
|
|
class TransportError final : public Error {
|
|
public:
|
|
using Error::Error;
|
|
|
|
private:
|
|
void anchor_() const override {}
|
|
};
|
|
|
|
/// Thrown for malformed JSON in a response, or when the SDK can't construct a
|
|
/// valid HTTP request from caller input (bad URL, missing required field, …).
|
|
class ProtocolError final : public Error {
|
|
public:
|
|
using Error::Error;
|
|
|
|
private:
|
|
void anchor_() const override {}
|
|
};
|
|
|
|
} // namespace clawdforge
|