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
349
350
351
352
353
354
355
356
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
382
383
384
385
386
387
388
389
390
391
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
436
437
438
439
442
443
444
445
446
447
449class QNetworkRequestPrivate:
public QSharedData,
public QNetworkHeadersPrivate
452 static const int maxRedirectCount = 50;
453 inline QNetworkRequestPrivate()
454 : priority(QNetworkRequest::NormalPriority)
456 , sslConfiguration(
nullptr)
458 , maxRedirectsAllowed(maxRedirectCount)
459 { qRegisterMetaType<QNetworkRequest>(); }
460 ~QNetworkRequestPrivate()
463 delete sslConfiguration;
468 QNetworkRequestPrivate(
const QNetworkRequestPrivate &other)
469 : QSharedData(other), QNetworkHeadersPrivate(other)
472 priority = other.priority;
473 maxRedirectsAllowed = other.maxRedirectsAllowed;
475 sslConfiguration =
nullptr;
476 if (other.sslConfiguration)
477 sslConfiguration =
new QSslConfiguration(*other.sslConfiguration);
479 peerVerifyName = other.peerVerifyName;
481 h1Configuration = other.h1Configuration;
482 h2Configuration = other.h2Configuration;
483 decompressedSafetyCheckThreshold = other.decompressedSafetyCheckThreshold;
485 transferTimeout = other.transferTimeout;
486 idleTimeBeforeProbes = other.idleTimeBeforeProbes;
487 intervalBetweenProbes = other.intervalBetweenProbes;
488 probeCount = other.probeCount;
491 inline bool operator==(
const QNetworkRequestPrivate &other)
const
493 return url == other.url &&
494 priority == other.priority &&
495 attributes == other.attributes &&
496 maxRedirectsAllowed == other.maxRedirectsAllowed &&
497 peerVerifyName == other.peerVerifyName
499 && h1Configuration == other.h1Configuration
500 && h2Configuration == other.h2Configuration
501 && decompressedSafetyCheckThreshold == other.decompressedSafetyCheckThreshold
503 && transferTimeout == other.transferTimeout
504 && QHttpHeadersHelper::compareStrict(httpHeaders, other.httpHeaders)
505 && idleTimeBeforeProbes == other.idleTimeBeforeProbes
506 && intervalBetweenProbes == other.intervalBetweenProbes
507 && probeCount == other.probeCount;
513 QNetworkRequest::Priority priority;
515 mutable QSslConfiguration *sslConfiguration;
517 int maxRedirectsAllowed;
518 QString peerVerifyName;
520 QHttp1Configuration h1Configuration;
521 QHttp2Configuration h2Configuration;
522 qint64 decompressedSafetyCheckThreshold = 10ll * 1024ll * 1024ll;
524 std::chrono::milliseconds transferTimeout = 0ms;
525 std::chrono::duration<
int> idleTimeBeforeProbes{0};
526 std::chrono::duration<
int> intervalBetweenProbes{0};
531
532
533
534
535
536QNetworkRequest::QNetworkRequest()
537 : d(
new QNetworkRequestPrivate)
545 d->h2Configuration.setStreamReceiveWindowSize(Http2::qtDefaultStreamReceiveWindowSize);
546 d->h2Configuration.setSessionReceiveWindowSize(Http2::maxSessionReceiveWindowSize);
547 d->h2Configuration.setServerPushEnabled(
false);
552
553
554
555
556
557QNetworkRequest::QNetworkRequest(
const QUrl &url)
564
565
566QNetworkRequest::QNetworkRequest(
const QNetworkRequest &other)
572
573
574QNetworkRequest::~QNetworkRequest()
581
582
583
584
585
586bool QNetworkRequest::operator==(
const QNetworkRequest &other)
const
588 return d == other.d || *d == *other.d;
592
593
594
595
596
597
600
601
602QNetworkRequest &QNetworkRequest::operator=(
const QNetworkRequest &other)
609
610
611
612
615
616
617
618
619QUrl QNetworkRequest::url()
const
625
626
627
628
629void QNetworkRequest::setUrl(
const QUrl &url)
635
636
637
638
639
640
641QHttpHeaders QNetworkRequest::headers()
const
647
648
649
650
651
652
653
654
655
656
657void QNetworkRequest::setHeaders(QHttpHeaders &&newHeaders)
659 d->setHeaders(std::move(newHeaders));
663
664
665
666void QNetworkRequest::setHeaders(
const QHttpHeaders &newHeaders)
668 d->setHeaders(newHeaders);
672
673
674
675
676
677
678QVariant QNetworkRequest::header(KnownHeaders header)
const
680 return d->cookedHeaders.value(header);
684
685
686
687
688
689
690void QNetworkRequest::setHeader(KnownHeaders header,
const QVariant &value)
692 d->setCookedHeader(header, value);
696
697
698
699
700
701
702bool QNetworkRequest::hasRawHeader(QAnyStringView headerName)
const
704 return d->headers().contains(headerName);
708
709
710
711
712
713
714
715
716
717
718QByteArray QNetworkRequest::rawHeader(QAnyStringView headerName)
const
720 return d->rawHeader(headerName);
724
725
726
727
728
729QList<QByteArray> QNetworkRequest::rawHeaderList()
const
731 return d->rawHeadersKeys();
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758void QNetworkRequest::setRawHeader(
const QByteArray &headerName,
const QByteArray &headerValue)
760 d->setRawHeader(headerName, headerValue);
764
765
766
767
768
769
770
771
772QVariant QNetworkRequest::attribute(Attribute code,
const QVariant &defaultValue)
const
774 return d->attributes.value(code, defaultValue);
778
779
780
781
782
783
784
785void QNetworkRequest::setAttribute(Attribute code,
const QVariant &value)
788 d->attributes.insert(code, value);
790 d->attributes.remove(code);
795
796
797
798
799
800QSslConfiguration QNetworkRequest::sslConfiguration()
const
802 if (!d->sslConfiguration)
803 d->sslConfiguration =
new QSslConfiguration(QSslConfiguration::defaultConfiguration());
804 return *d->sslConfiguration;
808
809
810
811
812
813
814
815void QNetworkRequest::setSslConfiguration(
const QSslConfiguration &config)
817 if (!d->sslConfiguration)
818 d->sslConfiguration =
new QSslConfiguration(config);
820 *d->sslConfiguration = config;
825
826
827
828
829
830
831
832
833
834
835void QNetworkRequest::setOriginatingObject(QObject *object)
837 d->originatingObject = object;
841
842
843
844
845
846
847
848
849QObject *QNetworkRequest::originatingObject()
const
851 return d->originatingObject.data();
855
856
857
858
859
860
861QNetworkRequest::Priority QNetworkRequest::priority()
const
867
868
869
870
871
872
873
874
875
878
879
880
881
882
883
884
885
886
887
888void QNetworkRequest::setPriority(Priority priority)
890 d->priority = priority;
894
895
896
897
898
899
900
901int QNetworkRequest::maximumRedirectsAllowed()
const
903 return d->maxRedirectsAllowed;
907
908
909
910
911
912
913
914void QNetworkRequest::setMaximumRedirectsAllowed(
int maxRedirectsAllowed)
916 d->maxRedirectsAllowed = maxRedirectsAllowed;
920
921
922
923
924
925
926
927QString QNetworkRequest::peerVerifyName()
const
929 return d->peerVerifyName;
933
934
935
936
937
938
939
940void QNetworkRequest::setPeerVerifyName(
const QString &peerName)
942 d->peerVerifyName = peerName;
947
948
949
950
951
952
953
954QHttp1Configuration QNetworkRequest::http1Configuration()
const
956 return d->h1Configuration;
959
960
961
962
963
964
965void QNetworkRequest::setHttp1Configuration(
const QHttp1Configuration &configuration)
967 d->h1Configuration = configuration;
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991QHttp2Configuration QNetworkRequest::http2Configuration()
const
993 return d->h2Configuration;
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009void QNetworkRequest::setHttp2Configuration(
const QHttp2Configuration &configuration)
1011 d->h2Configuration = configuration;
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024qint64 QNetworkRequest::decompressedSafetyCheckThreshold()
const
1026 return d->decompressedSafetyCheckThreshold;
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060void QNetworkRequest::setDecompressedSafetyCheckThreshold(qint64 threshold)
1062 d->decompressedSafetyCheckThreshold = threshold;
1067
1068
1069
1070
1071
1072
1073
1074
1076std::chrono::seconds QNetworkRequest::tcpKeepAliveIdleTimeBeforeProbes()
const
1078 return d->idleTimeBeforeProbes;
1082
1083
1084
1085
1086
1087
1088
1089
1090
1092void QNetworkRequest::doSetIdleTimeBeforeProbes(std::chrono::duration<
int> seconds)
1094 d->idleTimeBeforeProbes = seconds;
1098
1099
1100
1101
1102
1103
1104
1106std::chrono::seconds QNetworkRequest::tcpKeepAliveIntervalBetweenProbes()
const
1108 return d->intervalBetweenProbes;
1112
1113
1114
1115
1116
1117
1118
1119
1121void QNetworkRequest::doSetIntervalBetweenProbes(std::chrono::duration<
int> seconds)
1123 d->intervalBetweenProbes = seconds;
1127
1128
1129
1130
1131
1132
1133
1134
1136int QNetworkRequest::tcpKeepAliveProbeCount()
const
1138 return d->probeCount;
1142
1143
1144
1145
1146
1147
1148
1149
1151void QNetworkRequest::setTcpKeepAliveProbeCount(
int probes)
1153 d->probeCount = probes;
1156#if QT_CONFIG(http) || defined (Q_OS_WASM)
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1170
1171
1172
1173
1174
1175
1176
1177
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189std::chrono::milliseconds QNetworkRequest::transferTimeoutAsDuration()
const
1191 return d->transferTimeout;
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208void QNetworkRequest::setTransferTimeout(std::chrono::milliseconds duration)
1210 d->transferTimeout = duration;
1217 QHttpHeaders::WellKnownHeader wellKnownHeader;
1218 QNetworkRequest::KnownHeaders knownHeader;
1221constexpr bool operator<(
const HeaderPair &lhs,
const HeaderPair &rhs)
1223 return lhs.wellKnownHeader < rhs.wellKnownHeader;
1226constexpr bool operator<(
const HeaderPair &lhs, QHttpHeaders::WellKnownHeader rhs)
1228 return lhs.wellKnownHeader < rhs;
1231constexpr bool operator<(QHttpHeaders::WellKnownHeader lhs,
const HeaderPair &rhs)
1233 return lhs < rhs.wellKnownHeader;
1239 { QHttpHeaders::WellKnownHeader::ContentDisposition, QNetworkRequest::KnownHeaders::ContentDispositionHeader },
1240 { QHttpHeaders::WellKnownHeader::ContentLength, QNetworkRequest::KnownHeaders::ContentLengthHeader },
1241 { QHttpHeaders::WellKnownHeader::ContentType, QNetworkRequest::KnownHeaders::ContentTypeHeader },
1242 { QHttpHeaders::WellKnownHeader::Cookie, QNetworkRequest::KnownHeaders::CookieHeader },
1243 { QHttpHeaders::WellKnownHeader::ETag, QNetworkRequest::KnownHeaders::ETagHeader },
1244 { QHttpHeaders::WellKnownHeader::IfMatch , QNetworkRequest::KnownHeaders::IfMatchHeader },
1245 { QHttpHeaders::WellKnownHeader::IfModifiedSince, QNetworkRequest::KnownHeaders::IfModifiedSinceHeader },
1246 { QHttpHeaders::WellKnownHeader::IfNoneMatch, QNetworkRequest::KnownHeaders::IfNoneMatchHeader },
1247 { QHttpHeaders::WellKnownHeader::LastModified, QNetworkRequest::KnownHeaders::LastModifiedHeader},
1248 { QHttpHeaders::WellKnownHeader::Location, QNetworkRequest::KnownHeaders::LocationHeader},
1249 { QHttpHeaders::WellKnownHeader::Server, QNetworkRequest::KnownHeaders::ServerHeader },
1250 { QHttpHeaders::WellKnownHeader::SetCookie, QNetworkRequest::KnownHeaders::SetCookieHeader },
1251 { QHttpHeaders::WellKnownHeader::UserAgent, QNetworkRequest::KnownHeaders::UserAgentHeader }
1254static_assert(std::size(knownHeadersArr) == size_t(QNetworkRequest::KnownHeaders::NumKnownHeaders));
1261 return std::nullopt;
1262 return it->knownHeader;
1267 auto pred = [key](
const HeaderPair &pair) {
return pair.knownHeader == key; };
1270 return std::nullopt;
1271 return it->wellKnownHeader;
1275 QNetworkCookie::RawForm type,
1276 QByteArrayView separator)
1279 for (
const QNetworkCookie &cookie : cookies) {
1280 result += cookie.toRawForm(type);
1281 result += separator;
1283 if (!result.isEmpty())
1284 result.chop(separator.size());
1289 QByteArrayView separator)
1291 const QList<QNetworkCookie> *cookies = get_if<QList<QNetworkCookie>>(&value);
1294 return makeCookieHeader(*cookies, type, separator);
1300 case QNetworkRequest::ContentTypeHeader:
1301 case QNetworkRequest::ContentLengthHeader:
1302 case QNetworkRequest::ContentDispositionHeader:
1303 case QNetworkRequest::UserAgentHeader:
1304 case QNetworkRequest::ServerHeader:
1305 case QNetworkRequest::ETagHeader:
1306 case QNetworkRequest::IfMatchHeader:
1307 case QNetworkRequest::IfNoneMatchHeader:
1308 return value.toByteArray();
1310 case QNetworkRequest::LocationHeader:
1311 switch (value.userType()) {
1312 case QMetaType::QUrl:
1313 return value.toUrl().toEncoded();
1316 return value.toByteArray();
1319 case QNetworkRequest::LastModifiedHeader:
1320 case QNetworkRequest::IfModifiedSinceHeader:
1321 switch (value.userType()) {
1323 case QMetaType::QDate:
1324 return QNetworkHeadersPrivate::toHttpDate(value.toDate().startOfDay(QTimeZone::UTC));
1325 case QMetaType::QDateTime:
1326 return QNetworkHeadersPrivate::toHttpDate(value.toDateTime());
1329 return value.toByteArray();
1332 case QNetworkRequest::CookieHeader:
1333 return makeCookieHeader(value, QNetworkCookie::NameAndValueOnly,
"; ");
1335 case QNetworkRequest::SetCookieHeader:
1336 return makeCookieHeader(value, QNetworkCookie::Full,
", ");
1339 Q_UNREACHABLE_RETURN({});
1345 if (headerName.isEmpty())
1348 auto is = [headerName](QByteArrayView what) {
1349 return headerName.compare(what, Qt::CaseInsensitive) == 0;
1352 switch (QtMiscUtils::toAsciiLower(headerName.front())) {
1354 if (is(
"content-type"))
1355 return QNetworkRequest::ContentTypeHeader;
1356 else if (is(
"content-length"))
1357 return QNetworkRequest::ContentLengthHeader;
1358 else if (is(
"cookie"))
1359 return QNetworkRequest::CookieHeader;
1360 else if (is(
"content-disposition"))
1361 return QNetworkRequest::ContentDispositionHeader;
1366 return QNetworkRequest::ETagHeader;
1370 if (is(
"if-modified-since"))
1371 return QNetworkRequest::IfModifiedSinceHeader;
1373 return QNetworkRequest::IfMatchHeader;
1374 if (is(
"if-none-match"))
1375 return QNetworkRequest::IfNoneMatchHeader;
1380 return QNetworkRequest::LocationHeader;
1381 else if (is(
"last-modified"))
1382 return QNetworkRequest::LastModifiedHeader;
1386 if (is(
"set-cookie"))
1387 return QNetworkRequest::SetCookieHeader;
1388 else if (is(
"server"))
1389 return QNetworkRequest::ServerHeader;
1393 if (is(
"user-agent"))
1394 return QNetworkRequest::UserAgentHeader;
1403 QDateTime dt = QNetworkHeadersPrivate::fromHttpDate(raw);
1411 QList<QNetworkCookie> result;
1412 for (
auto cookie : QLatin1StringView(raw).tokenize(
';'_L1)) {
1413 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed());
1414 if (parsed.size() != 1)
1425 const QByteArrayView trimmed = raw.trimmed();
1426 if (!trimmed.startsWith(
'"') && !trimmed.startsWith(R"(W/")"))
1429 if (!trimmed.endsWith(
'"'))
1432 return QString::fromLatin1(trimmed);
1438 const QByteArrayView trimmedRaw = raw.trimmed();
1439 if (trimmedRaw ==
"*")
1440 return QStringList(QStringLiteral(
"*"));
1443 for (
auto &element : QLatin1StringView(trimmedRaw).tokenize(
','_L1)) {
1444 if (
const auto trimmed = element.trimmed(); op(trimmed))
1445 tags += QString::fromLatin1(trimmed);
1453 return parseMatchImpl(raw, [](QByteArrayView element) {
1454 return element.startsWith(
'"') && element.endsWith(
'"');
1460 return parseMatchImpl(raw, [](QByteArrayView element) {
1461 return (element.startsWith(
'"') || element.startsWith(R"(W/")")) && element.endsWith(
'"');
1470 case QNetworkRequest::UserAgentHeader:
1471 case QNetworkRequest::ServerHeader:
1472 case QNetworkRequest::ContentTypeHeader:
1473 case QNetworkRequest::ContentDispositionHeader:
1475 return QString::fromLatin1(value);
1477 case QNetworkRequest::ContentLengthHeader: {
1479 qint64 result = QByteArrayView(value).trimmed().toLongLong(&ok);
1485 case QNetworkRequest::LocationHeader: {
1486 QUrl result = QUrl::fromEncoded(value, QUrl::StrictMode);
1487 if (result.isValid() && !result.scheme().isEmpty())
1492 case QNetworkRequest::LastModifiedHeader:
1493 case QNetworkRequest::IfModifiedSinceHeader:
1494 return parseHttpDate(value);
1496 case QNetworkRequest::ETagHeader:
1497 return parseETag(value);
1499 case QNetworkRequest::IfMatchHeader:
1500 return parseIfMatch(value);
1502 case QNetworkRequest::IfNoneMatchHeader:
1503 return parseIfNoneMatch(value);
1505 case QNetworkRequest::CookieHeader:
1506 return QVariant::fromValue(parseCookieHeader(value));
1508 case QNetworkRequest::SetCookieHeader:
1509 return QVariant::fromValue(QNetworkCookie::parseCookies(value));
1512 Q_UNREACHABLE_RETURN({});
1523 case QNetworkRequest::IfMatchHeader: {
1525 for (
const auto &val : values)
1526 res << parseIfMatch(val);
1529 case QNetworkRequest::IfNoneMatchHeader: {
1531 for (
const auto &val : values)
1532 res << parseIfNoneMatch(val);
1535 case QNetworkRequest::CookieHeader: {
1536 auto listOpt = QNetworkHeadersPrivate::toCookieList(values);
1537 return listOpt.has_value() ? QVariant::fromValue(listOpt.value()) : QVariant();
1539 case QNetworkRequest::SetCookieHeader: {
1540 QList<QNetworkCookie> res;
1541 for (
const auto &val : values)
1542 res << QNetworkCookie::parseCookies(val);
1543 return QVariant::fromValue(res);
1546 return parseHeaderValue(header, values.first());
1553 return name.compare(QHttpHeaders::wellKnownHeaderName(QHttpHeaders::WellKnownHeader::SetCookie),
1554 Qt::CaseInsensitive) == 0;
1559 return name == QHttpHeaders::WellKnownHeader::SetCookie;
1562template<
class HeaderName>
1564 QByteArrayView value)
1566 headers.removeAll(header);
1572 if (isSetCookie(header)) {
1573 for (
auto cookie : QLatin1StringView(value).tokenize(
'\n'_L1))
1574 headers.append(QHttpHeaders::WellKnownHeader::SetCookie, cookie);
1576 headers.append(header, value);
1585 rawHeaderCache
.headersList = fromHttpToRaw(httpHeaders);
1592 if (httpHeaders.isEmpty())
1595 QList<QByteArray> result;
1596 result.reserve(httpHeaders.size());
1597 QDuplicateTracker<QByteArray> seen(httpHeaders.size());
1599 for (qsizetype i = 0; i < httpHeaders.size(); i++) {
1600 const auto nameL1 = httpHeaders.nameAt(i);
1601 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1602 if (seen.hasSeen(name))
1613 QByteArrayView setCookieStr = QHttpHeaders::wellKnownHeaderName(
1614 QHttpHeaders::WellKnownHeader::SetCookie);
1615 if (QAnyStringView::compare(headerName, setCookieStr, Qt::CaseInsensitive) != 0)
1616 return httpHeaders.combinedValue(headerName);
1619 const char* separator =
"";
1620 for (qsizetype i = 0; i < httpHeaders.size(); ++i) {
1621 if (QAnyStringView::compare(httpHeaders.nameAt(i), headerName, Qt::CaseInsensitive) == 0) {
1622 result.append(separator);
1623 result.append(httpHeaders.valueAt(i));
1636 setFromRawHeader(httpHeaders, key, value);
1637 parseAndSetHeader(key, value);
1639 invalidateHeaderCache();
1643 const QVariant &value)
1645 const auto wellKnownOpt = toWellKnownHeader(header);
1646 if (!wellKnownOpt) {
1648 qWarning(
"QNetworkRequest::setHeader: invalid header value KnownHeader(%d) received", header);
1652 if (value.isNull()) {
1653 httpHeaders.removeAll(wellKnownOpt.value());
1656 QByteArray rawValue = headerValue(header, value);
1657 if (rawValue.isEmpty()) {
1658 qWarning(
"QNetworkRequest::setHeader: QVariant of type %s cannot be used with header %s",
1660 QHttpHeaders::wellKnownHeaderName(wellKnownOpt.value()).constData());
1664 setFromRawHeader(httpHeaders, wellKnownOpt.value(), rawValue);
1668 invalidateHeaderCache();
1678 httpHeaders = newHeaders;
1679 setCookedFromHttp(httpHeaders);
1680 invalidateHeaderCache();
1685 httpHeaders = std::move(newHeaders);
1686 setCookedFromHttp(httpHeaders);
1687 invalidateHeaderCache();
1692 httpHeaders.replaceOrAppend(name, value);
1695 const auto knownHeaderOpt = toKnownHeader(name);
1697 parseAndSetHeader(knownHeaderOpt.value(), value);
1699 invalidateHeaderCache();
1704 httpHeaders.clear();
1706 invalidateHeaderCache();
1712 const int parsedKeyAsInt = parseHeaderName(key);
1713 if (parsedKeyAsInt != -1) {
1714 const QNetworkRequest::KnownHeaders parsedKey
1715 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1716 parseAndSetHeader(parsedKey, value);
1721 QByteArrayView value)
1723 if (value.isNull()) {
1725 }
else if (key == QNetworkRequest::ContentLengthHeader
1726 && cookedHeaders.contains(QNetworkRequest::ContentLengthHeader)) {
1739 switch (month_str[0]) {
1741 switch (month_str[1]) {
1745 switch (month_str[2] ) {
1756 switch (month_str[2] ) {
1764 switch (month_str[1]) {
1792 int pos = value.indexOf(
',');
1794#if QT_CONFIG(datestring)
1797 dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
1803 int day, year, hour, minute, second;
1806 if (sscanf_s(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, 4, &year, &hour, &minute, &second) == 6)
1810 if (sscanf(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
1812 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
1814 QLocale c = QLocale::c();
1816 QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
1818 dt = c.toDateTime(sansWeekday,
"dd-MMM-yy hh:mm:ss 'GMT'"_L1);
1824 dt.setTimeZone(QTimeZone::UTC);
1830 return QLocale::c().toString(dt.toUTC(), u"ddd, dd MMM yyyy hh:mm:ss 'GMT'").toLatin1();
1834 const QHttpHeaders &headers)
1836 if (headers.isEmpty())
1840 QHash<QByteArray, qsizetype> nameToIndex;
1841 list.reserve(headers.size());
1842 nameToIndex.reserve(headers.size());
1844 for (qsizetype i = 0; i < headers.size(); ++i) {
1845 const auto nameL1 = headers.nameAt(i);
1846 const auto value = headers.valueAt(i);
1848 const bool isSetCookie = nameL1 == QHttpHeaders::wellKnownHeaderName(
1849 QHttpHeaders::WellKnownHeader::SetCookie);
1851 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1852 if (
auto it = nameToIndex.find(name); it != nameToIndex.end()) {
1853 list[it.value()].second += isSetCookie ?
"\n" :
", ";
1854 list[it.value()].second += value;
1856 nameToIndex[name] = list.size();
1857 list.emplaceBack(name, value.toByteArray());
1869 QHttpHeaders headers;
1870 headers.reserve(raw.size());
1872 for (
const auto &[key, value] : raw) {
1873 const bool isSetCookie = key.compare(QHttpHeaders::wellKnownHeaderName(
1874 QHttpHeaders::WellKnownHeader::SetCookie),
1875 Qt::CaseInsensitive) == 0;
1877 for (
auto header : QLatin1StringView(value).tokenize(
'\n'_L1))
1878 headers.append(key, header);
1880 headers.append(key, value);
1890 return std::nullopt;
1893 qint64 res = value.toLongLong(&ok);
1896 return std::nullopt;
1900 const QList<QByteArray> &values)
1903 return std::nullopt;
1905 QList<QNetworkCookie> cookies;
1906 for (
const auto &s : values)
1907 cookies += QNetworkCookie::parseCookies(s);
1909 if (cookies.empty())
1910 return std::nullopt;
1916 return makeCookieHeader(cookies, QNetworkCookie::NameAndValueOnly,
"; ");
1920 const QList<QByteArray> &values)
1923 return std::nullopt;
1925 QList<QNetworkCookie> cookies;
1926 for (
const auto &s : values)
1927 cookies += parseCookieHeader(s);
1929 if (cookies.empty())
1930 return std::nullopt;
1944 QMap<QNetworkRequest::KnownHeaders, QList<QByteArray>> multipleHeadersMap;
1945 for (
int i = 0; i < newHeaders.size(); ++i) {
1946 const auto name = newHeaders.nameAt(i);
1947 const auto value = newHeaders.valueAt(i);
1949 const int parsedKeyAsInt = parseHeaderName(name);
1950 if (parsedKeyAsInt == -1)
1953 const QNetworkRequest::KnownHeaders parsedKey
1954 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1956 auto &list = multipleHeadersMap[parsedKey];
1957 list.append(value.toByteArray());
1960 for (
auto i = multipleHeadersMap.cbegin(), end = multipleHeadersMap.cend(); i != end; ++i)
1961 cookedHeaders.insert(i.key(), parseHeaderValue(i.key(), i.value()));
1966#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[]