Skip to content

Commit 335f7c1

Browse files
author
ejacques
committed
allow custom callback and response, fix CI
Enables streaming get, and out-of-band termination of connection. Had to fix CI as well. Added necessary tests, and enabled a previously disabled test.
1 parent 7d31d1e commit 335f7c1

File tree

9 files changed

+377
-119
lines changed

9 files changed

+377
-119
lines changed

Makefile.am

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,35 @@ librestclient_cpp_la_LDFLAGS=-version-info 2:1:1
1616

1717
dist_doc_DATA = README.md
1818

19-
.PHONY: test check clean-coverage-files coverage-html include/restclient-cpp/version.h lint ci docker-services
19+
.PHONY: test check clean-coverage-files coverage-html include/restclient-cpp/version.h lint ci docker-services clean-docker-services
2020

2121
include/restclient-cpp/version.h:
2222
m4 -I ${top_srcdir}/m4 -DM4_RESTCLIENT_VERSION=$(PACKAGE_VERSION) version.h.m4 > ${top_srcdir}/$@
2323

2424

2525

26-
test: check
26+
test: check docker-services
2727
./test-program
2828

2929
valgrind: check
3030
valgrind --leak-check=full --error-exitcode=1 ./test-program
3131

3232
lint:
33-
cpplint --filter=-legal/copyright include/restclient-cpp/*.h source/*.cc
33+
cpplint --filter=-legal/copyright --root=$(CURDIR) include/restclient-cpp/*.h source/*.cc
3434

3535
docker-services:
36-
docker inspect --format="{{ .State.Running }}" restclient-proxy &> /dev/null || docker run -d --name restclient-proxy -p 3128:3128 chrisdaish/squid
37-
docker ps -a
38-
39-
ci: lint docker-services test valgrind
36+
[ -n "$$(docker ps --quiet --filter name=restclient-cpp-httpbin)" ] || \
37+
docker run --detach -p 8998:80 --name restclient-cpp-httpbin kennethreitz/httpbin
38+
[ -n "$$(docker ps --quiet --filter name=restclient-cpp-squid)" ] || \
39+
docker run --detach -p 3128:3128 --name restclient-cpp-squid \
40+
--volume "$(CURDIR)/test/squid.conf:/etc/squid/squid.conf:ro" sameersbn/squid:3.5.27-2
41+
docker ps --all --filter 'name=^restclient-cpp-'
42+
43+
clean-docker-services:
44+
docker rm --force restclient-cpp-httpbin 2>/dev/null || true
45+
docker rm --force restclient-cpp-squid 2>/dev/null || true
46+
47+
ci: lint test valgrind
4048

4149
clean-local:
4250
find . -name "*.gcda" -print0 | xargs -0 rm

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,47 @@ conn->SetFileProgressCallback(progressFunc);
175175
conn->SetFileProgressCallbackData(data);
176176
```
177177
178+
### Write callback
179+
180+
A write callback function can be provided for processing data as it's received from a GET call (for instance the [Kubernetes Watch API](https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes)).
181+
182+
Calling `conn->SetWriteFunction(callback)` with a function parameter matching the prototype `size_t write_function(void *data, size_t size, size_t nmemb, void *userdata)int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)` will setup the write function.
183+
184+
Here is an example of a write callback function, processing result data line by line.
185+
186+
```cpp
187+
auto writeCallback = [](void *data, size_t size, size_t nmemb, void *userdata) -> size_t
188+
{
189+
size_t bytes = size * nmemb;
190+
try
191+
{
192+
// Add to the buffer
193+
auto res = reinterpret_cast<RestClient::Response *>(userdata);
194+
res->body.append(static_cast<char*>(data), bytes);
195+
// If the last character is not a new line, wait for the rest.
196+
if ('\n' != *(res->body.end() - 1))
197+
{
198+
return bytes;
199+
}
200+
// Process data one line at a time.
201+
std::stringstream stream(res->body);
202+
std::string line;
203+
while (std::getline(stream, line))
204+
{
205+
// Do something with the line here...
206+
}
207+
// Done processing the line
208+
res->body.clear();
209+
}
210+
catch(std::exception e)
211+
{
212+
// Log caught exception here
213+
return 0;
214+
}
215+
return bytes;
216+
};
217+
```
218+
178219
## Error handling
179220
When restclient-cpp encounters an error, generally the error (or "status") code is returned in the `Response` (see
180221
[Response struct in restclient.h](https://github.com/mrtazz/restclient-cpp/blob/master/include/restclient-cpp/restclient.h)). This error code can be either

include/restclient-cpp/connection.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
*/
2323
namespace RestClient {
2424

25+
/**
26+
* @brief define type used for RestClient write callback
27+
*/
28+
typedef size_t (*WriteCallback)(void *data, size_t size,
29+
size_t nmemb, void *userdata);
30+
2531
/**
2632
* @brief Connection object for advanced usage
2733
*/
@@ -146,6 +152,9 @@ class Connection {
146152
explicit Connection(const std::string& baseUrl);
147153
~Connection();
148154

155+
// Terminate open connection
156+
void Terminate();
157+
149158
// Instance configuration methods
150159
// configure basic auth
151160
void SetBasicAuth(const std::string& username,
@@ -193,6 +202,9 @@ class Connection {
193202
// set CURLOPT_UNIX_SOCKET_PATH
194203
void SetUnixSocketPath(const std::string& unixSocketPath);
195204

205+
// set CURLOPT_WRITEFUNCTION
206+
void SetWriteFunction(WriteCallback write_callback);
207+
196208
std::string GetUserAgent();
197209

198210
RestClient::Connection::Info GetInfo();
@@ -220,7 +232,12 @@ class Connection {
220232
RestClient::Response head(const std::string& uri);
221233
RestClient::Response options(const std::string& uri);
222234

235+
// GET with custom response structure
236+
RestClient::Response*
237+
get(const std::string& uri, RestClient::Response* response);
238+
223239
private:
240+
CURL* getCurlHandle();
224241
CURL* curlHandle;
225242
std::string baseUrl;
226243
RestClient::HeaderFields headerFields;
@@ -244,6 +261,9 @@ class Connection {
244261
std::string uriProxy;
245262
std::string unixSocketPath;
246263
char curlErrorBuf[CURL_ERROR_SIZE];
264+
RestClient::WriteCallback writeCallback;
265+
RestClient::Response*
266+
performCurlRequest(const std::string& uri, RestClient::Response* resp);
247267
RestClient::Response performCurlRequest(const std::string& uri);
248268
};
249269
}; // namespace RestClient

0 commit comments

Comments
 (0)