9#include <QtNetwork/qhttpmultipart.h>
10#include <QtNetwork/qnetworkaccessmanager.h>
11#include <QtNetwork/qnetworkreply.h>
13#include <QtCore/qjsondocument.h>
14#include <QtCore/qjsonobject.h>
15#include <QtCore/qloggingcategory.h>
16#include <QtCore/qthread.h>
20using namespace Qt::StringLiterals;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
220
221
222
223
224
225
226
227
230
231
232
233
234
235
236
237
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
276
277
278
279
280
281
282
283
284
287
288
289
290
291
292
293
294
297
298
299
300
301
302
303
304
307
308
309
310
311
312
313
314
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
353
354
355
356
357
358
359
360
363
364
365
366
367
368
369
370
373
374
375
376
377
378
379
380
383
384
385
386
387
388
389
390
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
428
429
430
431
432
433
434
435
438
439
440
441
442
443
444
445
448
449
450
451
452
453
454
455
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
525
526
527
528
529
530
531
532
535
536
537
538
539
540
541
542
545
546
547
548
549
550
552QRestAccessManager::QRestAccessManager(QNetworkAccessManager *manager, QObject *parent)
553 : QObject(*
new QRestAccessManagerPrivate, parent)
555 Q_D(QRestAccessManager);
558 qCWarning(lcQrest,
"QRestAccessManager: QNetworkAccesManager is nullptr");
562
563
564QRestAccessManager::~QRestAccessManager()
568
569
570
571
572QNetworkAccessManager *QRestAccessManager::networkAccessManager()
const
574 Q_D(
const QRestAccessManager);
583 if (!activeRequests.isEmpty()) {
584 qCWarning(lcQrest,
"Access manager destroyed while %lld requests were still in progress",
585 qlonglong(activeRequests.size()));
589QNetworkReply *QRestAccessManager::postWithDataImpl(
const QNetworkRequest &request,
590 const QJsonDocument &data,
const QObject *context,
591 QtPrivate::QSlotObjectBase *slot)
593 Q_D(QRestAccessManager);
594 return d->executeRequest([](
auto qnam,
auto req,
auto data) {
return qnam->post(req, data); },
595 data, request, context, slot);
598QNetworkReply *QRestAccessManager::postWithDataImpl(
const QNetworkRequest &request,
599 const QVariantMap &data,
const QObject *context,
600 QtPrivate::QSlotObjectBase *slot)
602 return postWithDataImpl(request, QJsonDocument::fromVariant(data), context, slot);
605QNetworkReply *QRestAccessManager::postWithDataImpl(
const QNetworkRequest &request,
606 const QByteArray &data,
const QObject *context,
607 QtPrivate::QSlotObjectBase *slot)
609 Q_D(QRestAccessManager);
610 return d->executeRequest([&](
auto qnam) {
return qnam->post(request, data); }, context, slot);
613QNetworkReply *QRestAccessManager::postWithDataImpl(
const QNetworkRequest &request,
614 QHttpMultiPart *data,
const QObject *context,
615 QtPrivate::QSlotObjectBase *slot)
617 Q_D(QRestAccessManager);
618 return d->executeRequest([&](
auto qnam) {
return qnam->post(request, data); }, context, slot);
621QNetworkReply *QRestAccessManager::postWithDataImpl(
const QNetworkRequest &request,
622 QIODevice *data,
const QObject *context,
623 QtPrivate::QSlotObjectBase *slot)
625 Q_D(QRestAccessManager);
626 return d->executeRequest([&](
auto qnam) {
return qnam->post(request, data); }, context, slot);
629QNetworkReply *QRestAccessManager::getNoDataImpl(
const QNetworkRequest &request,
630 const QObject *context, QtPrivate::QSlotObjectBase *slot)
632 Q_D(QRestAccessManager);
633 return d->executeRequest([&](
auto qnam) {
return qnam->get(request); }, context, slot);
636QNetworkReply *QRestAccessManager::getWithDataImpl(
const QNetworkRequest &request,
637 const QByteArray &data,
const QObject *context,
638 QtPrivate::QSlotObjectBase *slot)
640 Q_D(QRestAccessManager);
641 return d->executeRequest([&](
auto qnam) {
return qnam->get(request, data); }, context, slot);
644QNetworkReply *QRestAccessManager::getWithDataImpl(
const QNetworkRequest &request,
645 const QJsonDocument &data,
const QObject *context,
646 QtPrivate::QSlotObjectBase *slot)
648 Q_D(QRestAccessManager);
649 return d->executeRequest([](
auto qnam,
auto req,
auto data) {
return qnam->get(req, data); },
650 data, request, context, slot);
653QNetworkReply *QRestAccessManager::getWithDataImpl(
const QNetworkRequest &request,
654 QIODevice *data,
const QObject *context,
655 QtPrivate::QSlotObjectBase *slot)
657 Q_D(QRestAccessManager);
658 return d->executeRequest([&](
auto qnam) {
return qnam->get(request, data); }, context, slot);
661QNetworkReply *QRestAccessManager::deleteResourceNoDataImpl(
const QNetworkRequest &request,
662 const QObject *context, QtPrivate::QSlotObjectBase *slot)
664 Q_D(QRestAccessManager);
665 return d->executeRequest([&](
auto qnam) {
return qnam->deleteResource(request); }, context, slot);
668QNetworkReply *QRestAccessManager::headNoDataImpl(
const QNetworkRequest &request,
669 const QObject *context, QtPrivate::QSlotObjectBase *slot)
671 Q_D(QRestAccessManager);
672 return d->executeRequest([&](
auto qnam) {
return qnam->head(request); }, context, slot);
675QNetworkReply *QRestAccessManager::putWithDataImpl(
const QNetworkRequest &request,
676 const QJsonDocument &data,
const QObject *context,
677 QtPrivate::QSlotObjectBase *slot)
679 Q_D(QRestAccessManager);
680 return d->executeRequest([](
auto qnam,
auto req,
auto data) {
return qnam->put(req, data); },
681 data, request, context, slot);
684QNetworkReply *QRestAccessManager::putWithDataImpl(
const QNetworkRequest &request,
685 const QVariantMap &data,
const QObject *context,
686 QtPrivate::QSlotObjectBase *slot)
688 return putWithDataImpl(request, QJsonDocument::fromVariant(data), context, slot);
691QNetworkReply *QRestAccessManager::putWithDataImpl(
const QNetworkRequest &request,
692 const QByteArray &data,
const QObject *context,
693 QtPrivate::QSlotObjectBase *slot)
695 Q_D(QRestAccessManager);
696 return d->executeRequest([&](
auto qnam) {
return qnam->put(request, data); }, context, slot);
699QNetworkReply *QRestAccessManager::putWithDataImpl(
const QNetworkRequest &request,
700 QHttpMultiPart *data,
const QObject *context,
701 QtPrivate::QSlotObjectBase *slot)
703 Q_D(QRestAccessManager);
704 return d->executeRequest([&](
auto qnam) {
return qnam->put(request, data); }, context, slot);
707QNetworkReply *QRestAccessManager::putWithDataImpl(
const QNetworkRequest &request, QIODevice *data,
708 const QObject *context, QtPrivate::QSlotObjectBase *slot)
710 Q_D(QRestAccessManager);
711 return d->executeRequest([&](
auto qnam) {
return qnam->put(request, data); }, context, slot);
716 static auto patch =
"PATCH"_ba;
720QNetworkReply *QRestAccessManager::patchWithDataImpl(
const QNetworkRequest &request,
721 const QJsonDocument &data,
const QObject *context,
722 QtPrivate::QSlotObjectBase *slot)
724 Q_D(QRestAccessManager);
725 return d->executeRequest(
726 [](
auto qnam,
auto req,
auto data) {
return qnam->sendCustomRequest(req, PATCH(), data); },
727 data, request, context, slot);
730QNetworkReply *QRestAccessManager::patchWithDataImpl(
const QNetworkRequest &request,
731 const QVariantMap &data,
const QObject *context,
732 QtPrivate::QSlotObjectBase *slot)
734 return patchWithDataImpl(request, QJsonDocument::fromVariant(data), context, slot);
737QNetworkReply *QRestAccessManager::patchWithDataImpl(
const QNetworkRequest &request,
738 const QByteArray &data,
const QObject *context,
739 QtPrivate::QSlotObjectBase *slot)
741 Q_D(QRestAccessManager);
742 return d->executeRequest([&](
auto qnam) {
return qnam->sendCustomRequest(request, PATCH(), data); },
746QNetworkReply *QRestAccessManager::patchWithDataImpl(
const QNetworkRequest &request, QIODevice *data,
747 const QObject *context, QtPrivate::QSlotObjectBase *slot)
749 Q_D(QRestAccessManager);
750 return d->executeRequest([&](
auto qnam) {
return qnam->sendCustomRequest(request, PATCH(), data); },
754QNetworkReply *QRestAccessManager::customWithDataImpl(
const QNetworkRequest &request,
755 const QByteArray& method,
const QByteArray &data,
756 const QObject *context,
757 QtPrivate::QSlotObjectBase *slot)
759 Q_D(QRestAccessManager);
760 return d->executeRequest([&](
auto qnam) {
return qnam->sendCustomRequest(request, method, data); },
764QNetworkReply *QRestAccessManager::customWithDataImpl(
const QNetworkRequest &request,
765 const QByteArray& method, QIODevice *data,
766 const QObject *context,
767 QtPrivate::QSlotObjectBase *slot)
769 Q_D(QRestAccessManager);
770 return d->executeRequest([&](
auto qnam) {
return qnam->sendCustomRequest(request, method, data); },
774QNetworkReply *QRestAccessManager::customWithDataImpl(
const QNetworkRequest &request,
775 const QByteArray& method, QHttpMultiPart *data,
776 const QObject *context,
777 QtPrivate::QSlotObjectBase *slot)
779 Q_D(QRestAccessManager);
780 return d->executeRequest([&](
auto qnam) {
return qnam->sendCustomRequest(request, method, data); },
785 const QObject *contextObject,
786 QtPrivate::SlotObjUniquePtr slot)
788 Q_Q(QRestAccessManager);
790 [[maybe_unused]]
const auto [_, inserted] =
791 activeRequests.try_emplace(reply, CallerInfo{contextObject, std::move(slot)});
797 QObject::connect(reply, &QNetworkReply::finished, q, [reply,
this]() {
798 handleReplyFinished(reply);
801 QObject::connect(reply, &QObject::destroyed, q, [reply,
this]() {
802 activeRequests.remove(reply);
806 QObject::connect(contextObject, &QObject::destroyed, q, [reply,
this]() {
807 activeRequests.remove(reply);
815 Q_Q(QRestAccessManager);
816 if (QThread::currentThread() != q->thread()) {
817 qCWarning(lcQrest,
"QRestAccessManager can only be called in the thread it belongs to");
820 if (contextObject && (contextObject->thread() != q->thread())) {
821 qCWarning(lcQrest,
"QRestAccessManager: the context object must reside in the same thread");
827static QNetworkReply* warnNoAccessManager()
829 qCWarning(lcQrest,
"QRestAccessManager: QNetworkAccessManager not set");
835 auto request = activeRequests.find(reply);
836 if (request == activeRequests.end()) {
837 qCDebug(lcQrest,
"QRestAccessManager: Unexpected reply received, ignoring");
841 CallerInfo caller = std::move(request.value());
842 activeRequests.erase(request);
846 QRestReply restReply(reply);
847 void *argv[] = {
nullptr, &restReply };
849 QObject *context = caller.contextObject
850 ?
const_cast<QObject*>(caller.contextObject.get()) :
nullptr;
851 caller.slot->call(context, argv);
857 QtPrivate::QSlotObjectBase *rawSlot)
859 QtPrivate::SlotObjUniquePtr slot(rawSlot);
861 return warnNoAccessManager();
862 verifyThreadAffinity(context);
863 QNetworkReply *reply = requestOperation(qnam);
864 return createActiveRequest(reply, context, std::move(slot));
869 const QNetworkRequest &request,
const QObject *context,
870 QtPrivate::QSlotObjectBase *rawSlot)
872 QtPrivate::SlotObjUniquePtr slot(rawSlot);
874 return warnNoAccessManager();
875 verifyThreadAffinity(context);
876 QNetworkRequest req(request);
877 auto h = req.headers();
878 if (!h.contains(QHttpHeaders::WellKnownHeader::ContentType)) {
879 h.append(QHttpHeaders::WellKnownHeader::ContentType,
880 QLatin1StringView{
"application/json"});
882 req.setHeaders(
std::move(h));
883 QNetworkReply *reply = requestOperation(qnam, req, jsonDoc.toJson(QJsonDocument::Compact));
884 return createActiveRequest(reply, context, std::move(slot));
889#include "moc_qrestaccessmanager.cpp"
~QRestAccessManagerPrivate() override
QRestAccessManagerPrivate()
QNetworkReply * executeRequest(ReqOpRef requestOperation, const QObject *context, QtPrivate::QSlotObjectBase *rawSlot)
QNetworkReply * createActiveRequest(QNetworkReply *reply, const QObject *contextObject, QtPrivate::SlotObjUniquePtr slot)
void verifyThreadAffinity(const QObject *contextObject)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
static const QByteArray & PATCH()