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
756void QNetworkRequest::setRawHeader(
const QByteArray &headerName,
const QByteArray &headerValue)
758 d->setRawHeader(headerName, headerValue);
762
763
764
765
766
767
768
769
770QVariant QNetworkRequest::attribute(Attribute code,
const QVariant &defaultValue)
const
772 return d->attributes.value(code, defaultValue);
776
777
778
779
780
781
782
783void QNetworkRequest::setAttribute(Attribute code,
const QVariant &value)
786 d->attributes.insert(code, value);
788 d->attributes.remove(code);
793
794
795
796
797
798QSslConfiguration QNetworkRequest::sslConfiguration()
const
800 if (!d->sslConfiguration)
801 d->sslConfiguration =
new QSslConfiguration(QSslConfiguration::defaultConfiguration());
802 return *d->sslConfiguration;
806
807
808
809
810
811
812
813void QNetworkRequest::setSslConfiguration(
const QSslConfiguration &config)
815 if (!d->sslConfiguration)
816 d->sslConfiguration =
new QSslConfiguration(config);
818 *d->sslConfiguration = config;
823
824
825
826
827
828
829
830
831
832
833void QNetworkRequest::setOriginatingObject(QObject *object)
835 d->originatingObject = object;
839
840
841
842
843
844
845
846
847QObject *QNetworkRequest::originatingObject()
const
849 return d->originatingObject.data();
853
854
855
856
857
858
859QNetworkRequest::Priority QNetworkRequest::priority()
const
865
866
867
868
869
870
871
872
873
876
877
878
879
880
881
882
883
884
885
886void QNetworkRequest::setPriority(Priority priority)
888 d->priority = priority;
892
893
894
895
896
897
898
899int QNetworkRequest::maximumRedirectsAllowed()
const
901 return d->maxRedirectsAllowed;
905
906
907
908
909
910
911
912void QNetworkRequest::setMaximumRedirectsAllowed(
int maxRedirectsAllowed)
914 d->maxRedirectsAllowed = maxRedirectsAllowed;
918
919
920
921
922
923
924
925QString QNetworkRequest::peerVerifyName()
const
927 return d->peerVerifyName;
931
932
933
934
935
936
937
938void QNetworkRequest::setPeerVerifyName(
const QString &peerName)
940 d->peerVerifyName = peerName;
945
946
947
948
949
950
951
952QHttp1Configuration QNetworkRequest::http1Configuration()
const
954 return d->h1Configuration;
957
958
959
960
961
962
963void QNetworkRequest::setHttp1Configuration(
const QHttp1Configuration &configuration)
965 d->h1Configuration = configuration;
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989QHttp2Configuration QNetworkRequest::http2Configuration()
const
991 return d->h2Configuration;
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007void QNetworkRequest::setHttp2Configuration(
const QHttp2Configuration &configuration)
1009 d->h2Configuration = configuration;
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022qint64 QNetworkRequest::decompressedSafetyCheckThreshold()
const
1024 return d->decompressedSafetyCheckThreshold;
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049void QNetworkRequest::setDecompressedSafetyCheckThreshold(qint64 threshold)
1051 d->decompressedSafetyCheckThreshold = threshold;
1056
1057
1058
1059
1060
1061
1062
1063
1065std::chrono::seconds QNetworkRequest::tcpKeepAliveIdleTimeBeforeProbes()
const
1067 return d->idleTimeBeforeProbes;
1071
1072
1073
1074
1075
1076
1077
1078
1079
1081void QNetworkRequest::doSetIdleTimeBeforeProbes(std::chrono::duration<
int> seconds)
1083 d->idleTimeBeforeProbes = seconds;
1087
1088
1089
1090
1091
1092
1093
1095std::chrono::seconds QNetworkRequest::tcpKeepAliveIntervalBetweenProbes()
const
1097 return d->intervalBetweenProbes;
1101
1102
1103
1104
1105
1106
1107
1108
1110void QNetworkRequest::doSetIntervalBetweenProbes(std::chrono::duration<
int> seconds)
1112 d->intervalBetweenProbes = seconds;
1116
1117
1118
1119
1120
1121
1122
1123
1125int QNetworkRequest::tcpKeepAliveProbeCount()
const
1127 return d->probeCount;
1131
1132
1133
1134
1135
1136
1137
1138
1140void QNetworkRequest::setTcpKeepAliveProbeCount(
int probes)
1142 d->probeCount = probes;
1145#if QT_CONFIG(http) || defined (Q_OS_WASM)
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1159
1160
1161
1162
1163
1164
1165
1166
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178std::chrono::milliseconds QNetworkRequest::transferTimeoutAsDuration()
const
1180 return d->transferTimeout;
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197void QNetworkRequest::setTransferTimeout(std::chrono::milliseconds duration)
1199 d->transferTimeout = duration;
1206 QHttpHeaders::WellKnownHeader wellKnownHeader;
1207 QNetworkRequest::KnownHeaders knownHeader;
1210constexpr bool operator<(
const HeaderPair &lhs,
const HeaderPair &rhs)
1212 return lhs.wellKnownHeader < rhs.wellKnownHeader;
1215constexpr bool operator<(
const HeaderPair &lhs, QHttpHeaders::WellKnownHeader rhs)
1217 return lhs.wellKnownHeader < rhs;
1220constexpr bool operator<(QHttpHeaders::WellKnownHeader lhs,
const HeaderPair &rhs)
1222 return lhs < rhs.wellKnownHeader;
1228 { QHttpHeaders::WellKnownHeader::ContentDisposition, QNetworkRequest::KnownHeaders::ContentDispositionHeader },
1229 { QHttpHeaders::WellKnownHeader::ContentLength, QNetworkRequest::KnownHeaders::ContentLengthHeader },
1230 { QHttpHeaders::WellKnownHeader::ContentType, QNetworkRequest::KnownHeaders::ContentTypeHeader },
1231 { QHttpHeaders::WellKnownHeader::Cookie, QNetworkRequest::KnownHeaders::CookieHeader },
1232 { QHttpHeaders::WellKnownHeader::ETag, QNetworkRequest::KnownHeaders::ETagHeader },
1233 { QHttpHeaders::WellKnownHeader::IfMatch , QNetworkRequest::KnownHeaders::IfMatchHeader },
1234 { QHttpHeaders::WellKnownHeader::IfModifiedSince, QNetworkRequest::KnownHeaders::IfModifiedSinceHeader },
1235 { QHttpHeaders::WellKnownHeader::IfNoneMatch, QNetworkRequest::KnownHeaders::IfNoneMatchHeader },
1236 { QHttpHeaders::WellKnownHeader::LastModified, QNetworkRequest::KnownHeaders::LastModifiedHeader},
1237 { QHttpHeaders::WellKnownHeader::Location, QNetworkRequest::KnownHeaders::LocationHeader},
1238 { QHttpHeaders::WellKnownHeader::Server, QNetworkRequest::KnownHeaders::ServerHeader },
1239 { QHttpHeaders::WellKnownHeader::SetCookie, QNetworkRequest::KnownHeaders::SetCookieHeader },
1240 { QHttpHeaders::WellKnownHeader::UserAgent, QNetworkRequest::KnownHeaders::UserAgentHeader }
1243static_assert(std::size(knownHeadersArr) == size_t(QNetworkRequest::KnownHeaders::NumKnownHeaders));
1249 if (it == std::end(knownHeadersArr) || key < *it)
1250 return std::nullopt;
1251 return it->knownHeader;
1256 auto pred = [key](
const HeaderPair &pair) {
return pair.knownHeader == key; };
1258 if (it == std::end(knownHeadersArr))
1259 return std::nullopt;
1260 return it->wellKnownHeader;
1264 QNetworkCookie::RawForm type,
1265 QByteArrayView separator)
1268 for (
const QNetworkCookie &cookie : cookies) {
1269 result += cookie.toRawForm(type);
1270 result += separator;
1272 if (!result.isEmpty())
1273 result.chop(separator.size());
1278 QByteArrayView separator)
1280 const QList<QNetworkCookie> *cookies = get_if<QList<QNetworkCookie>>(&value);
1283 return makeCookieHeader(*cookies, type, separator);
1289 case QNetworkRequest::ContentTypeHeader:
1290 case QNetworkRequest::ContentLengthHeader:
1291 case QNetworkRequest::ContentDispositionHeader:
1292 case QNetworkRequest::UserAgentHeader:
1293 case QNetworkRequest::ServerHeader:
1294 case QNetworkRequest::ETagHeader:
1295 case QNetworkRequest::IfMatchHeader:
1296 case QNetworkRequest::IfNoneMatchHeader:
1297 return value.toByteArray();
1299 case QNetworkRequest::LocationHeader:
1300 switch (value.userType()) {
1301 case QMetaType::QUrl:
1302 return value.toUrl().toEncoded();
1305 return value.toByteArray();
1308 case QNetworkRequest::LastModifiedHeader:
1309 case QNetworkRequest::IfModifiedSinceHeader:
1310 switch (value.userType()) {
1312 case QMetaType::QDate:
1313 return QNetworkHeadersPrivate::toHttpDate(value.toDate().startOfDay(QTimeZone::UTC));
1314 case QMetaType::QDateTime:
1315 return QNetworkHeadersPrivate::toHttpDate(value.toDateTime());
1318 return value.toByteArray();
1321 case QNetworkRequest::CookieHeader:
1322 return makeCookieHeader(value, QNetworkCookie::NameAndValueOnly,
"; ");
1324 case QNetworkRequest::SetCookieHeader:
1325 return makeCookieHeader(value, QNetworkCookie::Full,
", ");
1328 Q_UNREACHABLE_RETURN({});
1334 if (headerName.isEmpty())
1337 auto is = [headerName](QByteArrayView what) {
1338 return headerName.compare(what, Qt::CaseInsensitive) == 0;
1341 switch (QtMiscUtils::toAsciiLower(headerName.front())) {
1343 if (is(
"content-type"))
1344 return QNetworkRequest::ContentTypeHeader;
1345 else if (is(
"content-length"))
1346 return QNetworkRequest::ContentLengthHeader;
1347 else if (is(
"cookie"))
1348 return QNetworkRequest::CookieHeader;
1349 else if (is(
"content-disposition"))
1350 return QNetworkRequest::ContentDispositionHeader;
1355 return QNetworkRequest::ETagHeader;
1359 if (is(
"if-modified-since"))
1360 return QNetworkRequest::IfModifiedSinceHeader;
1362 return QNetworkRequest::IfMatchHeader;
1363 if (is(
"if-none-match"))
1364 return QNetworkRequest::IfNoneMatchHeader;
1369 return QNetworkRequest::LocationHeader;
1370 else if (is(
"last-modified"))
1371 return QNetworkRequest::LastModifiedHeader;
1375 if (is(
"set-cookie"))
1376 return QNetworkRequest::SetCookieHeader;
1377 else if (is(
"server"))
1378 return QNetworkRequest::ServerHeader;
1382 if (is(
"user-agent"))
1383 return QNetworkRequest::UserAgentHeader;
1392 QDateTime dt = QNetworkHeadersPrivate::fromHttpDate(raw);
1400 QList<QNetworkCookie> result;
1401 for (
auto cookie : QLatin1StringView(raw).tokenize(
';'_L1)) {
1402 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed());
1403 if (parsed.size() != 1)
1414 const QByteArrayView trimmed = raw.trimmed();
1415 if (!trimmed.startsWith(
'"') && !trimmed.startsWith(R"(W/")"))
1418 if (!trimmed.endsWith(
'"'))
1421 return QString::fromLatin1(trimmed);
1427 const QByteArrayView trimmedRaw = raw.trimmed();
1428 if (trimmedRaw ==
"*")
1429 return QStringList(QStringLiteral(
"*"));
1432 for (
auto &element : QLatin1StringView(trimmedRaw).tokenize(
','_L1)) {
1433 if (
const auto trimmed = element.trimmed(); op(trimmed))
1434 tags += QString::fromLatin1(trimmed);
1442 return parseMatchImpl(raw, [](QByteArrayView element) {
1443 return element.startsWith(
'"') && element.endsWith(
'"');
1449 return parseMatchImpl(raw, [](QByteArrayView element) {
1450 return (element.startsWith(
'"') || element.startsWith(R"(W/")")) && element.endsWith(
'"');
1459 case QNetworkRequest::UserAgentHeader:
1460 case QNetworkRequest::ServerHeader:
1461 case QNetworkRequest::ContentTypeHeader:
1462 case QNetworkRequest::ContentDispositionHeader:
1464 return QString::fromLatin1(value);
1466 case QNetworkRequest::ContentLengthHeader: {
1468 qint64 result = QByteArrayView(value).trimmed().toLongLong(&ok);
1474 case QNetworkRequest::LocationHeader: {
1475 QUrl result = QUrl::fromEncoded(value, QUrl::StrictMode);
1476 if (result.isValid() && !result.scheme().isEmpty())
1481 case QNetworkRequest::LastModifiedHeader:
1482 case QNetworkRequest::IfModifiedSinceHeader:
1483 return parseHttpDate(value);
1485 case QNetworkRequest::ETagHeader:
1486 return parseETag(value);
1488 case QNetworkRequest::IfMatchHeader:
1489 return parseIfMatch(value);
1491 case QNetworkRequest::IfNoneMatchHeader:
1492 return parseIfNoneMatch(value);
1494 case QNetworkRequest::CookieHeader:
1495 return QVariant::fromValue(parseCookieHeader(value));
1497 case QNetworkRequest::SetCookieHeader:
1498 return QVariant::fromValue(QNetworkCookie::parseCookies(value));
1501 Q_UNREACHABLE_RETURN({});
1512 case QNetworkRequest::IfMatchHeader: {
1514 for (
const auto &val : values)
1515 res << parseIfMatch(val);
1518 case QNetworkRequest::IfNoneMatchHeader: {
1520 for (
const auto &val : values)
1521 res << parseIfNoneMatch(val);
1524 case QNetworkRequest::CookieHeader: {
1525 auto listOpt = QNetworkHeadersPrivate::toCookieList(values);
1526 return listOpt.has_value() ? QVariant::fromValue(listOpt.value()) : QVariant();
1528 case QNetworkRequest::SetCookieHeader: {
1529 QList<QNetworkCookie> res;
1530 for (
const auto &val : values)
1531 res << QNetworkCookie::parseCookies(val);
1532 return QVariant::fromValue(res);
1535 return parseHeaderValue(header, values.first());
1542 return name.compare(QHttpHeaders::wellKnownHeaderName(QHttpHeaders::WellKnownHeader::SetCookie),
1543 Qt::CaseInsensitive) == 0;
1548 return name == QHttpHeaders::WellKnownHeader::SetCookie;
1551template<
class HeaderName>
1553 QByteArrayView value)
1555 headers.removeAll(header);
1561 if (isSetCookie(header)) {
1562 for (
auto cookie : QLatin1StringView(value).tokenize(
'\n'_L1))
1563 headers.append(QHttpHeaders::WellKnownHeader::SetCookie, cookie);
1565 headers.append(header, value);
1574 rawHeaderCache
.headersList = fromHttpToRaw(httpHeaders);
1581 if (httpHeaders.isEmpty())
1584 QList<QByteArray> result;
1585 result.reserve(httpHeaders.size());
1586 QDuplicateTracker<QByteArray> seen(httpHeaders.size());
1588 for (qsizetype i = 0; i < httpHeaders.size(); i++) {
1589 const auto nameL1 = httpHeaders.nameAt(i);
1590 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1591 if (seen.hasSeen(name))
1602 QByteArrayView setCookieStr = QHttpHeaders::wellKnownHeaderName(
1603 QHttpHeaders::WellKnownHeader::SetCookie);
1604 if (QAnyStringView::compare(headerName, setCookieStr, Qt::CaseInsensitive) != 0)
1605 return httpHeaders.combinedValue(headerName);
1608 const char* separator =
"";
1609 for (qsizetype i = 0; i < httpHeaders.size(); ++i) {
1610 if (QAnyStringView::compare(httpHeaders.nameAt(i), headerName, Qt::CaseInsensitive) == 0) {
1611 result.append(separator);
1612 result.append(httpHeaders.valueAt(i));
1625 setFromRawHeader(httpHeaders, key, value);
1626 parseAndSetHeader(key, value);
1628 invalidateHeaderCache();
1632 const QVariant &value)
1634 const auto wellKnownOpt = toWellKnownHeader(header);
1635 if (!wellKnownOpt) {
1637 qWarning(
"QNetworkRequest::setHeader: invalid header value KnownHeader(%d) received", header);
1641 if (value.isNull()) {
1642 httpHeaders.removeAll(wellKnownOpt.value());
1645 QByteArray rawValue = headerValue(header, value);
1646 if (rawValue.isEmpty()) {
1647 qWarning(
"QNetworkRequest::setHeader: QVariant of type %s cannot be used with header %s",
1649 QHttpHeaders::wellKnownHeaderName(wellKnownOpt.value()).constData());
1653 setFromRawHeader(httpHeaders, wellKnownOpt.value(), rawValue);
1657 invalidateHeaderCache();
1667 httpHeaders = newHeaders;
1668 setCookedFromHttp(httpHeaders);
1669 invalidateHeaderCache();
1674 httpHeaders = std::move(newHeaders);
1675 setCookedFromHttp(httpHeaders);
1676 invalidateHeaderCache();
1681 httpHeaders.replaceOrAppend(name, value);
1684 const auto knownHeaderOpt = toKnownHeader(name);
1686 parseAndSetHeader(knownHeaderOpt.value(), value);
1688 invalidateHeaderCache();
1693 httpHeaders.clear();
1695 invalidateHeaderCache();
1701 const int parsedKeyAsInt = parseHeaderName(key);
1702 if (parsedKeyAsInt != -1) {
1703 const QNetworkRequest::KnownHeaders parsedKey
1704 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1705 parseAndSetHeader(parsedKey, value);
1710 QByteArrayView value)
1712 if (value.isNull()) {
1714 }
else if (key == QNetworkRequest::ContentLengthHeader
1715 && cookedHeaders.contains(QNetworkRequest::ContentLengthHeader)) {
1728 switch (month_str[0]) {
1730 switch (month_str[1]) {
1734 switch (month_str[2] ) {
1745 switch (month_str[2] ) {
1753 switch (month_str[1]) {
1781 int pos = value.indexOf(
',');
1783#if QT_CONFIG(datestring)
1786 dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
1792 int day, year, hour, minute, second;
1795 if (sscanf_s(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, 4, &year, &hour, &minute, &second) == 6)
1799 if (sscanf(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
1801 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
1803 QLocale c = QLocale::c();
1805 QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
1807 dt = c.toDateTime(sansWeekday,
"dd-MMM-yy hh:mm:ss 'GMT'"_L1);
1813 dt.setTimeZone(QTimeZone::UTC);
1819 return QLocale::c().toString(dt.toUTC(), u"ddd, dd MMM yyyy hh:mm:ss 'GMT'").toLatin1();
1823 const QHttpHeaders &headers)
1825 if (headers.isEmpty())
1829 QHash<QByteArray, qsizetype> nameToIndex;
1830 list.reserve(headers.size());
1831 nameToIndex.reserve(headers.size());
1833 for (qsizetype i = 0; i < headers.size(); ++i) {
1834 const auto nameL1 = headers.nameAt(i);
1835 const auto value = headers.valueAt(i);
1837 const bool isSetCookie = nameL1 == QHttpHeaders::wellKnownHeaderName(
1838 QHttpHeaders::WellKnownHeader::SetCookie);
1840 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1841 if (
auto it = nameToIndex.find(name); it != nameToIndex.end()) {
1842 list[it.value()].second += isSetCookie ?
"\n" :
", ";
1843 list[it.value()].second += value;
1845 nameToIndex[name] = list.size();
1846 list.emplaceBack(name, value.toByteArray());
1858 QHttpHeaders headers;
1859 headers.reserve(raw.size());
1861 for (
const auto &[key, value] : raw) {
1862 const bool isSetCookie = key.compare(QHttpHeaders::wellKnownHeaderName(
1863 QHttpHeaders::WellKnownHeader::SetCookie),
1864 Qt::CaseInsensitive) == 0;
1866 for (
auto header : QLatin1StringView(value).tokenize(
'\n'_L1))
1867 headers.append(key, header);
1869 headers.append(key, value);
1879 return std::nullopt;
1882 qint64 res = value.toLongLong(&ok);
1885 return std::nullopt;
1889 const QList<QByteArray> &values)
1892 return std::nullopt;
1894 QList<QNetworkCookie> cookies;
1895 for (
const auto &s : values)
1896 cookies += QNetworkCookie::parseCookies(s);
1898 if (cookies.empty())
1899 return std::nullopt;
1905 return makeCookieHeader(cookies, QNetworkCookie::NameAndValueOnly,
"; ");
1909 const QList<QByteArray> &values)
1912 return std::nullopt;
1914 QList<QNetworkCookie> cookies;
1915 for (
const auto &s : values)
1916 cookies += parseCookieHeader(s);
1918 if (cookies.empty())
1919 return std::nullopt;
1933 QMap<QNetworkRequest::KnownHeaders, QList<QByteArray>> multipleHeadersMap;
1934 for (
int i = 0; i < newHeaders.size(); ++i) {
1935 const auto name = newHeaders.nameAt(i);
1936 const auto value = newHeaders.valueAt(i);
1938 const int parsedKeyAsInt = parseHeaderName(name);
1939 if (parsedKeyAsInt == -1)
1942 const QNetworkRequest::KnownHeaders parsedKey
1943 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1945 auto &list = multipleHeadersMap[parsedKey];
1946 list.append(value.toByteArray());
1949 for (
auto i = multipleHeadersMap.cbegin(), end = multipleHeadersMap.cend(); i != end; ++i)
1950 cookedHeaders.insert(i.key(), parseHeaderValue(i.key(), i.value()));
1955#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[]