QtRestClient  3.0.0
A library for generic JSON-based REST-APIs, with a mechanism to map JSON to Qt objects
restreply.h
1 #ifndef QTRESTCLIENT_RESTREPLY_H
2 #define QTRESTCLIENT_RESTREPLY_H
3 
4 #include "QtRestClient/qtrestclient_global.h"
5 #include "QtRestClient/qtrestclient_helpertypes.h"
6 
7 #include <functional>
8 #include <chrono>
9 
10 #ifdef QT_RESTCLIENT_USE_ASYNC
11 #include <QtCore/QThreadPool>
12 #include <QtCore/QFuture>
13 #endif
14 
15 #include <QtNetwork/qnetworkreply.h>
16 
17 namespace QtRestClient {
18 
19 class RestReplyPrivate;
20 class RestReplyAwaitable;
21 class QmlGenericRestReply; //needed for QML bindings
23 class Q_RESTCLIENT_EXPORT RestReply : public QObject
24 {
25  Q_OBJECT
26 
28  Q_PROPERTY(bool autoDelete READ autoDelete WRITE setAutoDelete NOTIFY autoDeleteChanged)
30  Q_PROPERTY(bool allowEmptyReplies READ allowsEmptyReplies WRITE setAllowEmptyReplies NOTIFY allowEmptyRepliesChanged)
31 #ifdef QT_RESTCLIENT_USE_ASYNC
32  Q_PROPERTY(bool async READ isAsync WRITE setAsync NOTIFY asyncChanged)
34 #endif
35 
36 public:
37 #ifdef DOXYGEN_RUN
38  using DataType = std::variant<std::nullopt_t, QCborValue, QJsonValue>;
40 #else
41  using DataType = __private::__binder::DataType;
42 #endif
43 
45  enum class Error {
46  //default error types
47  Network,
48  Parser,
49  Failure,
50 
51  //extended error types
52  Deserialization
53  };
54  Q_ENUM(Error)
55 
56 
57  RestReply(QNetworkReply *networkReply, QObject *parent = nullptr);
58 #ifdef QT_RESTCLIENT_USE_ASYNC
59  RestReply(const QFuture<QNetworkReply*> &networkReplyFuture, QObject *parent = nullptr);
62  RestReply(QNetworkReply *networkReply, QThreadPool *asyncPool, QObject *parent = nullptr);
64  RestReply(const QFuture<QNetworkReply*> &networkReplyFuture, QThreadPool *asyncPool, QObject *parent = nullptr);
65 #endif
66  ~RestReply() override;
67 
69  template <typename TFn>
70  RestReply *onSucceeded(TFn &&handler);
72  template <typename TFn>
73  RestReply *onSucceeded(QObject *scope, TFn &&handler);
75  template <typename TFn>
76  RestReply *onFailed(TFn &&handler);
78  template <typename TFn>
79  RestReply *onFailed(QObject *scope, TFn &&handler);
81  template <typename TFn>
82  RestReply *onCompleted(TFn &&handler);
84  template <typename TFn>
85  RestReply *onCompleted(QObject *scope, TFn &&handler);
86 
88  RestReply *onError(std::function<void(QString, int, Error)> handler);
90  RestReply *onError(QObject *scope, std::function<void(QString, int, Error)> handler);
91 
93  RestReply *onAllErrors(const std::function<void(QString, int, Error)> &handler);
95  RestReply *onAllErrors(QObject *scope,
96  const std::function<void(QString, int, Error)> &handler);
98  template <typename TFn>
99  RestReply *onAllErrors(const std::function<void(QString, int, Error)> &handler,
100  TFn &&failureTransformer);
102  template <typename TFn>
103  RestReply *onAllErrors(QObject *scope,
104  const std::function<void(QString, int, Error)> &handler,
105  TFn &&failureTransformer);
106 
107 #ifdef QT_RESTCLIENT_USE_ASYNC
108  Q_INVOKABLE RestReply *makeAsync(QThreadPool *threadPool = QThreadPool::globalInstance());
110 #endif
111  Q_INVOKABLE inline RestReply *disableAutoDelete() {
113  setAutoDelete(false);
114  return this;
115  }
116 
118  bool autoDelete() const;
120  bool allowsEmptyReplies() const;
121 #ifdef QT_RESTCLIENT_USE_ASYNC
122  bool isAsync() const;
124 #endif
125 
127  Q_INVOKABLE QNetworkReply *networkReply() const;
128 
130  RestReplyAwaitable awaitable();
131 
132 public Q_SLOTS:
134  void abort();
136  void retry();
138  void retryAfter(std::chrono::milliseconds mSecs);
139 
141  void setAutoDelete(bool autoDelete);
143  void setAllowEmptyReplies(bool allowEmptyReplies);
144 #ifdef QT_RESTCLIENT_USE_ASYNC
145  void setAsync(bool async);
147 #endif
148 
149 Q_SIGNALS:
151  void completed(int httpStatus, const DataType &reply, QPrivateSignal);
153  void succeeded(int httpStatus, const DataType &reply, QPrivateSignal);
155  void failed(int httpStatus, const DataType &reason, QPrivateSignal);
157  void error(const QString &errorString, int error, Error errorType, QPrivateSignal);
158 
160  void networkError(QNetworkReply::NetworkError error);
161 #ifndef QT_NO_SSL
162  void sslErrors(const QList<QSslError> &errors, bool &ignoreErrors);
164 #endif
165 
167  void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
169  void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
170 
172  void autoDeleteChanged(bool autoDelete, QPrivateSignal);
174  void allowEmptyRepliesChanged(bool allowEmptyReplies, QPrivateSignal);
175 #ifdef QT_RESTCLIENT_USE_ASYNC
176  void asyncChanged(bool async, QPrivateSignal);
178 #endif
179 
180 protected:
182  RestReply(RestReplyPrivate &dd, QObject *parent = nullptr);
183 
184 private:
185  Q_DECLARE_PRIVATE(RestReply)
186 
187  Qt::ConnectionType callbackType() const;
188 
189  Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
190  Q_PRIVATE_SLOT(d_func(), void _q_retryReply())
191 #ifndef QT_NO_SSL
192  Q_PRIVATE_SLOT(d_func(), void _q_handleSslErrors(const QList<QSslError> &))
193 #endif
194 };
195 
196 template<typename TFn>
198 {
199  return onSucceeded(this, std::forward<TFn>(handler));
200 }
201 
202 template<typename TFn>
203 RestReply *RestReply::onSucceeded(QObject *scope, TFn &&handler)
204 {
206  scope, __private::bindCallback(std::forward<TFn>(handler)),
207  callbackType());
208  return this;
209 }
210 
211 template<typename TFn>
213 {
214  return onFailed(this, std::forward<TFn>(handler));
215 }
216 
217 template<typename TFn>
218 RestReply *RestReply::onFailed(QObject *scope, TFn &&handler)
219 {
220  connect(this, &RestReply::failed,
221  scope, __private::bindCallback(std::forward<TFn>(handler)),
222  callbackType());
223  return this;
224 }
225 
226 template<typename TFn>
228 {
229  return onCompleted(this, std::forward<TFn>(handler));
230 }
231 
232 template<typename TFn>
233 RestReply *RestReply::onCompleted(QObject *scope, TFn &&handler)
234 {
236  scope, __private::bindCallback(std::forward<TFn>(handler)),
237  callbackType());
238  return this;
239 }
240 
241 template<typename TFn>
242 RestReply *RestReply::onAllErrors(const std::function<void (QString, int, Error)> &handler, TFn &&failureTransformer)
243 {
244  return onAllErrors(this, handler, std::forward<TFn>(failureTransformer));
245 }
246 
247 template<typename TFn>
248 RestReply *RestReply::onAllErrors(QObject *scope, const std::function<void (QString, int, Error)> &handler, TFn &&failureTransformer)
249 {
250  this->onFailed(scope, __private::bindCallback(handler, std::forward<TFn>(failureTransformer), Error::Failure));
251  this->onError(scope, handler);
252  return this;
253 }
254 
255 }
256 
257 #endif // QTRESTCLIENT_RESTREPLY_H
QtRestClient
The Namespace containing all classes of the QtRestClient module.
Definition: genericrestreply.h:14
QtRestClient::RestReply::Error
Error
Defines the different possible error types.
Definition: restreply.h:45
QNetworkReply
QThreadPool::globalInstance
QThreadPool * globalInstance()
QtRestClient::RestReply::Error::Failure
Indicates that the server sent a failure for the request.
QList
QtRestClient::RestReply::onCompleted
RestReply * onCompleted(TFn &&handler)
Set a handler to be called when the request was completed, regardless of success or failure.
Definition: restreply.h:227
QObject::connect
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QtRestClient::RestReply::onFailed
RestReply * onFailed(TFn &&handler)
Set a handler to be called if the request failed.
Definition: restreply.h:212
QtRestClient::RestReply::onSucceeded
RestReply * onSucceeded(TFn &&handler)
Set a handler to be called if the request succeeded.
Definition: restreply.h:197
QString
QtRestClient::RestReply::completed
void completed(int httpStatus, const DataType &reply, QPrivateSignal)
Is emitted when the request completed, i.e. succeeded or failed.
QThreadPool
QtRestClient::RestReply::succeeded
void succeeded(int httpStatus, const DataType &reply, QPrivateSignal)
Is emitted when the request succeeded.
QtRestClient::RestReply::failed
void failed(int httpStatus, const DataType &reason, QPrivateSignal)
Is emitted when the request failed.
QFuture
QtRestClient::RestReply::onError
RestReply * onError(std::function< void(QString, int, Error)> handler)
Set a handler to be called if a network error or json parse error occures.
QtRestClient::RestReply::DataType
std::variant< std::nullopt_t, QCborValue, QJsonValue > DataType
Internal datatype that unites JSON and CBOR data in a typesafe union.
Definition: restreply.h:39
QObject
QtRestClient::RestReply
A class to handle replies for JSON requests.
Definition: restreply.h:23