7#include "qplatformdefs.h"
12#include "qhttp1configuration.h"
13#include "qhttp2configuration.h"
14#include "private/http2protocol_p.h"
17#include "QtCore/qdatetime.h"
18#include "QtCore/qlocale.h"
19#include "QtCore/qshareddata.h"
20#include "QtCore/qtimezone.h"
21#include "QtCore/private/qduplicatetracker_p.h"
22#include "QtCore/private/qtools_p.h"
24#if QT_CONFIG(datestring)
29#include <q20algorithm.h>
33using namespace Qt::StringLiterals;
34using namespace std::chrono_literals;
36constexpr std::chrono::milliseconds QNetworkRequest::DefaultTransferTimeout;
39QT_IMPL_METATYPE_EXTERN_TAGGED(QNetworkRequest::RedirectPolicy, QNetworkRequest__RedirectPolicy)
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
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
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
374
375
376
377
378
379
380
381
382
383
386
387
388
389
390
391
392
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
420
421
422
423
424
425
426
427
428
429
430
431
434
435
436
437
438
439
441class QNetworkRequestPrivate:
public QSharedData,
public QNetworkHeadersPrivate
444 static const int maxRedirectCount = 50;
445 inline QNetworkRequestPrivate()
446 : priority(QNetworkRequest::NormalPriority)
448 , sslConfiguration(
nullptr)
450 , maxRedirectsAllowed(maxRedirectCount)
451 { qRegisterMetaType<QNetworkRequest>(); }
452 ~QNetworkRequestPrivate()
455 delete sslConfiguration;
460 QNetworkRequestPrivate(
const QNetworkRequestPrivate &other)
461 : QSharedData(other), QNetworkHeadersPrivate(other)
464 priority = other.priority;
465 maxRedirectsAllowed = other.maxRedirectsAllowed;
467 sslConfiguration =
nullptr;
468 if (other.sslConfiguration)
469 sslConfiguration =
new QSslConfiguration(*other.sslConfiguration);
471 peerVerifyName = other.peerVerifyName;
473 h1Configuration = other.h1Configuration;
474 h2Configuration = other.h2Configuration;
475 decompressedSafetyCheckThreshold = other.decompressedSafetyCheckThreshold;
477 transferTimeout = other.transferTimeout;
478 idleTimeBeforeProbes = other.idleTimeBeforeProbes;
479 intervalBetweenProbes = other.intervalBetweenProbes;
480 probeCount = other.probeCount;
483 inline bool operator==(
const QNetworkRequestPrivate &other)
const
485 return url == other.url &&
486 priority == other.priority &&
487 attributes == other.attributes &&
488 maxRedirectsAllowed == other.maxRedirectsAllowed &&
489 peerVerifyName == other.peerVerifyName
491 && h1Configuration == other.h1Configuration
492 && h2Configuration == other.h2Configuration
493 && decompressedSafetyCheckThreshold == other.decompressedSafetyCheckThreshold
495 && transferTimeout == other.transferTimeout
496 && QHttpHeadersHelper::compareStrict(httpHeaders, other.httpHeaders)
497 && idleTimeBeforeProbes == other.idleTimeBeforeProbes
498 && intervalBetweenProbes == other.intervalBetweenProbes
499 && probeCount == other.probeCount;
505 QNetworkRequest::Priority priority;
507 mutable QSslConfiguration *sslConfiguration;
509 int maxRedirectsAllowed;
510 QString peerVerifyName;
512 QHttp1Configuration h1Configuration;
513 QHttp2Configuration h2Configuration;
514 qint64 decompressedSafetyCheckThreshold = 10ll * 1024ll * 1024ll;
516 std::chrono::milliseconds transferTimeout = 0ms;
517 std::chrono::duration<
int> idleTimeBeforeProbes{0};
518 std::chrono::duration<
int> intervalBetweenProbes{0};
523
524
525
526
527
528QNetworkRequest::QNetworkRequest()
529 : d(
new QNetworkRequestPrivate)
537 d->h2Configuration.setStreamReceiveWindowSize(Http2::qtDefaultStreamReceiveWindowSize);
538 d->h2Configuration.setSessionReceiveWindowSize(Http2::maxSessionReceiveWindowSize);
539 d->h2Configuration.setServerPushEnabled(
false);
544
545
546
547
548
549QNetworkRequest::QNetworkRequest(
const QUrl &url)
556
557
558QNetworkRequest::QNetworkRequest(
const QNetworkRequest &other)
564
565
566QNetworkRequest::~QNetworkRequest()
573
574
575
576
577
578bool QNetworkRequest::operator==(
const QNetworkRequest &other)
const
580 return d == other.d || *d == *other.d;
584
585
586
587
588
589
592
593
594QNetworkRequest &QNetworkRequest::operator=(
const QNetworkRequest &other)
601
602
603
604
607
608
609
610
611QUrl QNetworkRequest::url()
const
617
618
619
620
621void QNetworkRequest::setUrl(
const QUrl &url)
627
628
629
630
631
632
633QHttpHeaders QNetworkRequest::headers()
const
639
640
641
642
643
644
645
646
647
648
649void QNetworkRequest::setHeaders(QHttpHeaders &&newHeaders)
651 d->setHeaders(std::move(newHeaders));
655
656
657
658void QNetworkRequest::setHeaders(
const QHttpHeaders &newHeaders)
660 d->setHeaders(newHeaders);
664
665
666
667
668
669
670QVariant QNetworkRequest::header(KnownHeaders header)
const
672 return d->cookedHeaders.value(header);
676
677
678
679
680
681
682void QNetworkRequest::setHeader(KnownHeaders header,
const QVariant &value)
684 d->setCookedHeader(header, value);
688
689
690
691
692
693
694bool QNetworkRequest::hasRawHeader(QAnyStringView headerName)
const
696 return d->headers().contains(headerName);
700
701
702
703
704
705
706
707
708
709
710QByteArray QNetworkRequest::rawHeader(QAnyStringView headerName)
const
712 return d->rawHeader(headerName);
716
717
718
719
720
721QList<QByteArray> QNetworkRequest::rawHeaderList()
const
723 return d->rawHeadersKeys();
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748void QNetworkRequest::setRawHeader(
const QByteArray &headerName,
const QByteArray &headerValue)
750 d->setRawHeader(headerName, headerValue);
754
755
756
757
758
759
760
761
762QVariant QNetworkRequest::attribute(Attribute code,
const QVariant &defaultValue)
const
764 return d->attributes.value(code, defaultValue);
768
769
770
771
772
773
774
775void QNetworkRequest::setAttribute(Attribute code,
const QVariant &value)
778 d->attributes.insert(code, value);
780 d->attributes.remove(code);
785
786
787
788
789
790QSslConfiguration QNetworkRequest::sslConfiguration()
const
792 if (!d->sslConfiguration)
793 d->sslConfiguration =
new QSslConfiguration(QSslConfiguration::defaultConfiguration());
794 return *d->sslConfiguration;
798
799
800
801
802
803
804
805void QNetworkRequest::setSslConfiguration(
const QSslConfiguration &config)
807 if (!d->sslConfiguration)
808 d->sslConfiguration =
new QSslConfiguration(config);
810 *d->sslConfiguration = config;
815
816
817
818
819
820
821
822
823
824
825void QNetworkRequest::setOriginatingObject(QObject *object)
827 d->originatingObject = object;
831
832
833
834
835
836
837
838
839QObject *QNetworkRequest::originatingObject()
const
841 return d->originatingObject.data();
845
846
847
848
849
850
851QNetworkRequest::Priority QNetworkRequest::priority()
const
857
858
859
860
861
862
863
864
865
868
869
870
871
872
873
874
875
876
877
878void QNetworkRequest::setPriority(Priority priority)
880 d->priority = priority;
884
885
886
887
888
889
890
891int QNetworkRequest::maximumRedirectsAllowed()
const
893 return d->maxRedirectsAllowed;
897
898
899
900
901
902
903
904void QNetworkRequest::setMaximumRedirectsAllowed(
int maxRedirectsAllowed)
906 d->maxRedirectsAllowed = maxRedirectsAllowed;
910
911
912
913
914
915
916
917QString QNetworkRequest::peerVerifyName()
const
919 return d->peerVerifyName;
923
924
925
926
927
928
929
930void QNetworkRequest::setPeerVerifyName(
const QString &peerName)
932 d->peerVerifyName = peerName;
937
938
939
940
941
942
943
944QHttp1Configuration QNetworkRequest::http1Configuration()
const
946 return d->h1Configuration;
949
950
951
952
953
954
955void QNetworkRequest::setHttp1Configuration(
const QHttp1Configuration &configuration)
957 d->h1Configuration = configuration;
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981QHttp2Configuration QNetworkRequest::http2Configuration()
const
983 return d->h2Configuration;
987
988
989
990
991
992
993
994
995
996
997
998
999void QNetworkRequest::setHttp2Configuration(
const QHttp2Configuration &configuration)
1001 d->h2Configuration = configuration;
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014qint64 QNetworkRequest::decompressedSafetyCheckThreshold()
const
1016 return d->decompressedSafetyCheckThreshold;
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041void QNetworkRequest::setDecompressedSafetyCheckThreshold(qint64 threshold)
1043 d->decompressedSafetyCheckThreshold = threshold;
1048
1049
1050
1051
1052
1053
1054
1055
1057std::chrono::seconds QNetworkRequest::tcpKeepAliveIdleTimeBeforeProbes()
const
1059 return d->idleTimeBeforeProbes;
1063
1064
1065
1066
1067
1068
1069
1070
1071
1073void QNetworkRequest::doSetIdleTimeBeforeProbes(std::chrono::duration<
int> seconds)
1075 d->idleTimeBeforeProbes = seconds;
1079
1080
1081
1082
1083
1084
1085
1087std::chrono::seconds QNetworkRequest::tcpKeepAliveIntervalBetweenProbes()
const
1089 return d->intervalBetweenProbes;
1093
1094
1095
1096
1097
1098
1099
1100
1102void QNetworkRequest::doSetIntervalBetweenProbes(std::chrono::duration<
int> seconds)
1104 d->intervalBetweenProbes = seconds;
1108
1109
1110
1111
1112
1113
1114
1115
1117int QNetworkRequest::tcpKeepAliveProbeCount()
const
1119 return d->probeCount;
1123
1124
1125
1126
1127
1128
1129
1130
1132void QNetworkRequest::setTcpKeepAliveProbeCount(
int probes)
1134 d->probeCount = probes;
1137#if QT_CONFIG(http) || defined (Q_OS_WASM)
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1151
1152
1153
1154
1155
1156
1157
1158
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170std::chrono::milliseconds QNetworkRequest::transferTimeoutAsDuration()
const
1172 return d->transferTimeout;
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189void QNetworkRequest::setTransferTimeout(std::chrono::milliseconds duration)
1191 d->transferTimeout = duration;
1198 QHttpHeaders::WellKnownHeader wellKnownHeader;
1199 QNetworkRequest::KnownHeaders knownHeader;
1202constexpr bool operator<(
const HeaderPair &lhs,
const HeaderPair &rhs)
1204 return lhs.wellKnownHeader < rhs.wellKnownHeader;
1207constexpr bool operator<(
const HeaderPair &lhs, QHttpHeaders::WellKnownHeader rhs)
1209 return lhs.wellKnownHeader < rhs;
1212constexpr bool operator<(QHttpHeaders::WellKnownHeader lhs,
const HeaderPair &rhs)
1214 return lhs < rhs.wellKnownHeader;
1220 { QHttpHeaders::WellKnownHeader::ContentDisposition, QNetworkRequest::KnownHeaders::ContentDispositionHeader },
1221 { QHttpHeaders::WellKnownHeader::ContentLength, QNetworkRequest::KnownHeaders::ContentLengthHeader },
1222 { QHttpHeaders::WellKnownHeader::ContentType, QNetworkRequest::KnownHeaders::ContentTypeHeader },
1223 { QHttpHeaders::WellKnownHeader::Cookie, QNetworkRequest::KnownHeaders::CookieHeader },
1224 { QHttpHeaders::WellKnownHeader::ETag, QNetworkRequest::KnownHeaders::ETagHeader },
1225 { QHttpHeaders::WellKnownHeader::IfMatch , QNetworkRequest::KnownHeaders::IfMatchHeader },
1226 { QHttpHeaders::WellKnownHeader::IfModifiedSince, QNetworkRequest::KnownHeaders::IfModifiedSinceHeader },
1227 { QHttpHeaders::WellKnownHeader::IfNoneMatch, QNetworkRequest::KnownHeaders::IfNoneMatchHeader },
1228 { QHttpHeaders::WellKnownHeader::LastModified, QNetworkRequest::KnownHeaders::LastModifiedHeader},
1229 { QHttpHeaders::WellKnownHeader::Location, QNetworkRequest::KnownHeaders::LocationHeader},
1230 { QHttpHeaders::WellKnownHeader::Server, QNetworkRequest::KnownHeaders::ServerHeader },
1231 { QHttpHeaders::WellKnownHeader::SetCookie, QNetworkRequest::KnownHeaders::SetCookieHeader },
1232 { QHttpHeaders::WellKnownHeader::UserAgent, QNetworkRequest::KnownHeaders::UserAgentHeader }
1235static_assert(std::size(knownHeadersArr) == size_t(QNetworkRequest::KnownHeaders::NumKnownHeaders));
1241 if (it == std::end(knownHeadersArr) || key < *it)
1242 return std::nullopt;
1243 return it->knownHeader;
1248 auto pred = [key](
const HeaderPair &pair) {
return pair.knownHeader == key; };
1250 if (it == std::end(knownHeadersArr))
1251 return std::nullopt;
1252 return it->wellKnownHeader;
1256 QNetworkCookie::RawForm type,
1257 QByteArrayView separator)
1260 for (
const QNetworkCookie &cookie : cookies) {
1261 result += cookie.toRawForm(type);
1262 result += separator;
1264 if (!result.isEmpty())
1265 result.chop(separator.size());
1270 QByteArrayView separator)
1272 const QList<QNetworkCookie> *cookies = get_if<QList<QNetworkCookie>>(&value);
1275 return makeCookieHeader(*cookies, type, separator);
1281 case QNetworkRequest::ContentTypeHeader:
1282 case QNetworkRequest::ContentLengthHeader:
1283 case QNetworkRequest::ContentDispositionHeader:
1284 case QNetworkRequest::UserAgentHeader:
1285 case QNetworkRequest::ServerHeader:
1286 case QNetworkRequest::ETagHeader:
1287 case QNetworkRequest::IfMatchHeader:
1288 case QNetworkRequest::IfNoneMatchHeader:
1289 return value.toByteArray();
1291 case QNetworkRequest::LocationHeader:
1292 switch (value.userType()) {
1293 case QMetaType::QUrl:
1294 return value.toUrl().toEncoded();
1297 return value.toByteArray();
1300 case QNetworkRequest::LastModifiedHeader:
1301 case QNetworkRequest::IfModifiedSinceHeader:
1302 switch (value.userType()) {
1304 case QMetaType::QDate:
1305 return QNetworkHeadersPrivate::toHttpDate(value.toDate().startOfDay(QTimeZone::UTC));
1306 case QMetaType::QDateTime:
1307 return QNetworkHeadersPrivate::toHttpDate(value.toDateTime());
1310 return value.toByteArray();
1313 case QNetworkRequest::CookieHeader:
1314 return makeCookieHeader(value, QNetworkCookie::NameAndValueOnly,
"; ");
1316 case QNetworkRequest::SetCookieHeader:
1317 return makeCookieHeader(value, QNetworkCookie::Full,
", ");
1320 Q_UNREACHABLE_RETURN({});
1326 if (headerName.isEmpty())
1329 auto is = [headerName](QByteArrayView what) {
1330 return headerName.compare(what, Qt::CaseInsensitive) == 0;
1333 switch (QtMiscUtils::toAsciiLower(headerName.front())) {
1335 if (is(
"content-type"))
1336 return QNetworkRequest::ContentTypeHeader;
1337 else if (is(
"content-length"))
1338 return QNetworkRequest::ContentLengthHeader;
1339 else if (is(
"cookie"))
1340 return QNetworkRequest::CookieHeader;
1341 else if (is(
"content-disposition"))
1342 return QNetworkRequest::ContentDispositionHeader;
1347 return QNetworkRequest::ETagHeader;
1351 if (is(
"if-modified-since"))
1352 return QNetworkRequest::IfModifiedSinceHeader;
1354 return QNetworkRequest::IfMatchHeader;
1355 if (is(
"if-none-match"))
1356 return QNetworkRequest::IfNoneMatchHeader;
1361 return QNetworkRequest::LocationHeader;
1362 else if (is(
"last-modified"))
1363 return QNetworkRequest::LastModifiedHeader;
1367 if (is(
"set-cookie"))
1368 return QNetworkRequest::SetCookieHeader;
1369 else if (is(
"server"))
1370 return QNetworkRequest::ServerHeader;
1374 if (is(
"user-agent"))
1375 return QNetworkRequest::UserAgentHeader;
1384 QDateTime dt = QNetworkHeadersPrivate::fromHttpDate(raw);
1392 QList<QNetworkCookie> result;
1393 for (
auto cookie : QLatin1StringView(raw).tokenize(
';'_L1)) {
1394 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed());
1395 if (parsed.size() != 1)
1406 const QByteArrayView trimmed = raw.trimmed();
1407 if (!trimmed.startsWith(
'"') && !trimmed.startsWith(R"(W/")"))
1410 if (!trimmed.endsWith(
'"'))
1413 return QString::fromLatin1(trimmed);
1419 const QByteArrayView trimmedRaw = raw.trimmed();
1420 if (trimmedRaw ==
"*")
1421 return QStringList(QStringLiteral(
"*"));
1424 for (
auto &element : QLatin1StringView(trimmedRaw).tokenize(
','_L1)) {
1425 if (
const auto trimmed = element.trimmed(); op(trimmed))
1426 tags += QString::fromLatin1(trimmed);
1434 return parseMatchImpl(raw, [](QByteArrayView element) {
1435 return element.startsWith(
'"') && element.endsWith(
'"');
1441 return parseMatchImpl(raw, [](QByteArrayView element) {
1442 return (element.startsWith(
'"') || element.startsWith(R"(W/")")) && element.endsWith(
'"');
1451 case QNetworkRequest::UserAgentHeader:
1452 case QNetworkRequest::ServerHeader:
1453 case QNetworkRequest::ContentTypeHeader:
1454 case QNetworkRequest::ContentDispositionHeader:
1456 return QString::fromLatin1(value);
1458 case QNetworkRequest::ContentLengthHeader: {
1460 qint64 result = QByteArrayView(value).trimmed().toLongLong(&ok);
1466 case QNetworkRequest::LocationHeader: {
1467 QUrl result = QUrl::fromEncoded(value, QUrl::StrictMode);
1468 if (result.isValid() && !result.scheme().isEmpty())
1473 case QNetworkRequest::LastModifiedHeader:
1474 case QNetworkRequest::IfModifiedSinceHeader:
1475 return parseHttpDate(value);
1477 case QNetworkRequest::ETagHeader:
1478 return parseETag(value);
1480 case QNetworkRequest::IfMatchHeader:
1481 return parseIfMatch(value);
1483 case QNetworkRequest::IfNoneMatchHeader:
1484 return parseIfNoneMatch(value);
1486 case QNetworkRequest::CookieHeader:
1487 return QVariant::fromValue(parseCookieHeader(value));
1489 case QNetworkRequest::SetCookieHeader:
1490 return QVariant::fromValue(QNetworkCookie::parseCookies(value));
1493 Q_UNREACHABLE_RETURN({});
1504 case QNetworkRequest::IfMatchHeader: {
1506 for (
const auto &val : values)
1507 res << parseIfMatch(val);
1510 case QNetworkRequest::IfNoneMatchHeader: {
1512 for (
const auto &val : values)
1513 res << parseIfNoneMatch(val);
1516 case QNetworkRequest::CookieHeader: {
1517 auto listOpt = QNetworkHeadersPrivate::toCookieList(values);
1518 return listOpt.has_value() ? QVariant::fromValue(listOpt.value()) : QVariant();
1520 case QNetworkRequest::SetCookieHeader: {
1521 QList<QNetworkCookie> res;
1522 for (
const auto &val : values)
1523 res << QNetworkCookie::parseCookies(val);
1524 return QVariant::fromValue(res);
1527 return parseHeaderValue(header, values.first());
1534 return name.compare(QHttpHeaders::wellKnownHeaderName(QHttpHeaders::WellKnownHeader::SetCookie),
1535 Qt::CaseInsensitive) == 0;
1540 return name == QHttpHeaders::WellKnownHeader::SetCookie;
1543template<
class HeaderName>
1545 QByteArrayView value)
1547 headers.removeAll(header);
1553 if (isSetCookie(header)) {
1554 for (
auto cookie : QLatin1StringView(value).tokenize(
'\n'_L1))
1555 headers.append(QHttpHeaders::WellKnownHeader::SetCookie, cookie);
1557 headers.append(header, value);
1566 rawHeaderCache
.headersList = fromHttpToRaw(httpHeaders);
1573 if (httpHeaders.isEmpty())
1576 QList<QByteArray> result;
1577 result.reserve(httpHeaders.size());
1578 QDuplicateTracker<QByteArray> seen(httpHeaders.size());
1580 for (qsizetype i = 0; i < httpHeaders.size(); i++) {
1581 const auto nameL1 = httpHeaders.nameAt(i);
1582 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1583 if (seen.hasSeen(name))
1594 QByteArrayView setCookieStr = QHttpHeaders::wellKnownHeaderName(
1595 QHttpHeaders::WellKnownHeader::SetCookie);
1596 if (QAnyStringView::compare(headerName, setCookieStr, Qt::CaseInsensitive) != 0)
1597 return httpHeaders.combinedValue(headerName);
1600 const char* separator =
"";
1601 for (qsizetype i = 0; i < httpHeaders.size(); ++i) {
1602 if (QAnyStringView::compare(httpHeaders.nameAt(i), headerName, Qt::CaseInsensitive) == 0) {
1603 result.append(separator);
1604 result.append(httpHeaders.valueAt(i));
1617 setFromRawHeader(httpHeaders, key, value);
1618 parseAndSetHeader(key, value);
1620 invalidateHeaderCache();
1624 const QVariant &value)
1626 const auto wellKnownOpt = toWellKnownHeader(header);
1627 if (!wellKnownOpt) {
1629 qWarning(
"QNetworkRequest::setHeader: invalid header value KnownHeader(%d) received", header);
1633 if (value.isNull()) {
1634 httpHeaders.removeAll(wellKnownOpt.value());
1637 QByteArray rawValue = headerValue(header, value);
1638 if (rawValue.isEmpty()) {
1639 qWarning(
"QNetworkRequest::setHeader: QVariant of type %s cannot be used with header %s",
1641 QHttpHeaders::wellKnownHeaderName(wellKnownOpt.value()).constData());
1645 setFromRawHeader(httpHeaders, wellKnownOpt.value(), rawValue);
1649 invalidateHeaderCache();
1659 httpHeaders = newHeaders;
1660 setCookedFromHttp(httpHeaders);
1661 invalidateHeaderCache();
1666 httpHeaders = std::move(newHeaders);
1667 setCookedFromHttp(httpHeaders);
1668 invalidateHeaderCache();
1673 httpHeaders.replaceOrAppend(name, value);
1676 const auto knownHeaderOpt = toKnownHeader(name);
1678 parseAndSetHeader(knownHeaderOpt.value(), value);
1680 invalidateHeaderCache();
1685 httpHeaders.clear();
1687 invalidateHeaderCache();
1693 const int parsedKeyAsInt = parseHeaderName(key);
1694 if (parsedKeyAsInt != -1) {
1695 const QNetworkRequest::KnownHeaders parsedKey
1696 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1697 parseAndSetHeader(parsedKey, value);
1702 QByteArrayView value)
1704 if (value.isNull()) {
1706 }
else if (key == QNetworkRequest::ContentLengthHeader
1707 && cookedHeaders.contains(QNetworkRequest::ContentLengthHeader)) {
1720 switch (month_str[0]) {
1722 switch (month_str[1]) {
1726 switch (month_str[2] ) {
1737 switch (month_str[2] ) {
1745 switch (month_str[1]) {
1773 int pos = value.indexOf(
',');
1775#if QT_CONFIG(datestring)
1778 dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
1784 int day, year, hour, minute, second;
1787 if (sscanf_s(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, 4, &year, &hour, &minute, &second) == 6)
1791 if (sscanf(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
1793 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
1795 QLocale c = QLocale::c();
1797 QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
1799 dt = c.toDateTime(sansWeekday,
"dd-MMM-yy hh:mm:ss 'GMT'"_L1);
1805 dt.setTimeZone(QTimeZone::UTC);
1811 return QLocale::c().toString(dt.toUTC(), u"ddd, dd MMM yyyy hh:mm:ss 'GMT'").toLatin1();
1815 const QHttpHeaders &headers)
1817 if (headers.isEmpty())
1821 QHash<QByteArray, qsizetype> nameToIndex;
1822 list.reserve(headers.size());
1823 nameToIndex.reserve(headers.size());
1825 for (qsizetype i = 0; i < headers.size(); ++i) {
1826 const auto nameL1 = headers.nameAt(i);
1827 const auto value = headers.valueAt(i);
1829 const bool isSetCookie = nameL1 == QHttpHeaders::wellKnownHeaderName(
1830 QHttpHeaders::WellKnownHeader::SetCookie);
1832 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1833 if (
auto it = nameToIndex.find(name); it != nameToIndex.end()) {
1834 list[it.value()].second += isSetCookie ?
"\n" :
", ";
1835 list[it.value()].second += value;
1837 nameToIndex[name] = list.size();
1838 list.emplaceBack(name, value.toByteArray());
1850 QHttpHeaders headers;
1851 headers.reserve(raw.size());
1853 for (
const auto &[key, value] : raw) {
1854 const bool isSetCookie = key.compare(QHttpHeaders::wellKnownHeaderName(
1855 QHttpHeaders::WellKnownHeader::SetCookie),
1856 Qt::CaseInsensitive) == 0;
1858 for (
auto header : QLatin1StringView(value).tokenize(
'\n'_L1))
1859 headers.append(key, header);
1861 headers.append(key, value);
1871 return std::nullopt;
1874 qint64 res = value.toLongLong(&ok);
1877 return std::nullopt;
1881 const QList<QByteArray> &values)
1884 return std::nullopt;
1886 QList<QNetworkCookie> cookies;
1887 for (
const auto &s : values)
1888 cookies += QNetworkCookie::parseCookies(s);
1890 if (cookies.empty())
1891 return std::nullopt;
1897 return makeCookieHeader(cookies, QNetworkCookie::NameAndValueOnly,
"; ");
1901 const QList<QByteArray> &values)
1904 return std::nullopt;
1906 QList<QNetworkCookie> cookies;
1907 for (
const auto &s : values)
1908 cookies += parseCookieHeader(s);
1910 if (cookies.empty())
1911 return std::nullopt;
1925 QMap<QNetworkRequest::KnownHeaders, QList<QByteArray>> multipleHeadersMap;
1926 for (
int i = 0; i < newHeaders.size(); ++i) {
1927 const auto name = newHeaders.nameAt(i);
1928 const auto value = newHeaders.valueAt(i);
1930 const int parsedKeyAsInt = parseHeaderName(name);
1931 if (parsedKeyAsInt == -1)
1934 const QNetworkRequest::KnownHeaders parsedKey
1935 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1937 auto &list = multipleHeadersMap[parsedKey];
1938 list.append(value.toByteArray());
1941 for (
auto i = multipleHeadersMap.cbegin(), end = multipleHeadersMap.cend(); i != end; ++i)
1942 cookedHeaders.insert(i.key(), parseHeaderValue(i.key(), i.value()));
1947#include "moc_qnetworkrequest.cpp"
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
Combined button and popup list for selecting options.
static int name_to_month(const char *month_str)
static QStringList parseMatchImpl(QByteArrayView raw, T op)
static bool isSetCookie(QByteArrayView name)
static QList< QNetworkCookie > parseCookieHeader(QByteArrayView raw)
static int parseHeaderName(QByteArrayView headerName)
static std::optional< QNetworkRequest::KnownHeaders > toKnownHeader(QHttpHeaders::WellKnownHeader key)
static QVariant parseETag(QByteArrayView raw)
static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, QByteArrayView value)
static QVariant parseHttpDate(QByteArrayView raw)
static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVariant &value)
static QByteArray makeCookieHeader(const QList< QNetworkCookie > &cookies, QNetworkCookie::RawForm type, QByteArrayView separator)
static QStringList parseIfMatch(QByteArrayView raw)
static QStringList parseIfNoneMatch(QByteArrayView raw)
static void setFromRawHeader(QHttpHeaders &headers, HeaderName header, QByteArrayView value)
static std::optional< QHttpHeaders::WellKnownHeader > toWellKnownHeader(QNetworkRequest::KnownHeaders key)
static constexpr HeaderPair knownHeadersArr[]