diff options
Diffstat (limited to 'lib/jobs')
-rw-r--r-- | lib/jobs/basejob.cpp | 73 | ||||
-rw-r--r-- | lib/jobs/basejob.h | 4 |
2 files changed, 46 insertions, 31 deletions
diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 696861fb..2d41650a 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -336,39 +336,50 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const { - const auto httpCode = - reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - if (httpCode == 429) // Qt doesn't know about it yet - return { TooManyRequestsError, tr("Too many requests") }; - - // Should we check httpCode instead? Maybe even use it in BaseJob::Status? - // That would make codes in logs slightly more readable. - switch( reply->error() ) + // QNetworkReply error codes seem to be flawed when it comes to HTTP; + // see, e.g., https://github.com/QMatrixClient/libqmatrixclient/issues/200 + // so check genuine HTTP codes. The below processing is based on + // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + const auto httpCodeHeader = + reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + if (!httpCodeHeader.isValid()) // Woah, we didn't even get HTTP headers + return { NetworkError, reply->errorString() }; + + const auto httpCode = httpCodeHeader.toInt(); + if (httpCode / 100 == 2) // 2xx { - case QNetworkReply::NoError: - if (checkContentType(reply->rawHeader("Content-Type"), - d->expectedContentTypes)) - return NoError; - else // A warning in the logs might be more proper instead - return { IncorrectResponseError, - "Incorrect content type of the response" }; - - case QNetworkReply::AuthenticationRequiredError: - case QNetworkReply::ContentAccessDenied: - case QNetworkReply::ContentOperationNotPermittedError: - return { ContentAccessError, reply->errorString() }; - - case QNetworkReply::ProtocolInvalidOperationError: - case QNetworkReply::UnknownContentError: - return { IncorrectRequestError, reply->errorString() }; - - case QNetworkReply::ContentNotFoundError: - return { NotFoundError, reply->errorString() }; - - default: - return { NetworkError, reply->errorString() }; + if (checkContentType(reply->rawHeader("Content-Type"), + d->expectedContentTypes)) + return NoError; + else // A warning in the logs might be more proper instead + return { UnexpectedResponseTypeWarning, + "Unexpected content type of the response" }; } + + return { [httpCode]() -> StatusCode { + if (httpCode / 10 == 41) + return httpCode == 410 ? IncorrectRequestError : NotFoundError; + switch (httpCode) + { + case 401: case 403: case 407: + return ContentAccessError; + case 404: + return NotFoundError; + case 400: case 405: case 406: case 426: case 428: + case 505: + case 494: // Unofficial nginx "Request header too large" + case 497: // Unofficial nginx "HTTP request sent to HTTPS port" + return IncorrectRequestError; + case 429: + return TooManyRequestsError; + case 501: case 510: + return RequestNotImplementedError; + case 511: + return NetworkAuthRequiredError; + default: + return NetworkError; + } + }(), reply->errorString() }; } BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index f243066f..763ef75a 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -53,6 +53,8 @@ namespace QMatrixClient enum StatusCode { NoError = 0 // To be compatible with Qt conventions , Success = 0 , Pending = 1 + , WarningLevel = 20 + , UnexpectedResponseTypeWarning = 21 , Abandoned = 50 //< A very brief period between abandoning and object deletion , ErrorLevel = 100 //< Errors have codes starting from this , NetworkError = 100 @@ -63,6 +65,8 @@ namespace QMatrixClient , IncorrectRequestError , IncorrectResponseError , TooManyRequestsError + , RequestNotImplementedError + , NetworkAuthRequiredError , UserDefinedError = 200 }; |