summaryrefslogtreecommitdiffstats
path: root/include/iprt/cpp/restclient.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/iprt/cpp/restclient.h793
1 files changed, 793 insertions, 0 deletions
diff --git a/include/iprt/cpp/restclient.h b/include/iprt/cpp/restclient.h
new file mode 100644
index 00000000..37e394ac
--- /dev/null
+++ b/include/iprt/cpp/restclient.h
@@ -0,0 +1,793 @@
+/** @file
+ * IPRT - C++ Representational State Transfer (REST) Client Classes.
+ */
+
+/*
+ * Copyright (C) 2008-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef IPRT_INCLUDED_cpp_restclient_h
+#define IPRT_INCLUDED_cpp_restclient_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/http.h>
+#include <iprt/cpp/restbase.h>
+#include <iprt/cpp/reststringmap.h>
+
+
+/** @defgroup grp_rt_cpp_restclient C++ Representational State Transfer (REST) Client Classes.
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * Specialization of RTCRestBinary for use with body parameters in a client.
+ *
+ * This enables registering data callbacks for provinding data to upload.
+ */
+class RT_DECL_CLASS RTCRestBinaryParameter : public RTCRestBinary
+{
+public:
+ /** Default constructor. */
+ RTCRestBinaryParameter() RT_NOEXCEPT;
+
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestBinaryParameter const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method.
+ * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
+ virtual int assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT RT_OVERRIDE;
+ /** Safe copy assignment method.
+ * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
+ virtual int assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Use the specified data buffer directly.
+ * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
+ virtual int assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+ /**
+ * Use the specified data buffer directly.
+ * @note This will assert and work like assignReadOnly. */
+ virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Make a clone of this object. */
+ inline RTCRestBinaryParameter *clone() const RT_NOEXCEPT { return (RTCRestBinaryParameter *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+
+ /**
+ * Retrieves the callback data.
+ */
+ inline void *getCallbackData() const RT_NOEXCEPT { return m_pvCallbackData; }
+
+ /**
+ * Sets the content-type for an upload.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
+ * @param a_pszContentType The content type to set.
+ * If NULL, no content type is set.
+ */
+ int setContentType(const char *a_pszContentType) RT_NOEXCEPT;
+
+ /**
+ * Gets the content type that was set.
+ */
+ inline RTCString const &getContentType() const RT_NOEXCEPT { return m_strContentType; }
+
+ /**
+ * Gets the content-length value (UINT64_MAX if not available).
+ */
+ inline uint64_t getContentLength() const RT_NOEXCEPT { return m_cbContentLength; }
+
+ /**
+ * Callback for producing bytes to upload.
+ *
+ * @returns IPRT status code.
+ * @param a_pThis The related string object.
+ * @param a_pvDst Where to put the bytes.
+ * @param a_cbDst Max number of bytes to produce.
+ * @param a_offContent The byte offset corresponding to the start of @a a_pvDst.
+ * @param a_pcbActual Where to return the number of bytes actually produced.
+ *
+ * @remarks Use getCallbackData to get the user data.
+ *
+ * @note The @a a_offContent parameter does not imply random access or anthing
+ * like that, it is just a convenience provided by the caller. The value
+ * is the sum of the previously returned @a *pcbActual values.
+ */
+ typedef DECLCALLBACK(int) FNPRODUCER(RTCRestBinaryParameter *a_pThis, void *a_pvDst, size_t a_cbDst,
+ uint64_t a_offContent, size_t *a_pcbActual) /*RT_NOEXCEPT*/;
+ /** Pointer to a byte producer callback. */
+ typedef FNPRODUCER *PFNPRODUCER;
+
+ /**
+ * Sets the producer callback.
+ *
+ * @param a_pfnProducer The callback function for producing data.
+ * @param a_pvCallbackData Data the can be retrieved from the callback
+ * using getCallbackData().
+ * @param a_cbContentLength The amount of data that will be uploaded and
+ * to be set as the value of the content-length
+ * header field. Pass UINT64_MAX if not known.
+ *
+ * @note This will drop any buffer previously registered using setUploadData().
+ */
+ void setProducerCallback(PFNPRODUCER a_pfnProducer, void *a_pvCallbackData = NULL, uint64_t a_cbContentLength = UINT64_MAX) RT_NOEXCEPT;
+
+ /**
+ * Preprares transmission via the @a a_hHttp client instance.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @internal
+ */
+ virtual int xmitPrepare(RTHTTP a_hHttp) const RT_NOEXCEPT;
+
+ /**
+ * For completing and/or undoing setup from xmitPrepare.
+ *
+ * @param a_hHttp The HTTP client instance.
+ * @internal
+ */
+ virtual void xmitComplete(RTHTTP a_hHttp) const RT_NOEXCEPT;
+
+protected:
+ /** Number of bytes corresponding to content-length.
+ * UINT64_MAX if not known. Used both for unploads and downloads. */
+ uint64_t m_cbContentLength;
+ /** The content type if set (upload only). */
+ RTCString m_strContentType;
+ /** Pointer to user-registered producer callback function (upload only). */
+ PFNPRODUCER m_pfnProducer;
+ /** User argument for both callbacks (both). */
+ void *m_pvCallbackData;
+
+ /** @copydoc FNRTHTTPUPLOADCALLBACK */
+ static DECLCALLBACK(int) xmitHttpCallback(RTHTTP hHttp, void *pvBuf, size_t cbBuf, uint64_t offContent,
+ size_t *pcbActual, void *pvUser) RT_NOEXCEPT;
+
+private:
+ /* No copy constructor or copy assignment: */
+ RTCRestBinaryParameter(RTCRestBinaryParameter const &a_rThat);
+ RTCRestBinaryParameter &operator=(RTCRestBinaryParameter const &a_rThat);
+};
+
+
+/**
+ * Specialization of RTCRestBinary for use with responses in a client.
+ *
+ * This enables registering data callbacks for consuming downloaded data.
+ */
+class RT_DECL_CLASS RTCRestBinaryResponse : public RTCRestBinary
+{
+public:
+ /** Default constructor. */
+ RTCRestBinaryResponse() RT_NOEXCEPT;
+
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestBinaryResponse const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT RT_OVERRIDE;
+ /** Safe copy assignment method.
+ * @note This will assert and fail as it makes no sense for a download. */
+ virtual int assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Use the specified data buffer directly.
+ * @note This will assert and fail as it makes no sense for a download.
+ */
+ virtual int assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+ /**
+ * Use the specified data buffer directly.
+ * @note This will drop any previously registered producer callback and user data.
+ */
+ virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Make a clone of this object. */
+ inline RTCRestBinaryResponse *clone() const RT_NOEXCEPT { return (RTCRestBinaryResponse *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+
+ /**
+ * Retrieves the callback data.
+ */
+ inline void *getCallbackData() const RT_NOEXCEPT { return m_pvCallbackData; }
+
+ /**
+ * Sets the max size to download to memory.
+ *
+ * This also indicates the intention to download to a memory buffer, so it
+ * will drop any previously registered consumer callback and its user data.
+ *
+ * @param a_cbMaxDownload Maximum number of bytes to download to memory.
+ * If 0, a default is selected (currently 32MiB for
+ * 32-bit hosts and 128MiB for 64-bit).
+ */
+ void setMaxDownloadSize(size_t a_cbMaxDownload) RT_NOEXCEPT;
+
+ /**
+ * Gets the content-length value (UINT64_MAX if not available).
+ */
+ inline uint64_t getContentLength() const RT_NOEXCEPT { return m_cbContentLength; }
+
+ /**
+ * Callback for consuming downloaded bytes.
+ *
+ * @returns IPRT status code.
+ * @param a_pThis The related string object.
+ * @param a_pvSrc Buffer containing the bytes.
+ * @param a_cbSrc The number of bytes in the buffer.
+ * @param a_uHttpStatus The HTTP status code.
+ * @param a_offContent The byte offset corresponding to the start of @a a_pvSrc.
+ * @param a_cbContent The content length field value, UINT64_MAX if not available.
+ *
+ * @remarks Use getCallbackData to get the user data.
+ *
+ * @note The @a a_offContent parameter does not imply random access or anthing
+ * like that, it is just a convenience provided by the caller. The value
+ * is the sum of the previous @a a_cbSrc values.
+ */
+ typedef DECLCALLBACK(int) FNCONSUMER(RTCRestBinaryResponse *a_pThis, const void *a_pvSrc, size_t a_cbSrc,
+ uint32_t a_uHttpStatus, uint64_t a_offContent, uint64_t a_cbContent) /*RT_NOEXCEPT*/;
+ /** Pointer to a byte consumer callback. */
+ typedef FNCONSUMER *PFNCONSUMER;
+
+ /**
+ * Sets the consumer callback.
+ *
+ * @param a_pfnConsumer The callback function for consuming downloaded data.
+ * NULL if data should be stored in m_pbData (the default).
+ * @param a_pvCallbackData Data the can be retrieved from the callback
+ * using getCallbackData().
+ */
+ void setConsumerCallback(PFNCONSUMER a_pfnConsumer, void *a_pvCallbackData = NULL) RT_NOEXCEPT;
+
+ /**
+ * Preprares for receiving via the @a a_hHttp client instance.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @param a_fCallbackFlags The HTTP callback flags (status code spec).
+ * @internal
+ */
+ virtual int receivePrepare(RTHTTP a_hHttp, uint32_t a_fCallbackFlags) RT_NOEXCEPT;
+
+ /**
+ * For completing and/or undoing setup from receivePrepare.
+ *
+ * @param a_hHttp The HTTP client instance.
+ * @internal
+ */
+ virtual void receiveComplete(RTHTTP a_hHttp) RT_NOEXCEPT;
+
+protected:
+ /** Number of bytes corresponding to content-length.
+ * UINT64_MAX if not known. Used both for unploads and downloads. */
+ uint64_t m_cbContentLength;
+ /** Number of bytes downloaded thus far. */
+ uint64_t m_cbDownloaded;
+ /** Pointer to user-registered consumer callback function (download only). */
+ PFNCONSUMER m_pfnConsumer;
+ /** User argument for both callbacks (both). */
+ void *m_pvCallbackData;
+ /** Maximum data to download to memory (download only). */
+ size_t m_cbMaxDownload;
+
+ /** @copydoc FNRTHTTPDOWNLOADCALLBACK */
+ static DECLCALLBACK(int) receiveHttpCallback(RTHTTP hHttp, void const *pvBuf, size_t cbBuf, uint32_t uHttpStatus,
+ uint64_t offContent, uint64_t cbContent, void *pvUser) RT_NOEXCEPT;
+
+private:
+ /* No copy constructor or copy assignment: */
+ RTCRestBinaryResponse(RTCRestBinaryResponse const &a_rThat);
+ RTCRestBinaryResponse &operator=(RTCRestBinaryResponse const &a_rThat);
+};
+
+
+/**
+ * Base class for REST client requests.
+ *
+ * This encapsulates parameters and helps transform them into a HTTP request.
+ *
+ * Parameters can be transfered in a number of places:
+ * - Path part of the URL.
+ * - Query part of the URL.
+ * - HTTP header fields.
+ * - FORM body.
+ * - JSON body.
+ * - XML body.
+ * - ...
+ *
+ * They can be require or optional. The latter may have default values. In
+ * swagger 3 they can also be nullable, which means the null-indicator cannot
+ * be used for tracking optional parameters.
+ */
+class RT_DECL_CLASS RTCRestClientRequestBase
+{
+public:
+ RTCRestClientRequestBase() RT_NOEXCEPT;
+ virtual ~RTCRestClientRequestBase();
+ RTCRestClientRequestBase(RTCRestClientRequestBase const &a_rThat) RT_NOEXCEPT;
+ RTCRestClientRequestBase &operator=(RTCRestClientRequestBase const &a_rThat) RT_NOEXCEPT;
+
+ /**
+ * Reset all members to default values.
+ * @returns IPRT status code.
+ */
+ virtual int resetToDefault() RT_NOEXCEPT = 0;
+
+ /**
+ * Prepares the HTTP handle for transmitting this request.
+ *
+ * @returns IPRT status code.
+ * @param a_pStrPath Where to set path parameters. Will be appended to the base path.
+ * @param a_pStrQuery Where to set query parameters.
+ * @param a_hHttp Where to set header parameters and such.
+ * @param a_pStrBody Where to set body parameters.
+ */
+ virtual int xmitPrepare(RTCString *a_pStrPath, RTCString *a_pStrQuery, RTHTTP a_hHttp, RTCString *a_pStrBody) const RT_NOEXCEPT = 0;
+
+ /**
+ * Always called after the request has been transmitted.
+ *
+ * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
+ * @param a_hHttp The HTTP handle the request was performed on.
+ */
+ virtual void xmitComplete(int a_rcStatus, RTHTTP a_hHttp) const RT_NOEXCEPT = 0;
+
+ /**
+ * Checks if there are were any assignment errors.
+ */
+ inline bool hasAssignmentErrors() const RT_NOEXCEPT { return m_fErrorSet != 0; }
+
+protected:
+ /** Set of fields that have been explicitly assigned a value. */
+ uint64_t m_fIsSet;
+ /** Set of fields where value assigning failed. */
+ uint64_t m_fErrorSet;
+
+ /** Path parameter descriptor. */
+ typedef struct
+ {
+ const char *pszName; /**< The name string to replace (including {}). */
+ size_t cchName; /**< Length of pszName. */
+ uint32_t fFlags; /**< The toString flags. */
+ uint8_t iBitNo; /**< The parameter bit number. */
+ } PATHPARAMDESC;
+
+ /** Path parameter state. */
+ typedef struct
+ {
+ RTCRestObjectBase const *pObj; /**< Pointer to the parameter object. */
+ size_t offName; /**< Maintained by worker. */
+ } PATHPARAMSTATE;
+
+ /**
+ * Do path parameters.
+ *
+ * @returns IPRT status code
+ * @param a_pStrPath The destination path.
+ * @param a_pszPathTemplate The path template string.
+ * @param a_cchPathTemplate The length of the path template string.
+ * @param a_paPathParams The path parameter descriptors (static).
+ * @param a_paPathParamStates The path parameter objects and states.
+ * @param a_cPathParams Number of path parameters.
+ */
+ int doPathParameters(RTCString *a_pStrPath, const char *a_pszPathTemplate, size_t a_cchPathTemplate,
+ PATHPARAMDESC const *a_paPathParams, PATHPARAMSTATE *a_paPathParamStates, size_t a_cPathParams) const RT_NOEXCEPT;
+
+ /** Query parameter descriptor. */
+ typedef struct
+ {
+ const char *pszName; /**< The parameter name. */
+ uint32_t fFlags; /**< The toString flags. */
+ bool fRequired; /**< Required or not. */
+ uint8_t iBitNo; /**< The parameter bit number. */
+ } QUERYPARAMDESC;
+
+ /**
+ * Do query parameters.
+ *
+ * @returns IPRT status code
+ * @param a_pStrQuery The destination string.
+ * @param a_paQueryParams The query parameter descriptors.
+ * @param a_papQueryParamObjs The query parameter objects, parallel to @a a_paQueryParams.
+ * @param a_cQueryParams Number of query parameters.
+ */
+ int doQueryParameters(RTCString *a_pStrQuery, QUERYPARAMDESC const *a_paQueryParams,
+ RTCRestObjectBase const **a_papQueryParamObjs, size_t a_cQueryParams) const RT_NOEXCEPT;
+
+ /** Header parameter descriptor. */
+ typedef struct
+ {
+ const char *pszName; /**< The parameter name. */
+ uint32_t fFlags; /**< The toString flags. */
+ bool fRequired; /**< Required or not. */
+ uint8_t iBitNo; /**< The parameter bit number. */
+ bool fMapCollection; /**< Collect headers starting with pszName into a map. */
+ } HEADERPARAMDESC;
+
+ /**
+ * Do header parameters.
+ *
+ * @returns IPRT status code
+ * @param a_hHttp Where to set header parameters.
+ * @param a_paHeaderParams The header parameter descriptors.
+ * @param a_papHeaderParamObjs The header parameter objects, parallel to @a a_paHeaderParams.
+ * @param a_cHeaderParams Number of header parameters.
+ */
+ int doHeaderParameters(RTHTTP a_hHttp, HEADERPARAMDESC const *a_paHeaderParams,
+ RTCRestObjectBase const **a_papHeaderParamObjs, size_t a_cHeaderParams) const RT_NOEXCEPT;
+};
+
+
+/**
+ * Base class for REST client responses.
+ */
+class RT_DECL_CLASS RTCRestClientResponseBase
+{
+public:
+ /** Default constructor. */
+ RTCRestClientResponseBase() RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestClientResponseBase();
+ /** Copy constructor. */
+ RTCRestClientResponseBase(RTCRestClientResponseBase const &a_rThat);
+ /** Copy assignment operator. */
+ RTCRestClientResponseBase &operator=(RTCRestClientResponseBase const &a_rThat);
+
+ /**
+ * Resets the object state.
+ */
+ virtual void reset(void) RT_NOEXCEPT;
+
+ /**
+ * Prepares the HTTP handle for receiving the response.
+ *
+ * This may install callbacks and such like.
+ *
+ * When overridden, the parent class must always be called.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP handle to prepare for receiving.
+ */
+ virtual int receivePrepare(RTHTTP a_hHttp) RT_NOEXCEPT;
+
+ /**
+ * Called when the HTTP request has been completely received.
+ *
+ * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
+ * @param a_hHttp The HTTP handle the request was performed on.
+ * This can be NIL_RTHTTP should something fail early, in
+ * which case it is possible receivePrepare() wasn't called.
+ *
+ * @note Called before consumeBody() but after consumeHeader().
+ */
+ virtual void receiveComplete(int a_rcStatus, RTHTTP a_hHttp) RT_NOEXCEPT;
+
+ /**
+ * Callback that consumes HTTP body data from the server.
+ *
+ * @param a_pchData Body data.
+ * @param a_cbData Amount of body data.
+ *
+ * @note Called after consumeHeader().
+ */
+ virtual void consumeBody(const char *a_pchData, size_t a_cbData) RT_NOEXCEPT;
+
+ /**
+ * Called after status, headers and body all have been presented.
+ *
+ * @returns IPRT status code.
+ */
+ virtual void receiveFinal() RT_NOEXCEPT;
+
+ /**
+ * Getter for m_rcStatus.
+ * @returns Negative numbers are IPRT errors, positive are HTTP status codes.
+ */
+ inline int getStatus() const RT_NOEXCEPT { return m_rcStatus; }
+
+ /**
+ * Getter for m_rcHttp.
+ * @returns HTTP status code or VERR_NOT_AVAILABLE.
+ */
+ inline int getHttpStatus() const RT_NOEXCEPT { return m_rcHttp; }
+
+ /**
+ * Getter for m_pErrInfo.
+ */
+ inline PCRTERRINFO getErrInfo(void) const RT_NOEXCEPT { return m_pErrInfo; }
+
+ /**
+ * Getter for m_strContentType.
+ */
+ inline RTCString const &getContentType(void) const RT_NOEXCEPT { return m_strContentType; }
+
+
+protected:
+ /** Negative numbers are IPRT errors, positive are HTTP status codes. */
+ int m_rcStatus;
+ /** The HTTP status code, VERR_NOT_AVAILABLE if not set. */
+ int m_rcHttp;
+ /** Error information. */
+ PRTERRINFO m_pErrInfo;
+ /** The value of the Content-Type header field. */
+ RTCString m_strContentType;
+
+ PRTERRINFO getErrInfoInternal(void) RT_NOEXCEPT;
+ void deleteErrInfo(void) RT_NOEXCEPT;
+ void copyErrInfo(PCRTERRINFO pErrInfo) RT_NOEXCEPT;
+
+ /**
+ * Reports an error (or warning if a_rc non-negative).
+ *
+ * @returns a_rc
+ * @param a_rc The status code to report and return. The first
+ * error status is assigned to m_rcStatus, subsequent
+ * ones as well as informational statuses are not
+ * recorded by m_rcStatus.
+ * @param a_pszFormat The message format string.
+ * @param ... Message arguments.
+ */
+ int addError(int a_rc, const char *a_pszFormat, ...) RT_NOEXCEPT;
+
+ /**
+ * Deserializes a header field value.
+ *
+ * @returns IPRT status code.
+ * @param a_pObj The object to deserialize into.
+ * @param a_pchValue Pointer to the value (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param a_cchValue The value length.
+ * @param a_fFlags Flags to pass to fromString().
+ * @param a_pszErrorTag The error tag (field name).
+ */
+ int deserializeHeader(RTCRestObjectBase *a_pObj, const char *a_pchValue, size_t a_cchValue,
+ uint32_t a_fFlags, const char *a_pszErrorTag) RT_NOEXCEPT;
+
+ /**
+ * Deserializes a header field value.
+ *
+ * @returns IPRT status code.
+ * @param a_pMap The string map object to deserialize into.
+ * @param a_pchField Pointer to the map field name. (Caller dropped the prefix.)
+ * Not necessarily valid UTF-8!
+ * @param a_cchField Length of field name.
+ * @param a_pchValue Pointer to the value (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param a_cchValue The value length.
+ * @param a_fFlags Flags to pass to fromString().
+ * @param a_pszErrorTag The error tag (field name).
+ */
+ int deserializeHeaderIntoMap(RTCRestStringMapBase *a_pMap, const char *a_pchField, size_t a_cchField,
+ const char *a_pchValue, size_t a_cchValue, uint32_t a_fFlags, const char *a_pszErrorTag) RT_NOEXCEPT;
+
+ /**
+ * Helper that does the deserializing of the response body
+ * via deserializeBodyFromJsonCursor().
+ *
+ * @param a_pchData The body blob.
+ * @param a_cbData The size of the body blob.
+ * @param a_pszBodyName The name of the body parameter.
+ */
+ void deserializeBody(const char *a_pchData, size_t a_cbData, const char *a_pszBodyName) RT_NOEXCEPT;
+
+ /**
+ * Called by deserializeBody to do the actual body deserialization.
+ *
+ * @param a_rCursor The JSON cursor.
+ */
+ virtual void deserializeBodyFromJsonCursor(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT;
+
+ /**
+ * Primary json cursor for parsing bodies.
+ */
+ class PrimaryJsonCursorForBody : public RTCRestJsonPrimaryCursor
+ {
+ public:
+ RTCRestClientResponseBase *m_pThat; /**< Pointer to response object. */
+ PrimaryJsonCursorForBody(RTJSONVAL hValue, const char *pszName, RTCRestClientResponseBase *a_pThat) RT_NOEXCEPT;
+ virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int unknownField(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ };
+
+
+ /**
+ * Consumes a header.
+ *
+ * Child classes can override this to pick up their header fields, but must
+ * always call the parent class.
+ *
+ * @returns IPRT status code.
+ * @param a_uMatchWord Match word constructed by RTHTTP_MAKE_HDR_MATCH_WORD
+ * @param a_pchField The field name (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param a_cchField The length of the field.
+ * @param a_pchValue The field value (not zero terminated).
+ * @param a_cchValue The length of the value.
+ */
+ virtual int consumeHeader(uint32_t a_uMatchWord, const char *a_pchField, size_t a_cchField,
+ const char *a_pchValue, size_t a_cchValue) RT_NOEXCEPT;
+
+private:
+ /** Callback for use with RTHttpSetHeaderCallback. */
+ static DECLCALLBACK(int) receiveHttpHeaderCallback(RTHTTP hHttp, uint32_t uMatchWord, const char *pchField, size_t cchField,
+ const char *pchValue, size_t cchValue, void *pvUser) RT_NOEXCEPT;
+};
+
+
+/**
+ * Base class for REST client responses.
+ */
+class RT_DECL_CLASS RTCRestClientApiBase
+{
+public:
+ RTCRestClientApiBase() RT_NOEXCEPT;
+ virtual ~RTCRestClientApiBase();
+
+ /** @name Host and Base path (URL) handling.
+ * @{ */
+ /**
+ * Gets the server URL.
+ */
+ const char *getServerUrl(void) const RT_NOEXCEPT;
+
+ /**
+ * Sets the whole server URL.
+ * @returns IPRT status code.
+ * @param a_pszUrl The new server URL. NULL/empty to reset to default.
+ */
+ int setServerUrl(const char *a_pszUrl) RT_NOEXCEPT;
+
+ /**
+ * Sets the scheme part of the the server URL.
+ * @returns IPRT status code.
+ * @param a_pszScheme The new scheme. Does not accept NULL or empty string.
+ */
+ int setServerScheme(const char *a_pszScheme) RT_NOEXCEPT;
+
+ /**
+ * Sets the authority (hostname + port) part of the the server URL.
+ * @returns IPRT status code.
+ * @param a_pszAuthority The new authority. Does not accept NULL or empty string.
+ */
+ int setServerAuthority(const char *a_pszAuthority) RT_NOEXCEPT;
+
+ /**
+ * Sets the base path part of the the server URL.
+ * @returns IPRT status code.
+ * @param a_pszBasePath The new base path. Does not accept NULL or empty string.
+ */
+ int setServerBasePath(const char *a_pszBasePath) RT_NOEXCEPT;
+
+ /**
+ * Gets the default server URL as specified in the specs.
+ * @returns Server URL.
+ */
+ virtual const char *getDefaultServerUrl() const RT_NOEXCEPT = 0;
+
+ /**
+ * Gets the default server base path as specified in the specs.
+ * @returns Host string (start of URL).
+ */
+ virtual const char *getDefaultServerBasePath() const RT_NOEXCEPT = 0;
+ /** @} */
+
+ /** Flags to doCall. */
+ enum
+ {
+ kDoCall_OciReqSignExcludeBody = 1, /**< Exclude the body when doing OCI request signing. */
+ kDoCall_RequireBody = 2 /**< The body is required. */
+ };
+
+protected:
+ /** Handle to the HTTP connection object. */
+ RTHTTP m_hHttp;
+ /** The server URL to use. If empty use the default. */
+ RTCString m_strServerUrl;
+
+ /* Make non-copyable (RTCNonCopyable causes warnings): */
+ RTCRestClientApiBase(RTCRestClientApiBase const &);
+ RTCRestClientApiBase *operator=(RTCRestClientApiBase const &);
+
+ /**
+ * Re-initializes the HTTP instance.
+ *
+ * @returns IPRT status code.
+ */
+ virtual int reinitHttpInstance() RT_NOEXCEPT;
+
+ /**
+ * Hook that's called when doCall has fully assembled the request.
+ *
+ * Can be used for request signing and similar final steps.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @param a_rStrFullUrl The full URL.
+ * @param a_enmHttpMethod The HTTP request method.
+ * @param a_rStrXmitBody The body text.
+ * @param a_fFlags kDoCall_XXX.
+ */
+ virtual int xmitReady(RTHTTP a_hHttp, RTCString const &a_rStrFullUrl, RTHTTPMETHOD a_enmHttpMethod,
+ RTCString const &a_rStrXmitBody, uint32_t a_fFlags) RT_NOEXCEPT;
+
+ /**
+ * Implements stuff for making an API call.
+ *
+ * @returns a_pResponse->getStatus()
+ * @param a_rRequest Reference to the request object.
+ * @param a_enmHttpMethod The HTTP request method.
+ * @param a_pResponse Pointer to the response object.
+ * @param a_pszMethod The method name, for logging purposes.
+ * @param a_fFlags kDoCall_XXX.
+ */
+ virtual int doCall(RTCRestClientRequestBase const &a_rRequest, RTHTTPMETHOD a_enmHttpMethod,
+ RTCRestClientResponseBase *a_pResponse, const char *a_pszMethod, uint32_t a_fFlags) RT_NOEXCEPT;
+
+ /**
+ * Implements OCI style request signing.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @param a_rStrFullUrl The full URL.
+ * @param a_enmHttpMethod The HTTP request method.
+ * @param a_rStrXmitBody The body text.
+ * @param a_fFlags kDoCall_XXX.
+ * @param a_hKey The key to use for signing.
+ * @param a_rStrKeyId The key ID.
+ *
+ * @remarks The signing scheme is covered by a series of drafts RFC, the latest being:
+ * https://tools.ietf.org/html/draft-cavage-http-signatures-10
+ */
+ int ociSignRequest(RTHTTP a_hHttp, RTCString const &a_rStrFullUrl, RTHTTPMETHOD a_enmHttpMethod,
+ RTCString const &a_rStrXmitBody, uint32_t a_fFlags, RTCRKEY a_hKey, RTCString const &a_rStrKeyId) RT_NOEXCEPT;
+
+ /**
+ * Worker for the server URL modifiers.
+ *
+ * @returns IPRT status code.
+ * @param a_pszServerUrl The current server URL (for comparing).
+ * @param a_offDst The offset of the component in the current server URL.
+ * @param a_cchDst The current component length.
+ * @param a_pszSrc The new URL component value.
+ * @param a_cchSrc The length of the new component.
+ */
+ int setServerUrlPart(const char *a_pszServerUrl, size_t a_offDst, size_t a_cchDst, const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT;
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_restclient_h */
+