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"
25#if QT_CONFIG(datestring)
30#include <q20algorithm.h>
34using namespace Qt::StringLiterals;
35using namespace std::chrono_literals;
37constexpr std::chrono::milliseconds QNetworkRequest::DefaultTransferTimeout;
40QT_IMPL_METATYPE_EXTERN_TAGGED(QNetworkRequest::RedirectPolicy, QNetworkRequest__RedirectPolicy)
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
119
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
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
375
376
377
378
379
380
381
382
383
384
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
418
421
422
423
424
425
426
427
428
429
430
431
432
435
436
437
438
439
440
442class QNetworkRequestPrivate:
public QSharedData,
public QNetworkHeadersPrivate
445 static const int maxRedirectCount = 50;
446 inline QNetworkRequestPrivate()
447 : priority(QNetworkRequest::NormalPriority)
449 , sslConfiguration(
nullptr)
451 , maxRedirectsAllowed(maxRedirectCount)
452 { qRegisterMetaType<QNetworkRequest>(); }
453 ~QNetworkRequestPrivate()
456 delete sslConfiguration;
461 QNetworkRequestPrivate(
const QNetworkRequestPrivate &other)
462 : QSharedData(other), QNetworkHeadersPrivate(other)
465 priority = other.priority;
466 maxRedirectsAllowed = other.maxRedirectsAllowed;
468 sslConfiguration =
nullptr;
469 if (other.sslConfiguration)
470 sslConfiguration =
new QSslConfiguration(*other.sslConfiguration);
472 peerVerifyName = other.peerVerifyName;
474 h1Configuration = other.h1Configuration;
475 h2Configuration = other.h2Configuration;
476 decompressedSafetyCheckThreshold = other.decompressedSafetyCheckThreshold;
478 transferTimeout = other.transferTimeout;
481 inline bool operator==(
const QNetworkRequestPrivate &other)
const
483 return url == other.url &&
484 priority == other.priority &&
485 attributes == other.attributes &&
486 maxRedirectsAllowed == other.maxRedirectsAllowed &&
487 peerVerifyName == other.peerVerifyName
489 && h1Configuration == other.h1Configuration
490 && h2Configuration == other.h2Configuration
491 && decompressedSafetyCheckThreshold == other.decompressedSafetyCheckThreshold
493 && transferTimeout == other.transferTimeout
494 && QHttpHeadersHelper::compareStrict(httpHeaders, other.httpHeaders)
500 QNetworkRequest::Priority priority;
502 mutable QSslConfiguration *sslConfiguration;
504 int maxRedirectsAllowed;
505 QString peerVerifyName;
507 QHttp1Configuration h1Configuration;
508 QHttp2Configuration h2Configuration;
509 qint64 decompressedSafetyCheckThreshold = 10ll * 1024ll * 1024ll;
511 std::chrono::milliseconds transferTimeout = 0ms;
515
516
517
518
519
520QNetworkRequest::QNetworkRequest()
521 : d(
new QNetworkRequestPrivate)
529 d->h2Configuration.setStreamReceiveWindowSize(Http2::qtDefaultStreamReceiveWindowSize);
530 d->h2Configuration.setSessionReceiveWindowSize(Http2::maxSessionReceiveWindowSize);
531 d->h2Configuration.setServerPushEnabled(
false);
536
537
538
539
540
541QNetworkRequest::QNetworkRequest(
const QUrl &url)
548
549
550QNetworkRequest::QNetworkRequest(
const QNetworkRequest &other)
556
557
558QNetworkRequest::~QNetworkRequest()
565
566
567
568
569
570bool QNetworkRequest::operator==(
const QNetworkRequest &other)
const
572 return d == other.d || *d == *other.d;
576
577
578
579
580
581
584
585
586QNetworkRequest &QNetworkRequest::operator=(
const QNetworkRequest &other)
593
594
595
596
599
600
601
602
603QUrl QNetworkRequest::url()
const
609
610
611
612
613void QNetworkRequest::setUrl(
const QUrl &url)
619
620
621
622
623
624
625QHttpHeaders QNetworkRequest::headers()
const
631
632
633
634
635
636
637
638
639
640
641void QNetworkRequest::setHeaders(QHttpHeaders &&newHeaders)
643 d->setHeaders(std::move(newHeaders));
647
648
649
650void QNetworkRequest::setHeaders(
const QHttpHeaders &newHeaders)
652 d->setHeaders(newHeaders);
656
657
658
659
660
661
662QVariant QNetworkRequest::header(KnownHeaders header)
const
664 return d->cookedHeaders.value(header);
668
669
670
671
672
673
674void QNetworkRequest::setHeader(KnownHeaders header,
const QVariant &value)
676 d->setCookedHeader(header, value);
680
681
682
683
684
685
686bool QNetworkRequest::hasRawHeader(QAnyStringView headerName)
const
688 return d->headers().contains(headerName);
692
693
694
695
696
697
698
699
700
701
702QByteArray QNetworkRequest::rawHeader(QAnyStringView headerName)
const
704 return d->rawHeader(headerName);
708
709
710
711
712
713QList<QByteArray> QNetworkRequest::rawHeaderList()
const
715 return d->rawHeadersKeys();
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740void QNetworkRequest::setRawHeader(
const QByteArray &headerName,
const QByteArray &headerValue)
742 d->setRawHeader(headerName, headerValue);
746
747
748
749
750
751
752
753
754QVariant QNetworkRequest::attribute(Attribute code,
const QVariant &defaultValue)
const
756 return d->attributes.value(code, defaultValue);
760
761
762
763
764
765
766
767void QNetworkRequest::setAttribute(Attribute code,
const QVariant &value)
770 d->attributes.insert(code, value);
772 d->attributes.remove(code);
777
778
779
780
781
782QSslConfiguration QNetworkRequest::sslConfiguration()
const
784 if (!d->sslConfiguration)
785 d->sslConfiguration =
new QSslConfiguration(QSslConfiguration::defaultConfiguration());
786 return *d->sslConfiguration;
790
791
792
793
794
795
796
797void QNetworkRequest::setSslConfiguration(
const QSslConfiguration &config)
799 if (!d->sslConfiguration)
800 d->sslConfiguration =
new QSslConfiguration(config);
802 *d->sslConfiguration = config;
807
808
809
810
811
812
813
814
815
816
817void QNetworkRequest::setOriginatingObject(QObject *object)
819 d->originatingObject = object;
823
824
825
826
827
828
829
830
831QObject *QNetworkRequest::originatingObject()
const
833 return d->originatingObject.data();
837
838
839
840
841
842
843QNetworkRequest::Priority QNetworkRequest::priority()
const
849
850
851
852
853
854
855
856
857
860
861
862
863
864
865
866
867
868
869
870void QNetworkRequest::setPriority(Priority priority)
872 d->priority = priority;
876
877
878
879
880
881
882
883int QNetworkRequest::maximumRedirectsAllowed()
const
885 return d->maxRedirectsAllowed;
889
890
891
892
893
894
895
896void QNetworkRequest::setMaximumRedirectsAllowed(
int maxRedirectsAllowed)
898 d->maxRedirectsAllowed = maxRedirectsAllowed;
902
903
904
905
906
907
908
909QString QNetworkRequest::peerVerifyName()
const
911 return d->peerVerifyName;
915
916
917
918
919
920
921
922void QNetworkRequest::setPeerVerifyName(
const QString &peerName)
924 d->peerVerifyName = peerName;
929
930
931
932
933
934
935
936QHttp1Configuration QNetworkRequest::http1Configuration()
const
938 return d->h1Configuration;
941
942
943
944
945
946
947void QNetworkRequest::setHttp1Configuration(
const QHttp1Configuration &configuration)
949 d->h1Configuration = configuration;
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973QHttp2Configuration QNetworkRequest::http2Configuration()
const
975 return d->h2Configuration;
979
980
981
982
983
984
985
986
987
988
989
990
991void QNetworkRequest::setHttp2Configuration(
const QHttp2Configuration &configuration)
993 d->h2Configuration = configuration;
997
998
999
1000
1001
1002
1003
1004
1005
1006qint64 QNetworkRequest::decompressedSafetyCheckThreshold()
const
1008 return d->decompressedSafetyCheckThreshold;
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033void QNetworkRequest::setDecompressedSafetyCheckThreshold(qint64 threshold)
1035 d->decompressedSafetyCheckThreshold = threshold;
1039#if QT_CONFIG(http) || defined (Q_OS_WASM)
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1053
1054
1055
1056
1057
1058
1059
1060
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072std::chrono::milliseconds QNetworkRequest::transferTimeoutAsDuration()
const
1074 return d->transferTimeout;
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091void QNetworkRequest::setTransferTimeout(std::chrono::milliseconds duration)
1093 d->transferTimeout = duration;
1100 QHttpHeaders::WellKnownHeader wellKnownHeader;
1101 QNetworkRequest::KnownHeaders knownHeader;
1104constexpr bool operator<(
const HeaderPair &lhs,
const HeaderPair &rhs)
1106 return lhs.wellKnownHeader < rhs.wellKnownHeader;
1109constexpr bool operator<(
const HeaderPair &lhs, QHttpHeaders::WellKnownHeader rhs)
1111 return lhs.wellKnownHeader < rhs;
1114constexpr bool operator<(QHttpHeaders::WellKnownHeader lhs,
const HeaderPair &rhs)
1116 return lhs < rhs.wellKnownHeader;
1122 { QHttpHeaders::WellKnownHeader::ContentDisposition, QNetworkRequest::KnownHeaders::ContentDispositionHeader },
1123 { QHttpHeaders::WellKnownHeader::ContentLength, QNetworkRequest::KnownHeaders::ContentLengthHeader },
1124 { QHttpHeaders::WellKnownHeader::ContentType, QNetworkRequest::KnownHeaders::ContentTypeHeader },
1125 { QHttpHeaders::WellKnownHeader::Cookie, QNetworkRequest::KnownHeaders::CookieHeader },
1126 { QHttpHeaders::WellKnownHeader::ETag, QNetworkRequest::KnownHeaders::ETagHeader },
1127 { QHttpHeaders::WellKnownHeader::IfMatch , QNetworkRequest::KnownHeaders::IfMatchHeader },
1128 { QHttpHeaders::WellKnownHeader::IfModifiedSince, QNetworkRequest::KnownHeaders::IfModifiedSinceHeader },
1129 { QHttpHeaders::WellKnownHeader::IfNoneMatch, QNetworkRequest::KnownHeaders::IfNoneMatchHeader },
1130 { QHttpHeaders::WellKnownHeader::LastModified, QNetworkRequest::KnownHeaders::LastModifiedHeader},
1131 { QHttpHeaders::WellKnownHeader::Location, QNetworkRequest::KnownHeaders::LocationHeader},
1132 { QHttpHeaders::WellKnownHeader::Server, QNetworkRequest::KnownHeaders::ServerHeader },
1133 { QHttpHeaders::WellKnownHeader::SetCookie, QNetworkRequest::KnownHeaders::SetCookieHeader },
1134 { QHttpHeaders::WellKnownHeader::UserAgent, QNetworkRequest::KnownHeaders::UserAgentHeader }
1137static_assert(std::size(knownHeadersArr) == size_t(QNetworkRequest::KnownHeaders::NumKnownHeaders));
1143 if (it == std::end(knownHeadersArr) || key < *it)
1144 return std::nullopt;
1145 return it->knownHeader;
1150 auto pred = [key](
const HeaderPair &pair) {
return pair.knownHeader == key; };
1152 if (it == std::end(knownHeadersArr))
1153 return std::nullopt;
1154 return it->wellKnownHeader;
1158 QNetworkCookie::RawForm type,
1159 QByteArrayView separator)
1162 for (
const QNetworkCookie &cookie : cookies) {
1163 result += cookie.toRawForm(type);
1164 result += separator;
1166 if (!result.isEmpty())
1167 result.chop(separator.size());
1172 QByteArrayView separator)
1174 const QList<QNetworkCookie> *cookies = get_if<QList<QNetworkCookie>>(&value);
1177 return makeCookieHeader(*cookies, type, separator);
1183 case QNetworkRequest::ContentTypeHeader:
1184 case QNetworkRequest::ContentLengthHeader:
1185 case QNetworkRequest::ContentDispositionHeader:
1186 case QNetworkRequest::UserAgentHeader:
1187 case QNetworkRequest::ServerHeader:
1188 case QNetworkRequest::ETagHeader:
1189 case QNetworkRequest::IfMatchHeader:
1190 case QNetworkRequest::IfNoneMatchHeader:
1191 return value.toByteArray();
1193 case QNetworkRequest::LocationHeader:
1194 switch (value.userType()) {
1195 case QMetaType::QUrl:
1196 return value.toUrl().toEncoded();
1199 return value.toByteArray();
1202 case QNetworkRequest::LastModifiedHeader:
1203 case QNetworkRequest::IfModifiedSinceHeader:
1204 switch (value.userType()) {
1206 case QMetaType::QDate:
1207 return QNetworkHeadersPrivate::toHttpDate(value.toDate().startOfDay(QTimeZone::UTC));
1208 case QMetaType::QDateTime:
1209 return QNetworkHeadersPrivate::toHttpDate(value.toDateTime());
1212 return value.toByteArray();
1215 case QNetworkRequest::CookieHeader:
1216 return makeCookieHeader(value, QNetworkCookie::NameAndValueOnly,
"; ");
1218 case QNetworkRequest::SetCookieHeader:
1219 return makeCookieHeader(value, QNetworkCookie::Full,
", ");
1222 Q_UNREACHABLE_RETURN({});
1228 if (headerName.isEmpty())
1231 auto is = [headerName](QByteArrayView what) {
1232 return headerName.compare(what, Qt::CaseInsensitive) == 0;
1235 switch (QtMiscUtils::toAsciiLower(headerName.front())) {
1237 if (is(
"content-type"))
1238 return QNetworkRequest::ContentTypeHeader;
1239 else if (is(
"content-length"))
1240 return QNetworkRequest::ContentLengthHeader;
1241 else if (is(
"cookie"))
1242 return QNetworkRequest::CookieHeader;
1243 else if (is(
"content-disposition"))
1244 return QNetworkRequest::ContentDispositionHeader;
1249 return QNetworkRequest::ETagHeader;
1253 if (is(
"if-modified-since"))
1254 return QNetworkRequest::IfModifiedSinceHeader;
1256 return QNetworkRequest::IfMatchHeader;
1257 if (is(
"if-none-match"))
1258 return QNetworkRequest::IfNoneMatchHeader;
1263 return QNetworkRequest::LocationHeader;
1264 else if (is(
"last-modified"))
1265 return QNetworkRequest::LastModifiedHeader;
1269 if (is(
"set-cookie"))
1270 return QNetworkRequest::SetCookieHeader;
1271 else if (is(
"server"))
1272 return QNetworkRequest::ServerHeader;
1276 if (is(
"user-agent"))
1277 return QNetworkRequest::UserAgentHeader;
1286 QDateTime dt = QNetworkHeadersPrivate::fromHttpDate(raw);
1294 QList<QNetworkCookie> result;
1295 for (
auto cookie : QLatin1StringView(raw).tokenize(
';'_L1)) {
1296 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed());
1297 if (parsed.size() != 1)
1308 const QByteArrayView trimmed = raw.trimmed();
1309 if (!trimmed.startsWith(
'"') && !trimmed.startsWith(R"(W/")"))
1312 if (!trimmed.endsWith(
'"'))
1315 return QString::fromLatin1(trimmed);
1321 const QByteArrayView trimmedRaw = raw.trimmed();
1322 if (trimmedRaw ==
"*")
1323 return QStringList(QStringLiteral(
"*"));
1326 for (
auto &element : QLatin1StringView(trimmedRaw).tokenize(
','_L1)) {
1327 if (
const auto trimmed = element.trimmed(); op(trimmed))
1328 tags += QString::fromLatin1(trimmed);
1336 return parseMatchImpl(raw, [](QByteArrayView element) {
1337 return element.startsWith(
'"') && element.endsWith(
'"');
1343 return parseMatchImpl(raw, [](QByteArrayView element) {
1344 return (element.startsWith(
'"') || element.startsWith(R"(W/")")) && element.endsWith(
'"');
1353 case QNetworkRequest::UserAgentHeader:
1354 case QNetworkRequest::ServerHeader:
1355 case QNetworkRequest::ContentTypeHeader:
1356 case QNetworkRequest::ContentDispositionHeader:
1358 return QString::fromLatin1(value);
1360 case QNetworkRequest::ContentLengthHeader: {
1362 qint64 result = QByteArrayView(value).trimmed().toLongLong(&ok);
1368 case QNetworkRequest::LocationHeader: {
1369 QUrl result = QUrl::fromEncoded(value, QUrl::StrictMode);
1370 if (result.isValid() && !result.scheme().isEmpty())
1375 case QNetworkRequest::LastModifiedHeader:
1376 case QNetworkRequest::IfModifiedSinceHeader:
1377 return parseHttpDate(value);
1379 case QNetworkRequest::ETagHeader:
1380 return parseETag(value);
1382 case QNetworkRequest::IfMatchHeader:
1383 return parseIfMatch(value);
1385 case QNetworkRequest::IfNoneMatchHeader:
1386 return parseIfNoneMatch(value);
1388 case QNetworkRequest::CookieHeader:
1389 return QVariant::fromValue(parseCookieHeader(value));
1391 case QNetworkRequest::SetCookieHeader:
1392 return QVariant::fromValue(QNetworkCookie::parseCookies(value));
1395 Q_UNREACHABLE_RETURN({});
1406 case QNetworkRequest::IfMatchHeader: {
1408 for (
const auto &val : values)
1409 res << parseIfMatch(val);
1412 case QNetworkRequest::IfNoneMatchHeader: {
1414 for (
const auto &val : values)
1415 res << parseIfNoneMatch(val);
1418 case QNetworkRequest::CookieHeader: {
1419 auto listOpt = QNetworkHeadersPrivate::toCookieList(values);
1420 return listOpt.has_value() ? QVariant::fromValue(listOpt.value()) : QVariant();
1422 case QNetworkRequest::SetCookieHeader: {
1423 QList<QNetworkCookie> res;
1424 for (
const auto &val : values)
1425 res << QNetworkCookie::parseCookies(val);
1426 return QVariant::fromValue(res);
1429 return parseHeaderValue(header, values.first());
1436 return name.compare(QHttpHeaders::wellKnownHeaderName(QHttpHeaders::WellKnownHeader::SetCookie),
1437 Qt::CaseInsensitive) == 0;
1442 return name == QHttpHeaders::WellKnownHeader::SetCookie;
1445template<
class HeaderName>
1447 QByteArrayView value)
1449 headers.removeAll(header);
1455 if (isSetCookie(header)) {
1456 for (
auto cookie : QLatin1StringView(value).tokenize(
'\n'_L1))
1457 headers.append(QHttpHeaders::WellKnownHeader::SetCookie, cookie);
1459 headers.append(header, value);
1468 rawHeaderCache.headersList = fromHttpToRaw(httpHeaders);
1475 if (httpHeaders.isEmpty())
1478 QList<QByteArray> result;
1479 result.reserve(httpHeaders.size());
1480 QDuplicateTracker<QByteArray> seen(httpHeaders.size());
1482 for (qsizetype i = 0; i < httpHeaders.size(); i++) {
1483 const auto nameL1 = httpHeaders.nameAt(i);
1484 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1485 if (seen.hasSeen(name))
1496 QByteArrayView setCookieStr = QHttpHeaders::wellKnownHeaderName(
1497 QHttpHeaders::WellKnownHeader::SetCookie);
1498 if (QAnyStringView::compare(headerName, setCookieStr, Qt::CaseInsensitive) != 0)
1499 return httpHeaders.combinedValue(headerName);
1502 const char* separator =
"";
1503 for (qsizetype i = 0; i < httpHeaders.size(); ++i) {
1504 if (QAnyStringView::compare(httpHeaders.nameAt(i), headerName, Qt::CaseInsensitive) == 0) {
1505 result.append(separator);
1506 result.append(httpHeaders.valueAt(i));
1519 setFromRawHeader(httpHeaders, key, value);
1520 parseAndSetHeader(key, value);
1522 invalidateHeaderCache();
1526 const QVariant &value)
1528 const auto wellKnownOpt = toWellKnownHeader(header);
1529 if (!wellKnownOpt) {
1531 qWarning(
"QNetworkRequest::setHeader: invalid header value KnownHeader(%d) received", header);
1535 if (value.isNull()) {
1536 httpHeaders.removeAll(wellKnownOpt.value());
1539 QByteArray rawValue = headerValue(header, value);
1540 if (rawValue.isEmpty()) {
1541 qWarning(
"QNetworkRequest::setHeader: QVariant of type %s cannot be used with header %s",
1543 QHttpHeaders::wellKnownHeaderName(wellKnownOpt.value()).constData());
1547 setFromRawHeader(httpHeaders, wellKnownOpt.value(), rawValue);
1551 invalidateHeaderCache();
1561 httpHeaders = newHeaders;
1562 setCookedFromHttp(httpHeaders);
1563 invalidateHeaderCache();
1568 httpHeaders = std::move(newHeaders);
1569 setCookedFromHttp(httpHeaders);
1570 invalidateHeaderCache();
1575 httpHeaders.replaceOrAppend(name, value);
1578 const auto knownHeaderOpt = toKnownHeader(name);
1580 parseAndSetHeader(knownHeaderOpt.value(), value);
1582 invalidateHeaderCache();
1587 httpHeaders.clear();
1589 invalidateHeaderCache();
1595 const int parsedKeyAsInt = parseHeaderName(key);
1596 if (parsedKeyAsInt != -1) {
1597 const QNetworkRequest::KnownHeaders parsedKey
1598 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1599 parseAndSetHeader(parsedKey, value);
1604 QByteArrayView value)
1606 if (value.isNull()) {
1608 }
else if (key == QNetworkRequest::ContentLengthHeader
1609 && cookedHeaders.contains(QNetworkRequest::ContentLengthHeader)) {
1613 cookedHeaders.insert(key, parseHeaderValue(key, value));
1622 switch (month_str[0]) {
1624 switch (month_str[1]) {
1628 switch (month_str[2] ) {
1639 switch (month_str[2] ) {
1647 switch (month_str[1]) {
1675 int pos = value.indexOf(
',');
1677#if QT_CONFIG(datestring)
1680 dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
1686 int day, year, hour, minute, second;
1689 if (sscanf_s(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, 4, &year, &hour, &minute, &second) == 6)
1693 if (sscanf(value.constData(),
"%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
1695 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
1697 QLocale c = QLocale::c();
1699 QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
1701 dt = c.toDateTime(sansWeekday,
"dd-MMM-yy hh:mm:ss 'GMT'"_L1);
1707 dt.setTimeZone(QTimeZone::UTC);
1713 return QLocale::c().toString(dt.toUTC(), u"ddd, dd MMM yyyy hh:mm:ss 'GMT'").toLatin1();
1717 const QHttpHeaders &headers)
1719 if (headers.isEmpty())
1723 QHash<QByteArray, qsizetype> nameToIndex;
1724 list.reserve(headers.size());
1725 nameToIndex.reserve(headers.size());
1727 for (qsizetype i = 0; i < headers.size(); ++i) {
1728 const auto nameL1 = headers.nameAt(i);
1729 const auto value = headers.valueAt(i);
1731 const bool isSetCookie = nameL1 == QHttpHeaders::wellKnownHeaderName(
1732 QHttpHeaders::WellKnownHeader::SetCookie);
1734 const auto name =
QByteArray(nameL1.data(), nameL1.size());
1735 if (
auto it = nameToIndex.find(name); it != nameToIndex.end()) {
1736 list[it.value()].second += isSetCookie ?
"\n" :
", ";
1737 list[it.value()].second += value;
1739 nameToIndex[name] = list.size();
1740 list.emplaceBack(name, value.toByteArray());
1752 QHttpHeaders headers;
1753 headers.reserve(raw.size());
1755 for (
const auto &[key, value] : raw) {
1756 const bool isSetCookie = key.compare(QHttpHeaders::wellKnownHeaderName(
1757 QHttpHeaders::WellKnownHeader::SetCookie),
1758 Qt::CaseInsensitive) == 0;
1760 for (
auto header : QLatin1StringView(value).tokenize(
'\n'_L1))
1761 headers.append(key, header);
1763 headers.append(key, value);
1773 return std::nullopt;
1776 qint64 res = value.toLongLong(&ok);
1779 return std::nullopt;
1783 const QList<QByteArray> &values)
1786 return std::nullopt;
1788 QList<QNetworkCookie> cookies;
1789 for (
const auto &s : values)
1790 cookies += QNetworkCookie::parseCookies(s);
1792 if (cookies.empty())
1793 return std::nullopt;
1799 return makeCookieHeader(cookies, QNetworkCookie::NameAndValueOnly,
"; ");
1803 const QList<QByteArray> &values)
1806 return std::nullopt;
1808 QList<QNetworkCookie> cookies;
1809 for (
const auto &s : values)
1810 cookies += parseCookieHeader(s);
1812 if (cookies.empty())
1813 return std::nullopt;
1827 QMap<QNetworkRequest::KnownHeaders, QList<QByteArray>> multipleHeadersMap;
1828 for (
int i = 0; i < newHeaders.size(); ++i) {
1829 const auto name = newHeaders.nameAt(i);
1830 const auto value = newHeaders.valueAt(i);
1832 const int parsedKeyAsInt = parseHeaderName(name);
1833 if (parsedKeyAsInt == -1)
1836 const QNetworkRequest::KnownHeaders parsedKey
1837 =
static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1839 auto &list = multipleHeadersMap[parsedKey];
1840 list.append(value.toByteArray());
1843 for (
auto i = multipleHeadersMap.cbegin(), end = multipleHeadersMap.cend(); i != end; ++i)
1844 cookedHeaders.insert(i.key(), parseHeaderValue(i.key(), i.value()));
1849#include "moc_qnetworkrequest.cpp"
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
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[]