From 37e66fa610bd60465076119e09ab9ef885175afb Mon Sep 17 00:00:00 2001 From: jianminzhao <76990468+jianminzhao@users.noreply.github.com> Date: Wed, 3 Dec 2025 11:57:04 -0800 Subject: [PATCH] CBL-7673: Better error message when Lite 4.0 talks to SGW 3.x * CBL-7496: Better error message when Lite 4.0 talks to SGW 3.x Starting in SGW 3.3.1, a request using "Sec-WebSocket-Protocol: BLIP_3+CBMobile_4" receives an HTTP 500 response with the message "I only speak BLIP_3+CBMobile_3,BLIP_3+CBMobile_2 protocols." This PR propagates that message into LiteCore's C4Error, improving the clarity of the logs. Ported from v4.1 --- Networking/HTTP/HTTPLogic.cc | 20 +++++++++++++------ .../tests/ReplicatorCollectionSGTest.cc | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Networking/HTTP/HTTPLogic.cc b/Networking/HTTP/HTTPLogic.cc index ff997ef88..a353589b6 100644 --- a/Networking/HTTP/HTTPLogic.cc +++ b/Networking/HTTP/HTTPLogic.cc @@ -19,6 +19,7 @@ #include "Error.hh" #include "SecureRandomize.hh" #include "SecureDigest.hh" +#include "StringUtil.hh" #include "slice_stream.hh" #include "NumConversion.hh" #include "fleece/Fleece.hh" @@ -351,12 +352,19 @@ namespace litecore::net { Disposition disposition = receivedResponse(response); if ( disposition == kFailure && _error.domain == WebSocketDomain && _error.code == int(_httpStatus) ) { // Look for a more detailed HTTP error message in the response body: - if ( _responseHeaders["Content-Type"_sl].hasPrefix("application/json"_sl) ) { - alloc_slice responseBody; - if ( socket.readHTTPBody(_responseHeaders, responseBody) ) { - Doc json = Doc::fromJSON(responseBody); - if ( slice reason = json["reason"].asString(); reason ) - _error = c4error_make(WebSocketDomain, int(_httpStatus), reason); + if ( bool isJSON = _responseHeaders["Content-Type"_sl].hasPrefix("application/json"_sl); + isJSON || _responseHeaders["Content-Type"_sl].hasPrefix("text/plain"_sl) ) { + if ( alloc_slice responseBody; socket.readHTTPBody(_responseHeaders, responseBody) ) { + slice reason; + Doc json; + if ( isJSON ) { + json = Doc::fromJSON(responseBody); + reason = json["reason"].asString(); + } else { // text/plain + // trimming the ending '\n's + reason = trimWhitespace(responseBody); + } + _error = c4error_make(WebSocketDomain, int(_httpStatus), (slice)reason); } } } diff --git a/Replicator/tests/ReplicatorCollectionSGTest.cc b/Replicator/tests/ReplicatorCollectionSGTest.cc index af56b4eff..099699d13 100644 --- a/Replicator/tests/ReplicatorCollectionSGTest.cc +++ b/Replicator/tests/ReplicatorCollectionSGTest.cc @@ -168,7 +168,7 @@ TEST_CASE_METHOD(ReplicatorCollectionSGTest, "Bad Configurations SG", "[.SyncSer for ( auto& coll : _collections ) { importJSONLines(sFixturesDir + "names_100.json", coll, 0, false, 2, idPrefix); } ReplParams replParams{_collectionSpecs}; - C4Error expectedError; + C4Error expectedError{}; slice expectedErrorMsg; SECTION("Mixed OneShot and Continuous Modes") {