9 #include <QtCore/QObject>
10 #include <QtCore/QStringBuilder>
11 #include <QtCore/QLoggingCategory>
12 #include <QtCore/QFuture>
14 #include <Quotient/converters.h>
15 #include <Quotient/quotient_common.h>
17 class QNetworkRequest;
24 enum class HttpVerb { Get, Put, Post, Delete };
28 Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT)
29 Q_PROPERTY(
int maxRetries READ maxRetries WRITE setMaxRetries)
30 Q_PROPERTY(
int statusCode READ error NOTIFY statusChanged)
32 static QByteArray encodeIfParam(
const QString& paramPart);
34 static auto encodeIfParam(
const char (&constPart)[N])
53 UnexpectedResponseType = 21,
54 UnexpectedResponseTypeWarning = UnexpectedResponseType,
66 RateLimited = TooManyRequests,
67 RequestNotImplemented,
68 UnsupportedRoomVersion,
74 UserDefinedError = 256
78 template <
typename... StrTs>
79 static QByteArray makePath(StrTs&&... parts)
81 return (QByteArray() % ... % encodeIfParam(parts));
94 Status(StatusCode c) : code(c) {}
95 Status(
int c, QString m) : code(c), message(std::move(m)) {}
97 static StatusCode fromHttpCode(
int httpCode);
98 static Status fromHttpCode(
int httpCode, QString msg)
100 return { fromHttpCode(httpCode), std::move(msg) };
103 bool good()
const {
return code < ErrorLevel; }
104 QDebug dumpToLog(QDebug dbg)
const;
105 friend QDebug operator<<(
const QDebug& dbg,
const Status& s)
107 return s.dumpToLog(dbg);
110 bool operator==(
const Status& other)
const
112 return code == other.code && message == other.message;
114 bool operator!=(
const Status& other)
const
116 return !operator==(other);
118 bool operator==(
int otherCode)
const
120 return code == otherCode;
122 bool operator!=(
int otherCode)
const
124 return !operator==(otherCode);
132 BaseJob(HttpVerb verb,
const QString& name, QByteArray endpoint,
133 bool needsToken =
true);
134 BaseJob(HttpVerb verb,
const QString& name, QByteArray endpoint,
135 const QUrlQuery& query, RequestData&& data = {},
136 bool needsToken =
true);
138 QUrl requestUrl()
const;
139 bool isBackground()
const;
142 Status status()
const;
145 QString statusCaption()
const;
153 QByteArray rawData(
int bytesAtMost)
const;
156 const QByteArray& rawData()
const;
168 QString rawDataSample(
int bytesAtMost = 65535)
const;
176 QJsonObject jsonData()
const;
184 QJsonArray jsonItems()
const;
191 template <
typename T,
typename StrT>
192 T loadFromJson(
const StrT& keyName, T&& defaultValue = {})
const
194 const auto& jv = jsonData().value(keyName);
195 return jv.isUndefined() ? std::forward<T>(defaultValue)
204 template <
typename T>
205 T takeFromJson(
const QString& key, T&& defaultValue = {})
207 if (
const auto& jv = takeValueFromJson(key); !jv.isUndefined())
208 return fromJson<T>(jv);
210 return std::forward<T>(defaultValue);
220 virtual QString errorString()
const;
223 QUrl errorUrl()
const;
225 int maxRetries()
const;
226 void setMaxRetries(
int newMaxRetries);
228 using duration_ms_t = std::chrono::milliseconds::rep;
230 std::chrono::seconds getCurrentTimeout()
const;
231 Q_INVOKABLE Quotient::BaseJob::duration_ms_t getCurrentTimeoutMs()
const;
232 std::chrono::seconds getNextRetryInterval()
const;
233 Q_INVOKABLE Quotient::BaseJob::duration_ms_t getNextRetryMs()
const;
234 std::chrono::milliseconds timeToRetry()
const;
235 Q_INVOKABLE Quotient::BaseJob::duration_ms_t millisToRetry()
const;
237 friend QDebug operator<<(QDebug dbg,
const BaseJob* j)
239 return dbg << j->objectName();
243 void initiate(Quotient::ConnectionData* connData,
bool inBackground);
265 void aboutToSendRequest(QNetworkRequest* req);
271 void statusChanged(Quotient::BaseJob::Status newStatus);
281 void retryScheduled(
int nextAttempt,
282 Quotient::BaseJob::duration_ms_t inMilliseconds);
308 void finished(Quotient::BaseJob* job);
319 void result(Quotient::BaseJob* job);
326 void success(Quotient::BaseJob*);
334 void failure(Quotient::BaseJob*);
336 void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
337 void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
340 using headers_t = QHash<QByteArray, QByteArray>;
342 const headers_t& requestHeaders()
const;
343 void setRequestHeader(
const headers_t::key_type& headerName,
344 const headers_t::mapped_type& headerValue);
345 void setRequestHeaders(
const headers_t& headers);
346 QUrlQuery query()
const;
347 void setRequestQuery(
const QUrlQuery& query);
348 const RequestData& requestData()
const;
349 void setRequestData(RequestData&& data);
350 const QByteArrayList& expectedContentTypes()
const;
351 void addExpectedContentType(
const QByteArray& contentType);
352 void setExpectedContentTypes(
const QByteArrayList& contentTypes);
353 QByteArrayList expectedKeys()
const;
354 void addExpectedKey(
const QByteArray &key);
355 void setExpectedKeys(
const QByteArrayList &keys);
357 const QNetworkReply* reply()
const;
358 QNetworkReply* reply();
365 static QUrl makeRequestUrl(QUrl baseUrl,
const QByteArray &encodedPath,
366 const QUrlQuery& query = {});
374 virtual void doPrepare();
382 virtual void onSentRequest(QNetworkReply*);
383 virtual void beforeAbandon();
391 virtual Status prepareResult();
404 virtual Status prepareError(Status currentStatus);
420 QJsonValue takeValueFromJson(
const QString& key);
422 void setStatus(Status s);
423 void setStatus(
int code, QString message);
430 void setLoggingCategory(QMessageLogger::CategoryFunction lcf);
456 virtual Status checkReply(
const QNetworkReply *reply)
const;
463 friend class ConnectionData;
464 template <
class JobT>
465 friend class JobHandle;
469 QFuture<
void> future();
477 return job && job->error() == BaseJob::Pending;