Changeset 73930 in vbox
- Timestamp:
- Aug 28, 2018 6:09:54 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
include/iprt/cpp/restbase.h (modified) (3 diffs)
-
include/iprt/err.h (modified) (2 diffs)
-
include/iprt/json.h (modified) (1 diff)
-
src/VBox/Runtime/common/misc/json.cpp (modified) (1 diff)
-
src/VBox/Runtime/common/rest/RTCRestClientResponseBase.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/cpp/restbase.h
r73922 r73930 707 707 int getHttpStatus() { return m_rcHttp; } 708 708 709 /** 710 * Getter for m_pErrInfo. 711 */ 712 PCRTERRINFO getErrIfno(void) const { return m_pErrInfo; } 713 714 /** 715 * Getter for m_strContentType. 716 */ 717 RTCString const &getContentType(void) const { return m_strContentType; } 718 719 709 720 protected: 710 721 /** Negative numbers are IPRT errors, positive are HTTP status codes. */ 711 int m_rcStatus;722 int m_rcStatus; 712 723 /** The HTTP status code, VERR_NOT_AVAILABLE if not set. */ 713 int m_rcHttp;724 int m_rcHttp; 714 725 /** Error information. */ 715 PRTERRINFO m_pErrInfo;726 PRTERRINFO m_pErrInfo; 716 727 /** The value of the Content-Type header field. */ 717 RTCString m_strContentType;718 719 PRTERRINFO allocErrInfo(void);728 RTCString m_strContentType; 729 730 PRTERRINFO getErrInfo(void); 720 731 void deleteErrInfo(void); 721 732 void copyErrInfo(PCRTERRINFO pErrInfo); 733 734 /** 735 * Reports an error (or warning if a_rc non-negative). 736 * 737 * @returns a_rc 738 * @param a_rc The status code to report and return. The first 739 * error status is assigned to m_rcStatus, subsequent 740 * ones as well as informational statuses are not 741 * recorded by m_rcStatus. 742 * @param a_pszFormat The message format string. 743 * @param ... Message arguments. 744 */ 745 int addError(int a_rc, const char *a_pszFormat, ...); 722 746 723 747 /** … … 735 759 int extractHeaderFromBlob(const char *a_pszField, size_t a_cchField, const char *a_pchData, size_t a_cbData, 736 760 RTCString *a_pStrDst); 761 762 /** 763 * Helper that does the deserializing of the response body. 764 * 765 * @param a_pDst The destination object for the body content. 766 * @param a_pchData The body blob. 767 * @param a_cbData The size of the body blob. 768 */ 769 void deserializeBody(RTCRestObjectBase *a_pDst, const char *a_pchData, size_t a_cbData); 770 771 /** 772 * Primary json cursor for parsing bodies. 773 */ 774 class PrimaryJsonCursorForBody : public RTCRestJsonPrimaryCursor 775 { 776 public: 777 RTCRestClientResponseBase *m_pThat; /**< Pointer to response object. */ 778 PrimaryJsonCursorForBody(RTJSONVAL hValue, const char *pszName, RTCRestClientResponseBase *a_pThat); 779 virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...) RT_OVERRIDE; 780 virtual int unknownField(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE; 781 }; 737 782 }; 738 783 … … 821 866 virtual void doCall(RTCRestClientRequestBase const &a_rRequest, RTHTTPMETHOD a_enmHttpMethod, 822 867 RTCRestClientResponseBase *a_pResponse); 868 823 869 }; 824 870 -
trunk/include/iprt/err.h
r73929 r73930 3194 3194 /** Internal processing error \#5. */ 3195 3195 #define VERR_ISOFS_IPE_5 (-25395) 3196 3197 3196 /** @} */ 3198 3197 … … 3204 3203 /** The chosen baudrate is invalid or not supported by the given serial port. */ 3205 3204 #define VERR_SERIALPORT_INVALID_BAUDRATE (-25501) 3206 3205 /** @} */ 3206 3207 3208 /** @name RTCRest status codes 3209 * @{ */ 3210 /** Do not know how to handle the content type in the server response. */ 3211 #define VERR_REST_RESPONSE_CONTENT_TYPE_NOT_SUPPORTED (-25700) 3212 /** Invalid UTF-8 encoding in the response. */ 3213 #define VERR_REST_RESPONSE_INVALID_UTF8_ENCODING (-25701) 3214 /** Server response contains embedded zero character(s). */ 3215 #define VERR_REST_RESPONSE_EMBEDDED_ZERO_CHAR (-25702) 3207 3216 /** @} */ 3208 3217 -
trunk/include/iprt/json.h
r73874 r73930 88 88 * @param cbBuf Size of the buffer. 89 89 * @param pErrInfo Where to store extended error info. Optional. 90 * 91 * @todo r=bird: The use of uint8_t makes no sense here since the parser 92 * expects ASCII / UTF-8. What's more, if this is a real buffer the 93 * type should be 'const void *' rather than 'const uint8_t *'. 94 * This function should be modified to reflect that it's really for 95 * handling unterminated strings. 90 96 */ 91 97 RTDECL(int) RTJsonParseFromBuf(PRTJSONVAL phJsonVal, const uint8_t *pbBuf, size_t cbBuf, PRTERRINFO pErrInfo); -
trunk/src/VBox/Runtime/common/misc/json.cpp
r73874 r73930 1225 1225 AssertPtrReturn(pszStr, VERR_INVALID_POINTER); 1226 1226 1227 /** @todo r=bird: The rtJsonTokenizerParseFromString function does 1228 * strlen() on the whole pszStr for each read. For larger strings ( 1229 * longer than sizeof(Tokenizer.achBuf)) it would be good to join 1230 * forces with RTJsonParseFromBuf. */ 1227 1231 RTJSONTOKENIZER Tokenizer; 1228 1232 int rc = rtJsonTokenizerInit(&Tokenizer, rtJsonTokenizerParseFromString, (void *)pszStr); -
trunk/src/VBox/Runtime/common/rest/RTCRestClientResponseBase.cpp
r73923 r73930 125 125 126 126 127 PRTERRINFO RTCRestClientResponseBase::allocErrInfo(void) 128 { 127 PRTERRINFO RTCRestClientResponseBase::getErrInfo(void) 128 { 129 if (m_pErrInfo) 130 return m_pErrInfo; 129 131 size_t cbMsg = _4K; 130 132 m_pErrInfo = (PRTERRINFO)RTMemAllocZ(sizeof(*m_pErrInfo) + cbMsg); … … 155 157 m_pErrInfo->apvReserved[1] = NULL; 156 158 } 159 } 160 161 162 int RTCRestClientResponseBase::addError(int rc, const char *pszFormat, ...) 163 { 164 PRTERRINFO pErrInfo = getErrInfo(); 165 if (pErrInfo) 166 { 167 va_list va; 168 va_start(va, pszFormat); 169 if ( !RTErrInfoIsSet(pErrInfo) 170 || pErrInfo->cbMsg == 0 171 || pErrInfo->pszMsg[pErrInfo->cbMsg - 1] == '\n') 172 RTErrInfoAddV(pErrInfo, rc, pszFormat, va); 173 else 174 RTErrInfoAddF(pErrInfo, rc, "\n%N", pszFormat, &va); 175 va_end(va); 176 } 177 if (RT_SUCCESS(m_rcStatus) && RT_FAILURE_NP(rc)) 178 m_rcStatus = rc; 179 return rc; 157 180 } 158 181 … … 198 221 int rc = a_pStrDst->assignNoThrow(a_pchData, cchField); 199 222 if (RT_SUCCESS(rc)) 200 RTStrPurgeEncoding(a_pStrDst->mutableRaw()); 223 RTStrPurgeEncoding(a_pStrDst->mutableRaw()); /** @todo this is probably a little wrong... */ 201 224 return rc; 202 225 } … … 210 233 } 211 234 235 236 237 RTCRestClientResponseBase::PrimaryJsonCursorForBody::PrimaryJsonCursorForBody(RTJSONVAL hValue, const char *pszName, 238 RTCRestClientResponseBase *a_pThat) 239 : RTCRestJsonPrimaryCursor(hValue, pszName, a_pThat->getErrInfo()) 240 , m_pThat(a_pThat) 241 { 242 } 243 244 245 int RTCRestClientResponseBase::PrimaryJsonCursorForBody::addError(RTCRestJsonCursor const &a_rCursor, int a_rc, 246 const char *a_pszFormat, ...) 247 { 248 va_list va; 249 va_start(va, a_pszFormat); 250 char szPath[256]; 251 m_pThat->addError(a_rc, "response body/%s: %N", getPath(a_rCursor, szPath, sizeof(szPath)), a_pszFormat, &va); 252 va_end(va); 253 return a_rc; 254 } 255 256 257 int RTCRestClientResponseBase::PrimaryJsonCursorForBody::unknownField(RTCRestJsonCursor const &a_rCursor) 258 { 259 char szPath[256]; 260 m_pThat->addError(VWRN_NOT_FOUND, "response body/%s: unknown field (type %s)", 261 getPath(a_rCursor, szPath, sizeof(szPath)), RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue))); 262 return VWRN_NOT_FOUND; 263 } 264 265 266 void RTCRestClientResponseBase::deserializeBody(RTCRestObjectBase *a_pDst, const char *a_pchData, size_t a_cbData) 267 { 268 if (m_strContentType.startsWith("application/json;")) 269 { 270 int rc = RTStrValidateEncodingEx(a_pchData, a_cbData, RTSTR_VALIDATE_ENCODING_EXACT_LENGTH); 271 if (RT_SUCCESS(rc)) 272 { 273 RTERRINFOSTATIC ErrInfo; 274 RTJSONVAL hValue; 275 rc = RTJsonParseFromBuf(&hValue, (const uint8_t *)a_pchData, a_cbData, RTErrInfoInitStatic(&ErrInfo)); 276 if (RT_SUCCESS(rc)) 277 { 278 PrimaryJsonCursorForBody PrimaryCursor(hValue, a_pDst->getType(), this); /* note: consumes hValue */ 279 a_pDst->deserializeFromJson(PrimaryCursor.m_Cursor); 280 } 281 else if (RTErrInfoIsSet(&ErrInfo.Core)) 282 addError(rc, "Error %Rrc parsing server response as JSON (type %s): %s", 283 rc, a_pDst->getType(), ErrInfo.Core.pszMsg); 284 else 285 addError(rc, "Error %Rrc parsing server response as JSON (type %s)", rc, a_pDst->getType()); 286 } 287 else if (rc == VERR_INVALID_UTF8_ENCODING) 288 addError(VERR_REST_RESPONSE_INVALID_UTF8_ENCODING, "Invalid UTF-8 body encoding (object type %s; Content-Type: %s)", 289 a_pDst->getType(), m_strContentType.c_str()); 290 else if (rc == VERR_BUFFER_UNDERFLOW) 291 addError(VERR_REST_RESPONSE_EMBEDDED_ZERO_CHAR, "Embedded zero character in response (object type %s; Content-Type: %s)", 292 a_pDst->getType(), m_strContentType.c_str()); 293 else 294 addError(rc, "Unexpected body validation error (object type %s; Content-Type: %s): %Rrc", 295 a_pDst->getType(), m_strContentType.c_str(), rc); 296 } 297 else 298 addError(VERR_REST_RESPONSE_CONTENT_TYPE_NOT_SUPPORTED, "Unsupported content type for '%s': %s", 299 a_pDst->getType(), m_strContentType.c_str()); 300 } 301
Note:
See TracChangeset
for help on using the changeset viewer.

