1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QRESTACCESSMANAGER_P_H |
5 | #define QRESTACCESSMANAGER_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists for the convenience |
12 | // of the Network Access API. This header file may change from |
13 | // version to version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include "qrestaccessmanager.h" |
19 | #include "private/qobject_p.h" |
20 | |
21 | #include <QtNetwork/qnetworkaccessmanager.h> |
22 | |
23 | #include <QtCore/qjsonarray.h> |
24 | #include <QtCore/qhash.h> |
25 | #include <QtCore/qjsondocument.h> |
26 | #include <QtCore/qjsonobject.h> |
27 | #include <QtCore/qxpfunctional.h> |
28 | |
29 | QT_BEGIN_NAMESPACE |
30 | |
31 | class QRestReply; |
32 | class QRestAccessManagerPrivate : public QObjectPrivate |
33 | { |
34 | public: |
35 | QRestAccessManagerPrivate(); |
36 | ~QRestAccessManagerPrivate() override; |
37 | |
38 | QNetworkReply* createActiveRequest(QNetworkReply *reply, const QObject *contextObject, |
39 | QtPrivate::SlotObjUniquePtr slot); |
40 | void handleReplyFinished(QNetworkReply *reply); |
41 | |
42 | using ReqOpRef = qxp::function_ref<QNetworkReply*(QNetworkAccessManager*) const>; |
43 | QNetworkReply *executeRequest(ReqOpRef requestOperation, |
44 | const QObject *context, QtPrivate::QSlotObjectBase *rawSlot) |
45 | { |
46 | QtPrivate::SlotObjUniquePtr slot(rawSlot); |
47 | if (!qnam) |
48 | return warnNoAccessManager(); |
49 | verifyThreadAffinity(contextObject: context); |
50 | QNetworkReply *reply = requestOperation(qnam); |
51 | return createActiveRequest(reply, contextObject: context, slot: std::move(slot)); |
52 | } |
53 | |
54 | using ReqOpRefJson = qxp::function_ref<QNetworkReply*(QNetworkAccessManager*, |
55 | const QNetworkRequest &, |
56 | const QByteArray &) const>; |
57 | QNetworkReply *executeRequest(ReqOpRefJson requestOperation, const QJsonDocument &jsonDoc, |
58 | const QNetworkRequest &request, |
59 | const QObject *context, QtPrivate::QSlotObjectBase *rawSlot) |
60 | { |
61 | QtPrivate::SlotObjUniquePtr slot(rawSlot); |
62 | if (!qnam) |
63 | return warnNoAccessManager(); |
64 | verifyThreadAffinity(contextObject: context); |
65 | QNetworkRequest req(request); |
66 | auto h = req.headers(); |
67 | if (!h.contains(name: QHttpHeaders::WellKnownHeader::ContentType)) { |
68 | h.append(name: QHttpHeaders::WellKnownHeader::ContentType, |
69 | value: QLatin1StringView{"application/json" }); |
70 | } |
71 | req.setHeaders(std::move(h)); |
72 | QNetworkReply *reply = requestOperation(qnam, req, jsonDoc.toJson(format: QJsonDocument::Compact)); |
73 | return createActiveRequest(reply, contextObject: context, slot: std::move(slot)); |
74 | } |
75 | |
76 | void verifyThreadAffinity(const QObject *contextObject); |
77 | Q_DECL_COLD_FUNCTION |
78 | QNetworkReply* warnNoAccessManager(); |
79 | |
80 | struct CallerInfo { |
81 | QPointer<const QObject> contextObject = nullptr; |
82 | QtPrivate::SlotObjSharedPtr slot; |
83 | }; |
84 | QHash<QNetworkReply*, CallerInfo> activeRequests; |
85 | |
86 | QNetworkAccessManager *qnam = nullptr; |
87 | bool deletesRepliesOnFinished = true; |
88 | Q_DECLARE_PUBLIC(QRestAccessManager) |
89 | }; |
90 | |
91 | QT_END_NAMESPACE |
92 | |
93 | #endif |
94 | |