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
1051void QNetworkRequest::setDecompressedSafetyCheckThreshold(qint64 threshold)
1053 d->decompressedSafetyCheckThreshold = threshold;
1058
1059
1060
1061
1062
1063
1064
1065
1067std::chrono::seconds QNetworkRequest::tcpKeepAliveIdleTimeBeforeProbes()
const
1069 return d->idleTimeBeforeProbes;
1073
1074
1075
1076
1077
1078
1079
1080
1081
1083void QNetworkRequest::doSetIdleTimeBeforeProbes(std::chrono::duration<
int> seconds)
1085 d->idleTimeBeforeProbes = seconds;
1089
1090
1091
1092
1093
1094
1095
1097std::chrono::seconds QNetworkRequest::tcpKeepAliveIntervalBetweenProbes()
const
1099 return d->intervalBetweenProbes;
1103
1104
1105
1106
1107
1108
1109
1110
1112void QNetworkRequest::doSetIntervalBetweenProbes(std::chrono::duration<
int> seconds)
1114 d->intervalBetweenProbes = seconds;
1118
1119
1120
1121
1122
1123
1124
1125
1127int QNetworkRequest::tcpKeepAliveProbeCount()
const
1129 return d->probeCount;
1133
1134
1135
1136
1137
1138
1139
1140
1142void QNetworkRequest::setTcpKeepAliveProbeCount(
int probes)
1144 d->probeCount = probes;
1147#if QT_CONFIG(http) || defined (Q_OS_WASM)
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1161
1162
1163
1164
1165
1166
1167
1168
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180std::chrono::milliseconds QNetworkRequest::transferTimeoutAsDuration()
const
1182 return d->transferTimeout;
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199void QNetworkRequest::setTransferTimeout(std::chrono::milliseconds duration)
1201 d->transferTimeout = duration;
1208 QHttpHeaders::WellKnownHeader wellKnownHeader;
1209 QNetworkRequest::KnownHeaders knownHeader;
1212constexpr bool operator<(
const HeaderPair &lhs,
const HeaderPair &rhs)
1214 return lhs.wellKnownHeader < rhs.wellKnownHeader;
1217constexpr bool operator<(
const HeaderPair &lhs, QHttpHeaders::WellKnownHeader rhs)
1219 return lhs.wellKnownHeader < rhs;
1222constexpr bool operator<(QHttpHeaders::WellKnownHeader lhs,
const HeaderPair &rhs)
1224 return lhs < rhs.wellKnownHeader;
1230 { QHttpHeaders::WellKnownHeader::ContentDisposition, QNetworkRequest::KnownHeaders::ContentDispositionHeader },
1231 { QHttpHeaders::WellKnownHeader::ContentLength, QNetworkRequest::KnownHeaders::ContentLengthHeader },
1232 { QHttpHeaders::WellKnownHeader::ContentType, QNetworkRequest::KnownHeaders::ContentTypeHeader },
1233 { QHttpHeaders::WellKnownHeader::Cookie, QNetworkRequest::KnownHeaders::CookieHeader },
1234 { QHttpHeaders::WellKnownHeader::ETag, QNetworkRequest::KnownHeaders::ETagHeader },
1235 { QHttpHeaders::WellKnownHeader::IfMatch , QNetworkRequest::KnownHeaders::IfMatchHeader },
1236 { QHttpHeaders::WellKnownHeader::IfModifiedSince, QNetworkRequest::KnownHeaders::IfModifiedSinceHeader },
1237 { QHttpHeaders::WellKnownHeader::IfNoneMatch, QNetworkRequest::KnownHeaders::IfNoneMatchHeader },
1238 { QHttpHeaders::WellKnownHeader::LastModified, QNetworkRequest::KnownHeaders::LastModifiedHeader},
1239 { QHttpHeaders::WellKnownHeader::Location, QNetworkRequest::KnownHeaders::LocationHeader},
1240 { QHttpHeaders::WellKnownHeader::Server, QNetworkRequest::KnownHeaders::ServerHeader },
1241 { QHttpHeaders::WellKnownHeader::SetCookie, QNetworkRequest::KnownHeaders::SetCookieHeader },
1242 { QHttpHeaders::WellKnownHeader::UserAgent, QNetworkRequest::KnownHeaders::UserAgentHeader }
1245static_assert(std::size(knownHeadersArr) == size_t(QNetworkRequest::KnownHeaders::NumKnownHeaders));
1251 if (it == std::end(knownHeadersArr) || key < *it)
1252 return std::nullopt;
1253 return it->knownHeader;
1258 auto pred = [key](
const HeaderPair &pair) {
return pair.knownHeader == key; };
1260 if (it == std::end(knownHeadersArr))
1261 return std::nullopt;
1262 return it->wellKnownHeader;
1266 QNetworkCookie::RawForm type,
1267 QByteArrayView separator)
1270 for (
const QNetworkCookie &cookie : cookies) {
1271 result += cookie.toRawForm(type);
1272 result += separator;
1274 if (!result.isEmpty())
1275 result.chop(separator.size());
1280 QByteArrayView separator)
1282 const QList<QNetworkCookie> *cookies = get_if<QList<QNetworkCookie>>(&value);
1285 return makeCookieHeader(*cookies, type, separator);
1291 case QNetworkRequest::ContentTypeHeader:
1292 case QNetworkRequest::ContentLengthHeader:
1293 case QNetworkRequest::ContentDispositionHeader:
1294 case QNetworkRequest::UserAgentHeader:
1295 case QNetworkRequest::ServerHeader:
1296 case QNetworkRequest::ETagHeader:
1297 case QNetworkRequest::IfMatchHeader:
1298 case QNetworkRequest::IfNoneMatchHeader:
1299 return value.toByteArray();
1301 case QNetworkRequest::LocationHeader:
1302 switch (value.userType()) {
1303 case QMetaType::QUrl:
1304 return value.toUrl().toEncoded();
1307 return value.toByteArray();
1310 case QNetworkRequest::LastModifiedHeader:
1311 case QNetworkRequest::IfModifiedSinceHeader:
1312 switch (value.userType()) {
1314 case QMetaType::QDate:
1315 return QNetworkHeadersPrivate::toHttpDate(value.toDate().startOfDay(QTimeZone::UTC));
1316 case QMetaType::QDateTime:
1317 return QNetworkHeadersPrivate::toHttpDate(value.toDateTime());
1320 return value.toByteArray();
1323 case QNetworkRequest::CookieHeader:
1324 return makeCookieHeader(value, QNetworkCookie::NameAndValueOnly,
"; ");
1326 case QNetworkRequest::SetCookieHeader:
1327 return makeCookieHeader(value, QNetworkCookie::Full,
", ");
1330 Q_UNREACHABLE_RETURN({});
1336 if (headerName.isEmpty())
1339 auto is = [headerName](QByteArrayView what) {
1340 return headerName.compare(what, Qt::CaseInsensitive) == 0;
1343 switch (QtMiscUtils::toAsciiLower(headerName.front())) {
1345 if (is(
"content-type"))
1346 return QNetworkRequest::ContentTypeHeader;
1347 else if (is(
"content-length"))
1348 return QNetworkRequest::ContentLengthHeader;
1349 else if (is(
"cookie"))
1350 return QNetworkRequest::CookieHeader;
1351 else if (is(
"content-disposition"))
1352 return QNetworkRequest::ContentDispositionHeader;
1357 return QNetworkRequest::ETagHeader;
1361 if (is(
"if-modified-since"))
1362 return QNetworkRequest::IfModifiedSinceHeader;
1364 return QNetworkRequest::IfMatchHeader;
1365 if (is(
"if-none-match"))
1366 return QNetworkRequest::IfNoneMatchHeader;
1371 return QNetworkRequest::LocationHeader;
1372 else if (is(
"last-modified"))
1373 return QNetworkRequest::LastModifiedHeader;
1377 if (is(
"set-cookie"))
1378 return QNetworkRequest::SetCookieHeader;
1379 else if (is(
"server"))
1380 return QNetworkRequest::ServerHeader;
1384 if (is(
"user-agent"))
1385 return QNetworkRequest::UserAgentHeader;
1394 QDateTime dt = QNetworkHeadersPrivate::fromHttpDate(raw);
1402 QList<QNetworkCookie> result;
1403 for (
auto cookie : QLatin1StringView(raw).tokenize(
';'_L1)) {
1404 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed());
1405 if (parsed.size() != 1)
1416 const QByteArrayView trimmed = raw.trimmed();
1417 if (!trimmed.startsWith(
'"') && !trimmed.startsWith(R"(W/")"))
1420 if (!trimmed.endsWith(
'"'))
1423 return QString::fromLatin1(trimmed);
1429 const QByteArrayView trimmedRaw = raw.trimmed();
1430 if (trimmedRaw ==
"*")
1431 return QStringList(QStringLiteral(
"*"));
1434 for (
auto &element : QLatin1StringView(trimmedRaw).tokenize(
','_L1)) {
1435 if (
const auto trimmed = element.trimmed(); op(trimmed))
1436 tags += QString::fromLatin1(trimmed);
1444 return parseMatchImpl(raw, [](QByteArrayView element) {
1445 return element.startsWith(
'"') && element.endsWith(
'"');
1451 return parseMatchImpl(raw, [](QByteArrayView element) {
1452 return (element.startsWith(
'"') || element.startsWith(R"(W/")")) && element.endsWith(
'"');
1461 case QNetworkRequest::UserAgentHeader:
1462 case QNetworkRequest::ServerHeader:
1463 case QNetworkRequest::ContentTypeHeader:
1464 case QNetworkRequest::ContentDispositionHeader:
1466 return QString::fromLatin1(value);
1468 case QNetworkRequest::ContentLengthHeader: {
1470 qint64 result = QByteArrayView(value).trimmed().toLongLong(&ok);
1476 case QNetworkRequest::LocationHeader: {
1477 QUrl result = QUrl::fromEncoded(value, QUrl::StrictMode);
1478 if (result.isValid() && !result.scheme().isEmpty())
1483 case QNetworkRequest::LastModifiedHeader:
1484 case QNetworkRequest::IfModifiedSinceHeader:
1485 return parseHttpDate(value);
1487 case QNetworkRequest::ETagHeader:
1488 return parseETag(value);
1490 case QNetworkRequest::IfMatchHeader:
1491 return parseIfMatch(value);
1493 case QNetworkRequest::IfNoneMatchHeader:
1494 return parseIfNoneMatch(value);
1496 case QNetworkRequest::CookieHeader:
1497 return QVariant::fromValue(parseCookieHeader(value));
1499 case QNetworkRequest::SetCookieHeader:
1500 return QVariant::fromValue(QNetworkCookie::parseCookies(value));
1503 Q_UNREACHABLE_RETURN({});
1514 case QNetworkRequest::IfMatchHeader: {
1516 for (
const auto &val : values)
1517 res << parseIfMatch(val);
1520 case QNetworkRequest::IfNoneMatchHeader: {
1522 for (
const auto &val : values)
1523 res << parseIfNoneMatch(val);
1526 case QNetworkRequest::CookieHeader: {
1527 auto listOpt = QNetworkHeadersPrivate::toCookieList(values);
1528 return listOpt.has_value() ? QVariant::fromValue(listOpt.value()) : QVariant();
1530 case QNetworkRequest::SetCookieHeader: {
1531 QList<QNetworkCookie> res;
1532 for (
const auto &val : values)
1533 res << QNetworkCookie::parseCookies(val);
1534 return QVariant::fromValue(res);
1537 return parseHeaderValue(header, values.first());
1544 return name.compare(QHttpHeaders::wellKnownHeaderName(QHttpHeaders::WellKnownHeader::SetCookie),
1545 Qt::CaseInsensitive) == 0;
1550 return name == QHttpHeaders::WellKnownHeader::SetCookie;
1553template<
class HeaderName>
1555 QByteArrayView value)
1557 headers.removeAll(header);
1563 if (isSetCookie(header)) {
1564 for (
auto cookie : QLatin1StringView(value).tokenize(
'\n'_L1))
1565 headers.append(QHttpHeaders::WellKnownHeader::SetCookie, cookie);
1567 headers.append(header, value);
1576 rawHeaderCache
.headersList = fromHttpToRaw(httpHeaders);
1583 if (httpHeaders.isEmpty())
1586 QList<QByteArray> result;
1587 result.reserve(httpHeaders.size());
1588 QDuplicateTracker<QByteArray> seen(httpHeaders.size());
1590 for (qsizetype i = 0; i < httpHeaders.size(); i++) {
1591 const auto nameL1 = httpHeaders.nameAt(i);
1592 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1593 if (seen.hasSeen(name))
1604 QByteArrayView setCookieStr = QHttpHeaders::wellKnownHeaderName(
1605 QHttpHeaders::WellKnownHeader::SetCookie);
1606 if (QAnyStringView::compare(headerName, setCookieStr, Qt::CaseInsensitive) != 0)
1607 return httpHeaders.combinedValue(headerName);
1610 const char* separator =
"";
1611 for (qsizetype i = 0; i < httpHeaders.size(); ++i) {
1612 if (QAnyStringView::compare(httpHeaders.nameAt(i), headerName, Qt::CaseInsensitive) == 0) {
1613 result.append(separator);
1614 result.append(httpHeaders.valueAt(i));
1627 setFromRawHeader(httpHeaders, key, value);
1628 parseAndSetHeader(key, value);
1630 invalidateHeaderCache();
1634 const QVariant &value)
1636 const auto wellKnownOpt = toWellKnownHeader(header);
1637 if (!wellKnownOpt) {
1639 qWarning(
"QNetworkRequest::setHeader: invalid header value KnownHeader(%d) received", header);
1643 if (value.isNull()) {
1644 httpHeaders.removeAll(wellKnownOpt.value());
1647 QByteArray rawValue = headerValue(header, value);
1648 if (rawValue.isEmpty()) {
1649 qWarning(
"QNetworkRequest::setHeader: QVariant of type %s cannot be used with header %s",
1651 QHttpHeaders::wellKnownHeaderName(wellKnownOpt.value()).constData());
1655 setFromRawHeader(httpHeaders, wellKnownOpt.value(), rawValue);
1659 invalidateHeaderCache();
1669 httpHeaders = newHeaders;
1670 setCookedFromHttp(httpHeaders);
1671 invalidateHeaderCache();
1676 httpHeaders = std::move(newHeaders);
1677 setCookedFromHttp(httpHeaders);
1678 invalidateHeaderCache();
1683 httpHeaders.replaceOrAppend(name, value);
1686 const auto knownHeaderOpt = toKnownHeader(name);
1688 parseAndSetHeader(knownHeaderOpt.value(), value);
1690 invalidateHeaderCache();
1695 httpHeaders.clear();
1697 invalidateHeaderCache();
1703 const int parsedKeyAsInt = parseHeaderName(key);
1704 if (parsedKeyAsInt != -1) {
1705 const QNetworkRequest::KnownHeaders parsedKey
1706 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1707 parseAndSetHeader(parsedKey, value);
1712 QByteArrayView value)
1714 if (value.isNull()) {
1716 }
else if (key == QNetworkRequest::ContentLengthHeader
1717 && cookedHeaders.contains(QNetworkRequest::ContentLengthHeader)) {
1730 switch (month_str[0]) {
1732 switch (month_str[1]) {
1736 switch (month_str[2] ) {
1747 switch (month_str[2] ) {
1755 switch (month_str[1]) {
1783 int pos = value.indexOf(
',');
1785#if QT_CONFIG(datestring)
1788 dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
1794 int day, year, hour, minute, second;
1797 if (sscanf_s(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, 4, &year, &hour, &minute, &second) == 6)
1801 if (sscanf(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
1803 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
1805 QLocale c = QLocale::c();
1807 QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
1809 dt = c.toDateTime(sansWeekday,
"dd-MMM-yy hh:mm:ss 'GMT'"_L1);
1815 dt.setTimeZone(QTimeZone::UTC);
1821 return QLocale::c().toString(dt.toUTC(), u"ddd, dd MMM yyyy hh:mm:ss 'GMT'").toLatin1();
1825 const QHttpHeaders &headers)
1827 if (headers.isEmpty())
1831 QHash<QByteArray, qsizetype> nameToIndex;
1832 list.reserve(headers.size());
1833 nameToIndex.reserve(headers.size());
1835 for (qsizetype i = 0; i < headers.size(); ++i) {
1836 const auto nameL1 = headers.nameAt(i);
1837 const auto value = headers.valueAt(i);
1839 const bool isSetCookie = nameL1 == QHttpHeaders::wellKnownHeaderName(
1840 QHttpHeaders::WellKnownHeader::SetCookie);
1842 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1843 if (
auto it = nameToIndex.find(name); it != nameToIndex.end()) {
1844 list[it.value()].second += isSetCookie ?
"\n" :
", ";
1845 list[it.value()].second += value;
1847 nameToIndex[name] = list.size();
1848 list.emplaceBack(name, value.toByteArray());
1860 QHttpHeaders headers;
1861 headers.reserve(raw.size());
1863 for (
const auto &[key, value] : raw) {
1864 const bool isSetCookie = key.compare(QHttpHeaders::wellKnownHeaderName(
1865 QHttpHeaders::WellKnownHeader::SetCookie),
1866 Qt::CaseInsensitive) == 0;
1868 for (
auto header : QLatin1StringView(value).tokenize(
'\n'_L1))
1869 headers.append(key, header);
1871 headers.append(key, value);
1881 return std::nullopt;
1884 qint64 res = value.toLongLong(&ok);
1887 return std::nullopt;
1891 const QList<QByteArray> &values)
1894 return std::nullopt;
1896 QList<QNetworkCookie> cookies;
1897 for (
const auto &s : values)
1898 cookies += QNetworkCookie::parseCookies(s);
1900 if (cookies.empty())
1901 return std::nullopt;
1907 return makeCookieHeader(cookies, QNetworkCookie::NameAndValueOnly,
"; ");
1911 const QList<QByteArray> &values)
1914 return std::nullopt;
1916 QList<QNetworkCookie> cookies;
1917 for (
const auto &s : values)
1918 cookies += parseCookieHeader(s);
1920 if (cookies.empty())
1921 return std::nullopt;
1935 QMap<QNetworkRequest::KnownHeaders, QList<QByteArray>> multipleHeadersMap;
1936 for (
int i = 0; i < newHeaders.size(); ++i) {
1937 const auto name = newHeaders.nameAt(i);
1938 const auto value = newHeaders.valueAt(i);
1940 const int parsedKeyAsInt = parseHeaderName(name);
1941 if (parsedKeyAsInt == -1)
1944 const QNetworkRequest::KnownHeaders parsedKey
1945 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1947 auto &list = multipleHeadersMap[parsedKey];
1948 list.append(value.toByteArray());
1951 for (
auto i = multipleHeadersMap.cbegin(), end = multipleHeadersMap.cend(); i != end; ++i)
1952 cookedHeaders.insert(i.key(), parseHeaderValue(i.key(), i.value()));
1957#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[]