Cppinecone
A C++ client for the Pinecone vector database
http_client.hpp
Go to the documentation of this file.
1 #pragma once
10 #include <cassert>
11 #include <cstddef>
12 #include <cstdint>
13 #include <memory>
14 #include <optional>
15 #include <string>
16 #include <variant>
17 
18 #include <curl/curl.h>
19 #include <curl/easy.h>
20 #include <nlohmann/json.hpp>
21 
26 #include "pinecone/util/result.hpp"
27 
28 using json = nlohmann::json;
29 
30 namespace pinecone::net
31 {
32 static constexpr size_t kInitialDataSize = 1024;
33 static constexpr int64_t kHttpOk = 200;
34 static constexpr int64_t kHttpCreated = 201;
35 static constexpr int64_t kHttpAccepted = 202;
36 
41 template <threading_mode Mode>
42 struct http_client;
43 
44 static constexpr auto kContentType = "Content-Type: application/json; charset=utf-8";
45 
50 template <>
59  {
60  auto* curl_handle = curl_easy_init();
61  curl_slist* headers{};
62  headers = curl_slist_append(headers, kContentType);
63  headers = curl_slist_append(headers, args.api_key_header());
64  if (headers == nullptr) {
65  return nullptr;
66  }
67  return curl_handle != nullptr ? std::unique_ptr<http_client>(new http_client(
68  std::move(args), curl_handle, headers)) // NOLINT
69  : nullptr;
70  }
71 
72  ~http_client() noexcept
73  {
74  curl_easy_cleanup(_curl_handle);
75  curl_slist_free_all(_headers);
76  }
77 
78  http_client(http_client const&) = delete;
79  auto operator=(http_client const&) -> http_client& = delete;
80  http_client(http_client&&) noexcept = default;
81  auto operator=(http_client&&) noexcept -> http_client& = default;
82 
91  template <domain::operation_type Op, typename Body = std::monostate>
92  auto request(domain::operation_args<Op, Body> op_args) const noexcept
93  -> util::result<typename domain::operation_args<Op, Body>::parsed_type>
94  {
95  domain::operation<Op, Body> operation(std::move(op_args));
96  _data.clear();
97  auto result =
98  operation.set_opts(_curl_handle, _headers)
99  .and_then([this]() {
100  return curl_easy_setopt(_curl_handle, CURLOPT_WRITEFUNCTION, http_client::read);
101  })
102  .and_then([this]() { return curl_easy_setopt(_curl_handle, CURLOPT_WRITEDATA, this); })
103  .and_then([this]() { return curl_easy_perform(_curl_handle); });
104  if (result.is_error()) {
105  return {result.error()};
106  }
107 
108  int64_t http_code = 0;
109  curl_easy_getinfo(_curl_handle, CURLINFO_RESPONSE_CODE, &http_code);
110  switch (http_code) {
111  case kHttpOk:
112  case kHttpCreated:
113  case kHttpAccepted:
114  try {
115  return op_args.parse(_data);
116  } catch (json::exception& ex) {
117  return {std::move(ex)};
118  }
119  default:
120  return {http_code, std::string(_data.begin(), _data.end())};
121  }
122  }
123 
124  private:
125  auto receive_chunk(void* buffer, size_t n) noexcept -> size_t
126  {
127  auto* bytes = static_cast<uint8_t*>(buffer);
128  for (size_t i = 0; i < n; ++i) {
129  _data.emplace_back(*(bytes + i)); // NOLINT
130  }
131 
132  return n;
133  }
134 
135  public:
136  static auto read(void* buffer, size_t sz, size_t n, void* f) noexcept -> size_t
137  {
138  return static_cast<http_client*>(f)->receive_chunk(buffer, n * sz);
139  }
140 
141  private:
142  connection_args _args;
143  CURL* _curl_handle;
144  curl_slist* _headers;
145  mutable std::vector<uint8_t> _data;
146 
147  http_client(connection_args args, CURL* curl_handle, curl_slist* headers) noexcept
148  : _args(std::move(args)), _curl_handle(curl_handle), _headers(headers)
149  {
150  assert(_curl_handle != nullptr);
151  _data.reserve(kInitialDataSize);
152  }
153 };
154 } // namespace pinecone::net
User-facing arguments for networking operations.
threading_mode
Threading behaviors supported by http_client.
Definition: arguments.hpp:14
@ sync
Synchronous operation; in this mode, http_client instances are not thread-safe.
HTTP method definitions.
T move(T... args)
STL namespace.
Metaprogamming infrastructure for generation of per-operation code.
Operations made available by the Pinecone API.
T reserve(T... args)
Models the possibility of failure for Pinecone operations.
Operation-specific arguments.
Definition: operation.hpp:172
Data common to all Pinecone API operation types.
Definition: operation.hpp:181
constexpr auto set_opts(CURL *curl, curl_slist *headers) noexcept -> util::curl_result
Set CURL options for the operation.
Definition: operation.hpp:204
Arguments required to connect to a Pinecone server.
Definition: arguments.hpp:25
static auto build(connection_args args) noexcept -> std::unique_ptr< http_client >
Attempts to construct a synchronous HTTP client via user-specific connection_args.
Definition: http_client.hpp:58
An HTTP client responsible for making requests to a Pinecone instance.
Definition: http_client.hpp:42