VirtualBox

source: vbox/trunk/include/iprt/cpp/restclient.h@ 86716

Last change on this file since 86716 was 86681, checked in by vboxsync, 4 years ago

IPRT/rest: bugref:9167 - Add release logging for REST operations.
Request are logged at level 5, and responses at level 7, so they are
not on by default. The format is a bit ad-hoc, but all the essential
information should be there. It's mostly done in base classes except
for request bodies (it can probably be done in the base class too, but
would require more runtime logic, while here we can only generate them
as needed).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.5 KB
Line 
1/** @file
2 * IPRT - C++ Representational State Transfer (REST) Client Classes.
3 */
4
5/*
6 * Copyright (C) 2008-2020 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef IPRT_INCLUDED_cpp_restclient_h
27#define IPRT_INCLUDED_cpp_restclient_h
28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
31
32#include <iprt/http.h>
33#include <iprt/cpp/restbase.h>
34#include <iprt/cpp/reststringmap.h>
35
36
37/** @defgroup grp_rt_cpp_restclient C++ Representational State Transfer (REST) Client Classes.
38 * @ingroup grp_rt_cpp
39 * @{
40 */
41
42/**
43 * Specialization of RTCRestBinary for use with body parameters in a client.
44 *
45 * This enables registering data callbacks for provinding data to upload.
46 */
47class RT_DECL_CLASS RTCRestBinaryParameter : public RTCRestBinary
48{
49public:
50 /** Default constructor. */
51 RTCRestBinaryParameter() RT_NOEXCEPT;
52
53 /** Safe copy assignment method. */
54 virtual int assignCopy(RTCRestBinaryParameter const &a_rThat) RT_NOEXCEPT;
55 /** Safe copy assignment method.
56 * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
57 virtual int assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT RT_OVERRIDE;
58 /** Safe copy assignment method.
59 * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
60 virtual int assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
61
62 /**
63 * Use the specified data buffer directly.
64 * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
65 virtual int assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
66 /**
67 * Use the specified data buffer directly.
68 * @note This will assert and work like assignReadOnly. */
69 virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT RT_OVERRIDE;
70
71 /** Make a clone of this object. */
72 inline RTCRestBinaryParameter *clone() const RT_NOEXCEPT { return (RTCRestBinaryParameter *)baseClone(); }
73
74 /* Overridden methods: */
75 virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
76 virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
77 virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
78
79 /** Factory method. */
80 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
81
82 /**
83 * Retrieves the callback data.
84 */
85 inline void *getCallbackData() const RT_NOEXCEPT { return m_pvCallbackData; }
86
87 /**
88 * Sets the content-type for an upload.
89 *
90 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
91 * @param a_pszContentType The content type to set.
92 * If NULL, no content type is set.
93 */
94 int setContentType(const char *a_pszContentType) RT_NOEXCEPT;
95
96 /**
97 * Gets the content type that was set.
98 */
99 inline RTCString const &getContentType() const RT_NOEXCEPT { return m_strContentType; }
100
101 /**
102 * Gets the content-length value (UINT64_MAX if not available).
103 */
104 inline uint64_t getContentLength() const RT_NOEXCEPT { return m_cbContentLength; }
105
106 /**
107 * Callback for producing bytes to upload.
108 *
109 * @returns IPRT status code.
110 * @param a_pThis The related string object.
111 * @param a_pvDst Where to put the bytes.
112 * @param a_cbDst Max number of bytes to produce.
113 * @param a_offContent The byte offset corresponding to the start of @a a_pvDst.
114 * @param a_pcbActual Where to return the number of bytes actually produced.
115 *
116 * @remarks Use getCallbackData to get the user data.
117 *
118 * @note The @a a_offContent parameter does not imply random access or anthing
119 * like that, it is just a convenience provided by the caller. The value
120 * is the sum of the previously returned @a *pcbActual values.
121 */
122 typedef DECLCALLBACKTYPE(int, FNPRODUCER,(RTCRestBinaryParameter *a_pThis, void *a_pvDst, size_t a_cbDst,
123 uint64_t a_offContent, size_t *a_pcbActual)) /*RT_NOEXCEPT*/;
124 /** Pointer to a byte producer callback. */
125 typedef FNPRODUCER *PFNPRODUCER;
126
127 /**
128 * Sets the producer callback.
129 *
130 * @param a_pfnProducer The callback function for producing data.
131 * @param a_pvCallbackData Data the can be retrieved from the callback
132 * using getCallbackData().
133 * @param a_cbContentLength The amount of data that will be uploaded and
134 * to be set as the value of the content-length
135 * header field. Pass UINT64_MAX if not known.
136 *
137 * @note This will drop any buffer previously registered using setUploadData().
138 */
139 void setProducerCallback(PFNPRODUCER a_pfnProducer, void *a_pvCallbackData = NULL, uint64_t a_cbContentLength = UINT64_MAX) RT_NOEXCEPT;
140
141 /**
142 * Preprares transmission via the @a a_hHttp client instance.
143 *
144 * @returns IPRT status code.
145 * @param a_hHttp The HTTP client instance.
146 * @internal
147 */
148 virtual int xmitPrepare(RTHTTP a_hHttp) const RT_NOEXCEPT;
149
150 /**
151 * For completing and/or undoing setup from xmitPrepare.
152 *
153 * @param a_hHttp The HTTP client instance.
154 * @internal
155 */
156 virtual void xmitComplete(RTHTTP a_hHttp) const RT_NOEXCEPT;
157
158protected:
159 /** Number of bytes corresponding to content-length.
160 * UINT64_MAX if not known. Used both for unploads and downloads. */
161 uint64_t m_cbContentLength;
162 /** The content type if set (upload only). */
163 RTCString m_strContentType;
164 /** Pointer to user-registered producer callback function (upload only). */
165 PFNPRODUCER m_pfnProducer;
166 /** User argument for both callbacks (both). */
167 void *m_pvCallbackData;
168
169 /** @copydoc FNRTHTTPUPLOADCALLBACK */
170 static DECLCALLBACK(int) xmitHttpCallback(RTHTTP hHttp, void *pvBuf, size_t cbBuf, uint64_t offContent,
171 size_t *pcbActual, void *pvUser) RT_NOEXCEPT;
172
173private:
174 /* No copy constructor or copy assignment: */
175 RTCRestBinaryParameter(RTCRestBinaryParameter const &a_rThat);
176 RTCRestBinaryParameter &operator=(RTCRestBinaryParameter const &a_rThat);
177};
178
179
180/**
181 * Specialization of RTCRestBinary for use with responses in a client.
182 *
183 * This enables registering data callbacks for consuming downloaded data.
184 */
185class RT_DECL_CLASS RTCRestBinaryResponse : public RTCRestBinary
186{
187public:
188 /** Default constructor. */
189 RTCRestBinaryResponse() RT_NOEXCEPT;
190
191 /** Safe copy assignment method. */
192 virtual int assignCopy(RTCRestBinaryResponse const &a_rThat) RT_NOEXCEPT;
193 /** Safe copy assignment method. */
194 virtual int assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT RT_OVERRIDE;
195 /** Safe copy assignment method.
196 * @note This will assert and fail as it makes no sense for a download. */
197 virtual int assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
198
199 /**
200 * Use the specified data buffer directly.
201 * @note This will assert and fail as it makes no sense for a download.
202 */
203 virtual int assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
204 /**
205 * Use the specified data buffer directly.
206 * @note This will drop any previously registered producer callback and user data.
207 */
208 virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT RT_OVERRIDE;
209
210 /** Make a clone of this object. */
211 inline RTCRestBinaryResponse *clone() const RT_NOEXCEPT { return (RTCRestBinaryResponse *)baseClone(); }
212
213 /* Overridden methods: */
214 virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
215 virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
216 virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
217
218 /** Factory method. */
219 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
220
221 /**
222 * Retrieves the callback data.
223 */
224 inline void *getCallbackData() const RT_NOEXCEPT { return m_pvCallbackData; }
225
226 /**
227 * Sets the max size to download to memory.
228 *
229 * This also indicates the intention to download to a memory buffer, so it
230 * will drop any previously registered consumer callback and its user data.
231 *
232 * @param a_cbMaxDownload Maximum number of bytes to download to memory.
233 * If 0, a default is selected (currently 32MiB for
234 * 32-bit hosts and 128MiB for 64-bit).
235 */
236 void setMaxDownloadSize(size_t a_cbMaxDownload) RT_NOEXCEPT;
237
238 /**
239 * Gets the content-length value (UINT64_MAX if not available).
240 */
241 inline uint64_t getContentLength() const RT_NOEXCEPT { return m_cbContentLength; }
242
243 /**
244 * Callback for consuming downloaded bytes.
245 *
246 * @returns IPRT status code.
247 * @param a_pThis The related string object.
248 * @param a_pvSrc Buffer containing the bytes.
249 * @param a_cbSrc The number of bytes in the buffer.
250 * @param a_uHttpStatus The HTTP status code.
251 * @param a_offContent The byte offset corresponding to the start of @a a_pvSrc.
252 * @param a_cbContent The content length field value, UINT64_MAX if not available.
253 *
254 * @remarks Use getCallbackData to get the user data.
255 *
256 * @note The @a a_offContent parameter does not imply random access or anthing
257 * like that, it is just a convenience provided by the caller. The value
258 * is the sum of the previous @a a_cbSrc values.
259 */
260 typedef DECLCALLBACKTYPE(int, FNCONSUMER,(RTCRestBinaryResponse *a_pThis, const void *a_pvSrc, size_t a_cbSrc,
261 uint32_t a_uHttpStatus, uint64_t a_offContent, uint64_t a_cbContent)) /*RT_NOEXCEPT*/;
262 /** Pointer to a byte consumer callback. */
263 typedef FNCONSUMER *PFNCONSUMER;
264
265 /**
266 * Sets the consumer callback.
267 *
268 * @param a_pfnConsumer The callback function for consuming downloaded data.
269 * NULL if data should be stored in m_pbData (the default).
270 * @param a_pvCallbackData Data the can be retrieved from the callback
271 * using getCallbackData().
272 */
273 void setConsumerCallback(PFNCONSUMER a_pfnConsumer, void *a_pvCallbackData = NULL) RT_NOEXCEPT;
274
275 /**
276 * Preprares for receiving via the @a a_hHttp client instance.
277 *
278 * @returns IPRT status code.
279 * @param a_hHttp The HTTP client instance.
280 * @param a_fCallbackFlags The HTTP callback flags (status code spec).
281 * @internal
282 */
283 virtual int receivePrepare(RTHTTP a_hHttp, uint32_t a_fCallbackFlags) RT_NOEXCEPT;
284
285 /**
286 * For completing and/or undoing setup from receivePrepare.
287 *
288 * @param a_hHttp The HTTP client instance.
289 * @internal
290 */
291 virtual void receiveComplete(RTHTTP a_hHttp) RT_NOEXCEPT;
292
293protected:
294 /** Number of bytes corresponding to content-length.
295 * UINT64_MAX if not known. Used both for unploads and downloads. */
296 uint64_t m_cbContentLength;
297 /** Number of bytes downloaded thus far. */
298 uint64_t m_cbDownloaded;
299 /** Pointer to user-registered consumer callback function (download only). */
300 PFNCONSUMER m_pfnConsumer;
301 /** User argument for both callbacks (both). */
302 void *m_pvCallbackData;
303 /** Maximum data to download to memory (download only). */
304 size_t m_cbMaxDownload;
305
306 /** @copydoc FNRTHTTPDOWNLOADCALLBACK */
307 static DECLCALLBACK(int) receiveHttpCallback(RTHTTP hHttp, void const *pvBuf, size_t cbBuf, uint32_t uHttpStatus,
308 uint64_t offContent, uint64_t cbContent, void *pvUser) RT_NOEXCEPT;
309
310private:
311 /* No copy constructor or copy assignment: */
312 RTCRestBinaryResponse(RTCRestBinaryResponse const &a_rThat);
313 RTCRestBinaryResponse &operator=(RTCRestBinaryResponse const &a_rThat);
314};
315
316
317/**
318 * Base class for REST client requests.
319 *
320 * This encapsulates parameters and helps transform them into a HTTP request.
321 *
322 * Parameters can be transfered in a number of places:
323 * - Path part of the URL.
324 * - Query part of the URL.
325 * - HTTP header fields.
326 * - FORM body.
327 * - JSON body.
328 * - XML body.
329 * - ...
330 *
331 * They can be require or optional. The latter may have default values. In
332 * swagger 3 they can also be nullable, which means the null-indicator cannot
333 * be used for tracking optional parameters.
334 */
335class RT_DECL_CLASS RTCRestClientRequestBase
336{
337public:
338 RTCRestClientRequestBase() RT_NOEXCEPT;
339 virtual ~RTCRestClientRequestBase();
340 RTCRestClientRequestBase(RTCRestClientRequestBase const &a_rThat) RT_NOEXCEPT;
341 RTCRestClientRequestBase &operator=(RTCRestClientRequestBase const &a_rThat) RT_NOEXCEPT;
342
343 /**
344 * Reset all members to default values.
345 * @returns IPRT status code.
346 */
347 virtual int resetToDefault() RT_NOEXCEPT = 0;
348
349 /**
350 * Getter for the operation name. Provided by the generated
351 * subclasses so that base class code may use it for more
352 * informative logs.
353 */
354 virtual const char *getOperationName() const RT_NOEXCEPT = 0;
355
356 /**
357 * Prepares the HTTP handle for transmitting this request.
358 *
359 * @returns IPRT status code.
360 * @param a_pStrPath Where to set path parameters. Will be appended to the base path.
361 * @param a_pStrQuery Where to set query parameters.
362 * @param a_hHttp Where to set header parameters and such.
363 * @param a_pStrBody Where to set body parameters.
364 */
365 virtual int xmitPrepare(RTCString *a_pStrPath, RTCString *a_pStrQuery, RTHTTP a_hHttp, RTCString *a_pStrBody) const RT_NOEXCEPT = 0;
366
367 /**
368 * Always called after the request has been transmitted.
369 *
370 * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
371 * @param a_hHttp The HTTP handle the request was performed on.
372 */
373 virtual void xmitComplete(int a_rcStatus, RTHTTP a_hHttp) const RT_NOEXCEPT = 0;
374
375 /**
376 * Checks if there are were any assignment errors.
377 */
378 inline bool hasAssignmentErrors() const RT_NOEXCEPT { return m_fErrorSet != 0; }
379
380protected:
381 /** Set of fields that have been explicitly assigned a value. */
382 uint64_t m_fIsSet;
383 /** Set of fields where value assigning failed. */
384 uint64_t m_fErrorSet;
385
386 /** Path parameter descriptor. */
387 typedef struct
388 {
389 const char *pszName; /**< The name string to replace (including {}). */
390 size_t cchName; /**< Length of pszName. */
391 uint32_t fFlags; /**< The toString flags. */
392 uint8_t iBitNo; /**< The parameter bit number. */
393 } PATHPARAMDESC;
394
395 /** Path parameter state. */
396 typedef struct
397 {
398 RTCRestObjectBase const *pObj; /**< Pointer to the parameter object. */
399 size_t offName; /**< Maintained by worker. */
400 } PATHPARAMSTATE;
401
402 /**
403 * Do path parameters.
404 *
405 * @returns IPRT status code
406 * @param a_pStrPath The destination path.
407 * @param a_pszPathTemplate The path template string.
408 * @param a_cchPathTemplate The length of the path template string.
409 * @param a_paPathParams The path parameter descriptors (static).
410 * @param a_paPathParamStates The path parameter objects and states.
411 * @param a_cPathParams Number of path parameters.
412 */
413 int doPathParameters(RTCString *a_pStrPath, const char *a_pszPathTemplate, size_t a_cchPathTemplate,
414 PATHPARAMDESC const *a_paPathParams, PATHPARAMSTATE *a_paPathParamStates, size_t a_cPathParams) const RT_NOEXCEPT;
415
416 /** Query parameter descriptor. */
417 typedef struct
418 {
419 const char *pszName; /**< The parameter name. */
420 uint32_t fFlags; /**< The toString flags. */
421 bool fRequired; /**< Required or not. */
422 uint8_t iBitNo; /**< The parameter bit number. */
423 } QUERYPARAMDESC;
424
425 /**
426 * Do query parameters.
427 *
428 * @returns IPRT status code
429 * @param a_pStrQuery The destination string.
430 * @param a_paQueryParams The query parameter descriptors.
431 * @param a_papQueryParamObjs The query parameter objects, parallel to @a a_paQueryParams.
432 * @param a_cQueryParams Number of query parameters.
433 */
434 int doQueryParameters(RTCString *a_pStrQuery, QUERYPARAMDESC const *a_paQueryParams,
435 RTCRestObjectBase const **a_papQueryParamObjs, size_t a_cQueryParams) const RT_NOEXCEPT;
436
437 /** Header parameter descriptor. */
438 typedef struct
439 {
440 const char *pszName; /**< The parameter name. */
441 uint32_t fFlags; /**< The toString flags. */
442 bool fRequired; /**< Required or not. */
443 uint8_t iBitNo; /**< The parameter bit number. */
444 bool fMapCollection; /**< Collect headers starting with pszName into a map. */
445 } HEADERPARAMDESC;
446
447 /**
448 * Do header parameters.
449 *
450 * @returns IPRT status code
451 * @param a_hHttp Where to set header parameters.
452 * @param a_paHeaderParams The header parameter descriptors.
453 * @param a_papHeaderParamObjs The header parameter objects, parallel to @a a_paHeaderParams.
454 * @param a_cHeaderParams Number of header parameters.
455 */
456 int doHeaderParameters(RTHTTP a_hHttp, HEADERPARAMDESC const *a_paHeaderParams,
457 RTCRestObjectBase const **a_papHeaderParamObjs, size_t a_cHeaderParams) const RT_NOEXCEPT;
458};
459
460
461/**
462 * Base class for REST client responses.
463 */
464class RT_DECL_CLASS RTCRestClientResponseBase
465{
466public:
467 /** Default constructor. */
468 RTCRestClientResponseBase() RT_NOEXCEPT;
469 /** Destructor. */
470 virtual ~RTCRestClientResponseBase();
471 /** Copy constructor. */
472 RTCRestClientResponseBase(RTCRestClientResponseBase const &a_rThat);
473 /** Copy assignment operator. */
474 RTCRestClientResponseBase &operator=(RTCRestClientResponseBase const &a_rThat);
475
476 /**
477 * Resets the object state.
478 */
479 virtual void reset(void) RT_NOEXCEPT;
480
481 /**
482 * Getter for the operation name. Provided by the generated
483 * subclasses so that base class code may use it for more
484 * informative logs.
485 */
486 virtual const char *getOperationName() const RT_NOEXCEPT = 0;
487
488 /**
489 * Prepares the HTTP handle for receiving the response.
490 *
491 * This may install callbacks and such like.
492 *
493 * When overridden, the parent class must always be called.
494 *
495 * @returns IPRT status code.
496 * @param a_hHttp The HTTP handle to prepare for receiving.
497 */
498 virtual int receivePrepare(RTHTTP a_hHttp) RT_NOEXCEPT;
499
500 /**
501 * Called when the HTTP request has been completely received.
502 *
503 * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
504 * @param a_hHttp The HTTP handle the request was performed on.
505 * This can be NIL_RTHTTP should something fail early, in
506 * which case it is possible receivePrepare() wasn't called.
507 *
508 * @note Called before consumeBody() but after consumeHeader().
509 */
510 virtual void receiveComplete(int a_rcStatus, RTHTTP a_hHttp) RT_NOEXCEPT;
511
512 /**
513 * Callback that consumes HTTP body data from the server.
514 *
515 * @param a_pchData Body data.
516 * @param a_cbData Amount of body data.
517 *
518 * @note Called after consumeHeader().
519 */
520 virtual void consumeBody(const char *a_pchData, size_t a_cbData) RT_NOEXCEPT;
521
522 /**
523 * Called after status, headers and body all have been presented.
524 *
525 * @returns IPRT status code.
526 */
527 virtual void receiveFinal() RT_NOEXCEPT;
528
529 /**
530 * Getter for m_rcStatus.
531 * @returns Negative numbers are IPRT errors, positive are HTTP status codes.
532 */
533 inline int getStatus() const RT_NOEXCEPT { return m_rcStatus; }
534
535 /**
536 * Getter for m_rcHttp.
537 * @returns HTTP status code or VERR_NOT_AVAILABLE.
538 */
539 inline int getHttpStatus() const RT_NOEXCEPT { return m_rcHttp; }
540
541 /**
542 * Getter for m_pErrInfo.
543 */
544 inline PCRTERRINFO getErrInfo(void) const RT_NOEXCEPT { return m_pErrInfo; }
545
546 /**
547 * Getter for m_strContentType.
548 */
549 inline RTCString const &getContentType(void) const RT_NOEXCEPT { return m_strContentType; }
550
551
552protected:
553 /** Negative numbers are IPRT errors, positive are HTTP status codes. */
554 int m_rcStatus;
555 /** The HTTP status code, VERR_NOT_AVAILABLE if not set. */
556 int m_rcHttp;
557 /** Error information. */
558 PRTERRINFO m_pErrInfo;
559 /** The value of the Content-Type header field. */
560 RTCString m_strContentType;
561
562 PRTERRINFO getErrInfoInternal(void) RT_NOEXCEPT;
563 void deleteErrInfo(void) RT_NOEXCEPT;
564 void copyErrInfo(PCRTERRINFO pErrInfo) RT_NOEXCEPT;
565
566 /**
567 * Reports an error (or warning if a_rc non-negative).
568 *
569 * @returns a_rc
570 * @param a_rc The status code to report and return. The first
571 * error status is assigned to m_rcStatus, subsequent
572 * ones as well as informational statuses are not
573 * recorded by m_rcStatus.
574 * @param a_pszFormat The message format string.
575 * @param ... Message arguments.
576 */
577 int addError(int a_rc, const char *a_pszFormat, ...) RT_NOEXCEPT;
578
579 /**
580 * Deserializes a header field value.
581 *
582 * @returns IPRT status code.
583 * @param a_pObj The object to deserialize into.
584 * @param a_pchValue Pointer to the value (not zero terminated).
585 * Not necessarily valid UTF-8!
586 * @param a_cchValue The value length.
587 * @param a_fFlags Flags to pass to fromString().
588 * @param a_pszErrorTag The error tag (field name).
589 */
590 int deserializeHeader(RTCRestObjectBase *a_pObj, const char *a_pchValue, size_t a_cchValue,
591 uint32_t a_fFlags, const char *a_pszErrorTag) RT_NOEXCEPT;
592
593 /**
594 * Deserializes a header field value.
595 *
596 * @returns IPRT status code.
597 * @param a_pMap The string map object to deserialize into.
598 * @param a_pchField Pointer to the map field name. (Caller dropped the prefix.)
599 * Not necessarily valid UTF-8!
600 * @param a_cchField Length of field name.
601 * @param a_pchValue Pointer to the value (not zero terminated).
602 * Not necessarily valid UTF-8!
603 * @param a_cchValue The value length.
604 * @param a_fFlags Flags to pass to fromString().
605 * @param a_pszErrorTag The error tag (field name).
606 */
607 int deserializeHeaderIntoMap(RTCRestStringMapBase *a_pMap, const char *a_pchField, size_t a_cchField,
608 const char *a_pchValue, size_t a_cchValue, uint32_t a_fFlags, const char *a_pszErrorTag) RT_NOEXCEPT;
609
610 /**
611 * Helper that does the deserializing of the response body
612 * via deserializeBodyFromJsonCursor().
613 *
614 * @param a_pchData The body blob.
615 * @param a_cbData The size of the body blob.
616 * @param a_pszBodyName The name of the body parameter.
617 */
618 void deserializeBody(const char *a_pchData, size_t a_cbData, const char *a_pszBodyName) RT_NOEXCEPT;
619
620 /**
621 * Called by deserializeBody to do the actual body deserialization.
622 *
623 * @param a_rCursor The JSON cursor.
624 */
625 virtual void deserializeBodyFromJsonCursor(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT;
626
627 /**
628 * Primary json cursor for parsing bodies.
629 */
630 class PrimaryJsonCursorForBody : public RTCRestJsonPrimaryCursor
631 {
632 public:
633 RTCRestClientResponseBase *m_pThat; /**< Pointer to response object. */
634 PrimaryJsonCursorForBody(RTJSONVAL hValue, const char *pszName, RTCRestClientResponseBase *a_pThat) RT_NOEXCEPT;
635 virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...) RT_NOEXCEPT RT_OVERRIDE;
636 virtual int unknownField(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
637 };
638
639
640 /**
641 * Consumes a header.
642 *
643 * Child classes can override this to pick up their header fields, but must
644 * always call the parent class.
645 *
646 * @returns IPRT status code.
647 * @param a_uMatchWord Match word constructed by RTHTTP_MAKE_HDR_MATCH_WORD
648 * @param a_pchField The field name (not zero terminated).
649 * Not necessarily valid UTF-8!
650 * @param a_cchField The length of the field.
651 * @param a_pchValue The field value (not zero terminated).
652 * @param a_cchValue The length of the value.
653 */
654 virtual int consumeHeader(uint32_t a_uMatchWord, const char *a_pchField, size_t a_cchField,
655 const char *a_pchValue, size_t a_cchValue) RT_NOEXCEPT;
656
657private:
658 /** Callback for use with RTHttpSetHeaderCallback. */
659 static DECLCALLBACK(int) receiveHttpHeaderCallback(RTHTTP hHttp, uint32_t uMatchWord, const char *pchField, size_t cchField,
660 const char *pchValue, size_t cchValue, void *pvUser) RT_NOEXCEPT;
661};
662
663
664/**
665 * Base class for REST client responses.
666 */
667class RT_DECL_CLASS RTCRestClientApiBase
668{
669public:
670 RTCRestClientApiBase() RT_NOEXCEPT;
671 virtual ~RTCRestClientApiBase();
672
673 /** @name Host and Base path (URL) handling.
674 * @{ */
675 /**
676 * Gets the server URL.
677 */
678 const char *getServerUrl(void) const RT_NOEXCEPT;
679
680 /**
681 * Sets the whole server URL.
682 * @returns IPRT status code.
683 * @param a_pszUrl The new server URL. NULL/empty to reset to default.
684 */
685 int setServerUrl(const char *a_pszUrl) RT_NOEXCEPT;
686
687 /**
688 * Sets the scheme part of the the server URL.
689 * @returns IPRT status code.
690 * @param a_pszScheme The new scheme. Does not accept NULL or empty string.
691 */
692 int setServerScheme(const char *a_pszScheme) RT_NOEXCEPT;
693
694 /**
695 * Sets the authority (hostname + port) part of the the server URL.
696 * @returns IPRT status code.
697 * @param a_pszAuthority The new authority. Does not accept NULL or empty string.
698 */
699 int setServerAuthority(const char *a_pszAuthority) RT_NOEXCEPT;
700
701 /**
702 * Sets the base path part of the the server URL.
703 * @returns IPRT status code.
704 * @param a_pszBasePath The new base path. Does not accept NULL or empty string.
705 */
706 int setServerBasePath(const char *a_pszBasePath) RT_NOEXCEPT;
707
708 /**
709 * Gets the default server URL as specified in the specs.
710 * @returns Server URL.
711 */
712 virtual const char *getDefaultServerUrl() const RT_NOEXCEPT = 0;
713
714 /**
715 * Gets the default server base path as specified in the specs.
716 * @returns Host string (start of URL).
717 */
718 virtual const char *getDefaultServerBasePath() const RT_NOEXCEPT = 0;
719 /** @} */
720
721 /** Flags to doCall. */
722 enum
723 {
724 kDoCall_OciReqSignExcludeBody = 1, /**< Exclude the body when doing OCI request signing. */
725 kDoCall_RequireBody = 2 /**< The body is required. */
726 };
727
728protected:
729 /** Handle to the HTTP connection object. */
730 RTHTTP m_hHttp;
731 /** The server URL to use. If empty use the default. */
732 RTCString m_strServerUrl;
733
734 /* Make non-copyable (RTCNonCopyable causes warnings): */
735 RTCRestClientApiBase(RTCRestClientApiBase const &);
736 RTCRestClientApiBase *operator=(RTCRestClientApiBase const &);
737
738 /**
739 * Re-initializes the HTTP instance.
740 *
741 * @returns IPRT status code.
742 */
743 virtual int reinitHttpInstance() RT_NOEXCEPT;
744
745 /**
746 * Hook that's called when doCall has fully assembled the request.
747 *
748 * Can be used for request signing and similar final steps.
749 *
750 * @returns IPRT status code.
751 * @param a_hHttp The HTTP client instance.
752 * @param a_rStrFullUrl The full URL.
753 * @param a_enmHttpMethod The HTTP request method.
754 * @param a_rStrXmitBody The body text.
755 * @param a_fFlags kDoCall_XXX.
756 */
757 virtual int xmitReady(RTHTTP a_hHttp, RTCString const &a_rStrFullUrl, RTHTTPMETHOD a_enmHttpMethod,
758 RTCString const &a_rStrXmitBody, uint32_t a_fFlags) RT_NOEXCEPT;
759
760 /**
761 * Implements stuff for making an API call.
762 *
763 * @returns a_pResponse->getStatus()
764 * @param a_rRequest Reference to the request object.
765 * @param a_enmHttpMethod The HTTP request method.
766 * @param a_pResponse Pointer to the response object.
767 * @param a_pszMethod The method name, for logging purposes.
768 * @param a_fFlags kDoCall_XXX.
769 */
770 virtual int doCall(RTCRestClientRequestBase const &a_rRequest, RTHTTPMETHOD a_enmHttpMethod,
771 RTCRestClientResponseBase *a_pResponse, const char *a_pszMethod, uint32_t a_fFlags) RT_NOEXCEPT;
772
773 /**
774 * Implements OCI style request signing.
775 *
776 * @returns IPRT status code.
777 * @param a_hHttp The HTTP client instance.
778 * @param a_rStrFullUrl The full URL.
779 * @param a_enmHttpMethod The HTTP request method.
780 * @param a_rStrXmitBody The body text.
781 * @param a_fFlags kDoCall_XXX.
782 * @param a_hKey The key to use for signing.
783 * @param a_rStrKeyId The key ID.
784 *
785 * @remarks The signing scheme is covered by a series of drafts RFC, the latest being:
786 * https://tools.ietf.org/html/draft-cavage-http-signatures-10
787 */
788 int ociSignRequest(RTHTTP a_hHttp, RTCString const &a_rStrFullUrl, RTHTTPMETHOD a_enmHttpMethod,
789 RTCString const &a_rStrXmitBody, uint32_t a_fFlags, RTCRKEY a_hKey, RTCString const &a_rStrKeyId) RT_NOEXCEPT;
790
791 /**
792 * Worker for the server URL modifiers.
793 *
794 * @returns IPRT status code.
795 * @param a_pszServerUrl The current server URL (for comparing).
796 * @param a_offDst The offset of the component in the current server URL.
797 * @param a_cchDst The current component length.
798 * @param a_pszSrc The new URL component value.
799 * @param a_cchSrc The length of the new component.
800 */
801 int setServerUrlPart(const char *a_pszServerUrl, size_t a_offDst, size_t a_cchDst, const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT;
802};
803
804/** @} */
805
806#endif /* !IPRT_INCLUDED_cpp_restclient_h */
807
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette