Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qnetworkrequest.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qnetworkrequest.h"
5#include "qnetworkrequest_p.h"
6#include "qplatformdefs.h"
7#include "qnetworkcookie.h"
8#include "qsslconfiguration.h"
10#if QT_CONFIG(http)
11#include "qhttp1configuration.h"
12#include "qhttp2configuration.h"
13#include "private/http2protocol_p.h"
14#endif
15
16#include "QtCore/qdatetime.h"
17#include "QtCore/qlocale.h"
18#include "QtCore/qshareddata.h"
19#include "QtCore/qtimezone.h"
20#include "QtCore/private/qduplicatetracker_p.h"
21#include "QtCore/private/qtools_p.h"
22
23#include <ctype.h>
24#if QT_CONFIG(datestring)
25# include <stdio.h>
26#endif
27
28#include <algorithm>
29#include <q20algorithm.h>
30
32
33using namespace Qt::StringLiterals;
34using namespace std::chrono_literals;
35
36constexpr std::chrono::milliseconds QNetworkRequest::DefaultTransferTimeout;
37
40
41
431{
432public:
433 static const int maxRedirectCount = 50;
435 : priority(QNetworkRequest::NormalPriority)
436#ifndef QT_NO_SSL
437 , sslConfiguration(nullptr)
438#endif
439 , maxRedirectsAllowed(maxRedirectCount)
440 { qRegisterMetaType<QNetworkRequest>(); }
442 {
443#ifndef QT_NO_SSL
444 delete sslConfiguration;
445#endif
446 }
447
448
451 {
452 url = other.url;
453 priority = other.priority;
454 maxRedirectsAllowed = other.maxRedirectsAllowed;
455#ifndef QT_NO_SSL
456 sslConfiguration = nullptr;
457 if (other.sslConfiguration)
458 sslConfiguration = new QSslConfiguration(*other.sslConfiguration);
459#endif
460 peerVerifyName = other.peerVerifyName;
461#if QT_CONFIG(http)
462 h1Configuration = other.h1Configuration;
463 h2Configuration = other.h2Configuration;
464 decompressedSafetyCheckThreshold = other.decompressedSafetyCheckThreshold;
465#endif
466 transferTimeout = other.transferTimeout;
467 }
468
469 inline bool operator==(const QNetworkRequestPrivate &other) const
470 {
471 return url == other.url &&
472 priority == other.priority &&
473 attributes == other.attributes &&
474 maxRedirectsAllowed == other.maxRedirectsAllowed &&
475 peerVerifyName == other.peerVerifyName
476#if QT_CONFIG(http)
477 && h1Configuration == other.h1Configuration
478 && h2Configuration == other.h2Configuration
479 && decompressedSafetyCheckThreshold == other.decompressedSafetyCheckThreshold
480#endif
481 && transferTimeout == other.transferTimeout
482 && QHttpHeadersHelper::compareStrict(httpHeaders, other.httpHeaders)
483 ;
484 // don't compare cookedHeaders
485 }
486
489#ifndef QT_NO_SSL
491#endif
494#if QT_CONFIG(http)
495 QHttp1Configuration h1Configuration;
496 QHttp2Configuration h2Configuration;
497 qint64 decompressedSafetyCheckThreshold = 10ll * 1024ll * 1024ll;
498#endif
499 std::chrono::milliseconds transferTimeout = 0ms;
500};
501
510{
511#if QT_CONFIG(http)
512 // Initial values proposed by RFC 7540 are quite draconian, but we
513 // know about servers configured with this value as maximum possible,
514 // rejecting our SETTINGS frame and sending us a GOAWAY frame with the
515 // flow control error set. If this causes a problem - the app should
516 // set a proper configuration. We'll use our defaults, as documented.
517 d->h2Configuration.setStreamReceiveWindowSize(Http2::qtDefaultStreamReceiveWindowSize);
518 d->h2Configuration.setSessionReceiveWindowSize(Http2::maxSessionReceiveWindowSize);
519 d->h2Configuration.setServerPushEnabled(false);
520#endif // QT_CONFIG(http)
521}
522
534
542
547{
548 // QSharedDataPointer auto deletes
549 d = nullptr;
550}
551
559{
560 return d == other.d || *d == *other.d;
561}
562
575{
576 d = other.d;
577 return *this;
578}
579
594{
595 return d->url;
596}
597
604{
605 d->url = url;
606}
607
616{
617 return d->headers();
618}
619
632{
633 d->setHeaders(std::move(newHeaders));
634}
635
641{
642 d->setHeaders(newHeaders);
643}
644
656
668
677{
678 return d->headers().contains(headerName);
679}
680
693{
694 return d->rawHeader(headerName);
695}
696
703QList<QByteArray> QNetworkRequest::rawHeaderList() const
704{
705 return d->rawHeadersKeys();
706}
707
728{
729 d->setRawHeader(headerName, headerValue);
730}
731
742{
743 return d->attributes.value(code, defaultValue);
744}
745
755{
756 if (value.isValid())
757 d->attributes.insert(code, value);
758 else
759 d->attributes.remove(code);
760}
761
762#ifndef QT_NO_SSL
775
791#endif
792
808
822
834
858{
859 d->priority = priority;
860}
861
874
884{
885 d->maxRedirectsAllowed = maxRedirectsAllowed;
886}
887
900
910{
911 d->peerVerifyName = peerName;
912}
913
914#if QT_CONFIG(http)
923QHttp1Configuration QNetworkRequest::http1Configuration() const
924{
925 return d->h1Configuration;
926}
934void QNetworkRequest::setHttp1Configuration(const QHttp1Configuration &configuration)
935{
936 d->h1Configuration = configuration;
937}
938
960QHttp2Configuration QNetworkRequest::http2Configuration() const
961{
962 return d->h2Configuration;
963}
964
978void QNetworkRequest::setHttp2Configuration(const QHttp2Configuration &configuration)
979{
980 d->h2Configuration = configuration;
981}
982
993qint64 QNetworkRequest::decompressedSafetyCheckThreshold() const
994{
995 return d->decompressedSafetyCheckThreshold;
996}
997
1020void QNetworkRequest::setDecompressedSafetyCheckThreshold(qint64 threshold)
1021{
1022 d->decompressedSafetyCheckThreshold = threshold;
1023}
1024#endif // QT_CONFIG(http)
1025
1026#if QT_CONFIG(http) || defined (Q_OS_WASM)
1056std::chrono::milliseconds QNetworkRequest::transferTimeoutAsDuration() const
1057{
1058 return d->transferTimeout;
1059}
1060
1075void QNetworkRequest::setTransferTimeout(std::chrono::milliseconds duration)
1076{
1077 d->transferTimeout = duration;
1078}
1079#endif // QT_CONFIG(http) || defined (Q_OS_WASM)
1080
1081namespace {
1082
1083struct HeaderPair {
1084 QHttpHeaders::WellKnownHeader wellKnownHeader;
1086};
1087
1088constexpr bool operator<(const HeaderPair &lhs, const HeaderPair &rhs)
1089{
1090 return lhs.wellKnownHeader < rhs.wellKnownHeader;
1091}
1092
1093constexpr bool operator<(const HeaderPair &lhs, QHttpHeaders::WellKnownHeader rhs)
1094{
1095 return lhs.wellKnownHeader < rhs;
1096}
1097
1098constexpr bool operator<(QHttpHeaders::WellKnownHeader lhs, const HeaderPair &rhs)
1099{
1100 return lhs < rhs.wellKnownHeader;
1101}
1102
1103} // anonymous namespace
1104
1120
1121static_assert(std::size(knownHeadersArr) == size_t(QNetworkRequest::KnownHeaders::NumKnownHeaders));
1122static_assert(q20::is_sorted(std::begin(knownHeadersArr), std::end(knownHeadersArr)));
1123
1124static std::optional<QNetworkRequest::KnownHeaders> toKnownHeader(QHttpHeaders::WellKnownHeader key)
1125{
1126 const auto it = std::lower_bound(std::begin(knownHeadersArr), std::end(knownHeadersArr), key);
1127 if (it == std::end(knownHeadersArr) || key < *it)
1128 return std::nullopt;
1129 return it->knownHeader;
1130}
1131
1132static std::optional<QHttpHeaders::WellKnownHeader> toWellKnownHeader(QNetworkRequest::KnownHeaders key)
1133{
1134 auto pred = [key](const HeaderPair &pair) { return pair.knownHeader == key; };
1135 const auto it = std::find_if(std::begin(knownHeadersArr), std::end(knownHeadersArr), pred);
1136 if (it == std::end(knownHeadersArr))
1137 return std::nullopt;
1138 return it->wellKnownHeader;
1139}
1140
1141static QByteArray makeCookieHeader(const QList<QNetworkCookie> &cookies,
1143 QByteArrayView separator)
1144{
1146 for (const QNetworkCookie &cookie : cookies) {
1147 result += cookie.toRawForm(type);
1148 result += separator;
1149 }
1150 if (!result.isEmpty())
1151 result.chop(separator.size());
1152 return result;
1153}
1154
1156 QByteArrayView separator)
1157{
1158 const QList<QNetworkCookie> *cookies = get_if<QList<QNetworkCookie>>(&value);
1159 if (!cookies)
1160 return {};
1161 return makeCookieHeader(*cookies, type, separator);
1162}
1163
1165{
1166 switch (header) {
1175 return value.toByteArray();
1176
1178 switch (value.userType()) {
1179 case QMetaType::QUrl:
1180 return value.toUrl().toEncoded();
1181
1182 default:
1183 return value.toByteArray();
1184 }
1185
1188 switch (value.userType()) {
1189 // Generate RFC 1123/822 dates:
1190 case QMetaType::QDate:
1191 return QNetworkHeadersPrivate::toHttpDate(value.toDate().startOfDay(QTimeZone::UTC));
1192 case QMetaType::QDateTime:
1193 return QNetworkHeadersPrivate::toHttpDate(value.toDateTime());
1194
1195 default:
1196 return value.toByteArray();
1197 }
1198
1201
1204
1205 default:
1206 Q_UNREACHABLE_RETURN({});
1207 }
1208}
1209
1210static int parseHeaderName(QByteArrayView headerName)
1211{
1212 if (headerName.isEmpty())
1213 return -1;
1214
1215 auto is = [headerName](QByteArrayView what) {
1216 return headerName.compare(what, Qt::CaseInsensitive) == 0;
1217 };
1218
1219 switch (QtMiscUtils::toAsciiLower(headerName.front())) {
1220 case 'c':
1221 if (is("content-type"))
1223 else if (is("content-length"))
1225 else if (is("cookie"))
1227 else if (is("content-disposition"))
1229 break;
1230
1231 case 'e':
1232 if (is("etag"))
1234 break;
1235
1236 case 'i':
1237 if (is("if-modified-since"))
1239 if (is("if-match"))
1241 if (is("if-none-match"))
1243 break;
1244
1245 case 'l':
1246 if (is("location"))
1248 else if (is("last-modified"))
1250 break;
1251
1252 case 's':
1253 if (is("set-cookie"))
1255 else if (is("server"))
1257 break;
1258
1259 case 'u':
1260 if (is("user-agent"))
1262 break;
1263 }
1264
1265 return -1; // nothing found
1266}
1267
1269{
1271 if (dt.isValid())
1272 return dt;
1273 return QVariant(); // transform an invalid QDateTime into a null QVariant
1274}
1275
1276static QList<QNetworkCookie> parseCookieHeader(QByteArrayView raw)
1277{
1278 QList<QNetworkCookie> result;
1279 for (auto cookie : QLatin1StringView(raw).tokenize(';'_L1)) {
1280 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed());
1281 if (parsed.size() != 1)
1282 return {}; // invalid Cookie: header
1283
1284 result += parsed;
1285 }
1286
1287 return result;
1288}
1289
1291{
1292 const QByteArrayView trimmed = raw.trimmed();
1293 if (!trimmed.startsWith('"') && !trimmed.startsWith(R"(W/")"))
1294 return QVariant();
1295
1296 if (!trimmed.endsWith('"'))
1297 return QVariant();
1298
1299 return QString::fromLatin1(trimmed);
1300}
1301
1302template<typename T>
1304{
1305 const QByteArrayView trimmedRaw = raw.trimmed();
1306 if (trimmedRaw == "*")
1307 return QStringList(QStringLiteral("*"));
1308
1309 QStringList tags;
1310 for (auto &element : QLatin1StringView(trimmedRaw).tokenize(','_L1)) {
1311 if (const auto trimmed = element.trimmed(); op(trimmed))
1312 tags += QString::fromLatin1(trimmed);
1313 }
1314 return tags;
1315}
1316
1317
1319{
1320 return parseMatchImpl(raw, [](QByteArrayView element) {
1321 return element.startsWith('"') && element.endsWith('"');
1322 });
1323}
1324
1326{
1327 return parseMatchImpl(raw, [](QByteArrayView element) {
1328 return (element.startsWith('"') || element.startsWith(R"(W/")")) && element.endsWith('"');
1329 });
1330}
1331
1332
1334{
1335 // header is always a valid value
1336 switch (header) {
1341 // copy exactly, convert to QString
1342 return QString::fromLatin1(value);
1343
1345 bool ok;
1347 if (ok)
1348 return result;
1349 return QVariant();
1350 }
1351
1354 if (result.isValid() && !result.scheme().isEmpty())
1355 return result;
1356 return QVariant();
1357 }
1358
1361 return parseHttpDate(value);
1362
1364 return parseETag(value);
1365
1367 return parseIfMatch(value);
1368
1370 return parseIfNoneMatch(value);
1371
1374
1377
1378 default:
1379 Q_UNREACHABLE_RETURN({});
1380 }
1381}
1382
1384{
1385 if (values.empty())
1386 return QVariant();
1387
1388 // header is always a valid value
1389 switch (header) {
1392 for (const auto &val : values)
1393 res << parseIfMatch(val);
1394 return res;
1395 }
1398 for (const auto &val : values)
1400 return res;
1401 }
1404 return listOpt.has_value() ? QVariant::fromValue(listOpt.value()) : QVariant();
1405 }
1407 QList<QNetworkCookie> res;
1408 for (const auto &val : values)
1410 return QVariant::fromValue(res);
1411 }
1412 default:
1413 return parseHeaderValue(header, values.first());
1414 }
1415 return QVariant();
1416}
1417
1423
1428
1429template<class HeaderName>
1432{
1433 headers.removeAll(header);
1434
1435 if (value.isNull())
1436 // only wanted to erase key
1437 return;
1438
1439 if (isSetCookie(header)) {
1440 for (auto cookie : QLatin1StringView(value).tokenize('\n'_L1))
1442 } else {
1443 headers.append(header, value);
1444 }
1445}
1446
1448{
1449 if (rawHeaderCache.isCached)
1450 return rawHeaderCache.headersList;
1451
1453 rawHeaderCache.isCached = true;
1454 return rawHeaderCache.headersList;
1455}
1456
1458{
1459 if (httpHeaders.isEmpty())
1460 return {};
1461
1462 QList<QByteArray> result;
1463 result.reserve(httpHeaders.size());
1464 QDuplicateTracker<QByteArray> seen(httpHeaders.size());
1465
1466 for (qsizetype i = 0; i < httpHeaders.size(); i++) {
1467 const auto nameL1 = httpHeaders.nameAt(i);
1468 const auto name = QByteArray(nameL1.data(), nameL1.size());
1469 if (seen.hasSeen(name))
1470 continue;
1471
1472 result << name;
1473 }
1474
1475 return result;
1476}
1477
1479{
1482 if (QAnyStringView::compare(headerName, setCookieStr, Qt::CaseInsensitive) != 0)
1483 return httpHeaders.combinedValue(headerName);
1484
1486 const char* separator = "";
1487 for (qsizetype i = 0; i < httpHeaders.size(); ++i) {
1489 result.append(separator);
1490 result.append(httpHeaders.valueAt(i));
1491 separator = "\n";
1492 }
1493 }
1494 return result;
1495}
1496
1498{
1499 if (key.isEmpty())
1500 // refuse to accept an empty raw header
1501 return;
1502
1504 parseAndSetHeader(key, value);
1505
1506 invalidateHeaderCache();
1507}
1508
1510 const QVariant &value)
1511{
1512 const auto wellKnownOpt = toWellKnownHeader(header);
1513 if (!wellKnownOpt) {
1514 // verifies that \a header is a known value
1515 qWarning("QNetworkRequest::setHeader: invalid header value KnownHeader(%d) received", header);
1516 return;
1517 }
1518
1519 if (value.isNull()) {
1520 httpHeaders.removeAll(wellKnownOpt.value());
1522 } else {
1523 QByteArray rawValue = headerValue(header, value);
1524 if (rawValue.isEmpty()) {
1525 qWarning("QNetworkRequest::setHeader: QVariant of type %s cannot be used with header %s",
1526 value.typeName(),
1527 QHttpHeaders::wellKnownHeaderName(wellKnownOpt.value()).constData());
1528 return;
1529 }
1530
1531 setFromRawHeader(httpHeaders, wellKnownOpt.value(), rawValue);
1533 }
1534
1535 invalidateHeaderCache();
1536}
1537
1542
1544{
1545 httpHeaders = newHeaders;
1546 setCookedFromHttp(httpHeaders);
1547 invalidateHeaderCache();
1548}
1549
1551{
1552 httpHeaders = std::move(newHeaders);
1553 setCookedFromHttp(httpHeaders);
1554 invalidateHeaderCache();
1555}
1556
1558{
1560
1561 // set cooked header
1562 const auto knownHeaderOpt = toKnownHeader(name);
1563 if (knownHeaderOpt)
1564 parseAndSetHeader(knownHeaderOpt.value(), value);
1565
1566 invalidateHeaderCache();
1567}
1568
1570{
1573 invalidateHeaderCache();
1574}
1575
1576void QNetworkHeadersPrivate::parseAndSetHeader(QByteArrayView key, QByteArrayView value)
1577{
1578 // is it a known header?
1579 const int parsedKeyAsInt = parseHeaderName(key);
1580 if (parsedKeyAsInt != -1) {
1581 const QNetworkRequest::KnownHeaders parsedKey
1582 = static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1583 parseAndSetHeader(parsedKey, value);
1584 }
1585}
1586
1587void QNetworkHeadersPrivate::parseAndSetHeader(QNetworkRequest::KnownHeaders key,
1589{
1590 if (value.isNull()) {
1594 // Only set the cooked header "Content-Length" once.
1595 // See bug QTBUG-15311
1596 } else {
1598 }
1599}
1600
1601// Fast month string to int conversion. This code
1602// assumes that the Month name is correct and that
1603// the string is at least three chars long.
1604static int name_to_month(const char* month_str)
1605{
1606 switch (month_str[0]) {
1607 case 'J':
1608 switch (month_str[1]) {
1609 case 'a':
1610 return 1;
1611 case 'u':
1612 switch (month_str[2] ) {
1613 case 'n':
1614 return 6;
1615 case 'l':
1616 return 7;
1617 }
1618 }
1619 break;
1620 case 'F':
1621 return 2;
1622 case 'M':
1623 switch (month_str[2] ) {
1624 case 'r':
1625 return 3;
1626 case 'y':
1627 return 5;
1628 }
1629 break;
1630 case 'A':
1631 switch (month_str[1]) {
1632 case 'p':
1633 return 4;
1634 case 'u':
1635 return 8;
1636 }
1637 break;
1638 case 'O':
1639 return 10;
1640 case 'S':
1641 return 9;
1642 case 'N':
1643 return 11;
1644 case 'D':
1645 return 12;
1646 }
1647
1648 return 0;
1649}
1650
1652{
1653 // HTTP dates have three possible formats:
1654 // RFC 1123/822 - ddd, dd MMM yyyy hh:mm:ss "GMT"
1655 // RFC 850 - dddd, dd-MMM-yy hh:mm:ss "GMT"
1656 // ANSI C's asctime - ddd MMM d hh:mm:ss yyyy
1657 // We only handle them exactly. If they deviate, we bail out.
1658
1659 int pos = value.indexOf(',');
1660 QDateTime dt;
1661#if QT_CONFIG(datestring)
1662 if (pos == -1) {
1663 // no comma -> asctime(3) format
1664 dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
1665 } else {
1666 // Use sscanf over QLocal/QDateTimeParser for speed reasons. See the
1667 // Qt WebKit performance benchmarks to get an idea.
1668 if (pos == 3) {
1669 char month_name[4];
1670 int day, year, hour, minute, second;
1671#ifdef Q_CC_MSVC
1672 // Use secure version to avoid compiler warning
1673 if (sscanf_s(value.constData(), "%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, 4, &year, &hour, &minute, &second) == 6)
1674#else
1675 // The POSIX secure mode is %ms (which allocates memory), too bleeding edge for now
1676 // In any case this is already safe as field width is specified.
1677 if (sscanf(value.constData(), "%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
1678#endif
1679 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
1680 } else {
1681 QLocale c = QLocale::c();
1682 // eat the weekday, the comma and the space following it
1683 QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
1684 // must be RFC 850 date
1685 dt = c.toDateTime(sansWeekday, "dd-MMM-yy hh:mm:ss 'GMT'"_L1);
1686 }
1687 }
1688#endif // datestring
1689
1690 if (dt.isValid())
1691 dt.setTimeZone(QTimeZone::UTC);
1692 return dt;
1693}
1694
1696{
1697 return QLocale::c().toString(dt.toUTC(), u"ddd, dd MMM yyyy hh:mm:ss 'GMT'").toLatin1();
1698}
1699
1701 const QHttpHeaders &headers)
1702{
1703 if (headers.isEmpty())
1704 return {};
1705
1707 QHash<QByteArray, qsizetype> nameToIndex;
1709 nameToIndex.reserve(headers.size());
1710
1711 for (qsizetype i = 0; i < headers.size(); ++i) {
1712 const auto nameL1 = headers.nameAt(i);
1713 const auto value = headers.valueAt(i);
1714
1715 const bool isSetCookie = nameL1 == QHttpHeaders::wellKnownHeaderName(
1717
1718 const auto name = QByteArray(nameL1.data(), nameL1.size());
1719 if (auto it = nameToIndex.find(name); it != nameToIndex.end()) {
1720 list[it.value()].second += isSetCookie ? "\n" : ", ";
1721 list[it.value()].second += value;
1722 } else {
1723 nameToIndex[name] = list.size();
1724 list.emplaceBack(name, value.toByteArray());
1725 }
1726 }
1727
1728 return list;
1729}
1730
1732{
1733 if (raw.empty())
1734 return {};
1735
1737 headers.reserve(raw.size());
1738
1739 for (const auto &[key, value] : raw) {
1742 Qt::CaseInsensitive) == 0;
1743 if (isSetCookie) {
1744 for (auto header : QLatin1StringView(value).tokenize('\n'_L1))
1746 } else {
1748 }
1749 }
1750
1751 return headers;
1752}
1753
1755{
1756 if (value.empty())
1757 return std::nullopt;
1758
1759 bool ok;
1760 qint64 res = value.toLongLong(&ok);
1761 if (ok)
1762 return res;
1763 return std::nullopt;
1764}
1765
1766std::optional<QNetworkHeadersPrivate::NetworkCookieList> QNetworkHeadersPrivate::toSetCookieList(
1767 const QList<QByteArray> &values)
1768{
1769 if (values.empty())
1770 return std::nullopt;
1771
1772 QList<QNetworkCookie> cookies;
1773 for (const auto &s : values)
1774 cookies += QNetworkCookie::parseCookies(s);
1775
1776 if (cookies.empty())
1777 return std::nullopt;
1778 return cookies;
1779}
1780
1781QByteArray QNetworkHeadersPrivate::fromCookieList(const QList<QNetworkCookie> &cookies)
1782{
1784}
1785
1786std::optional<QNetworkHeadersPrivate::NetworkCookieList> QNetworkHeadersPrivate::toCookieList(
1787 const QList<QByteArray> &values)
1788{
1789 if (values.empty())
1790 return std::nullopt;
1791
1792 QList<QNetworkCookie> cookies;
1793 for (const auto &s : values)
1794 cookies += parseCookieHeader(s);
1795
1796 if (cookies.empty())
1797 return std::nullopt;
1798 return cookies;
1799}
1800
1801void QNetworkHeadersPrivate::invalidateHeaderCache()
1802{
1803 rawHeaderCache.headersList.clear();
1804 rawHeaderCache.isCached = false;
1805}
1806
1807void QNetworkHeadersPrivate::setCookedFromHttp(const QHttpHeaders &newHeaders)
1808{
1810
1811 QMap<QNetworkRequest::KnownHeaders, QList<QByteArray>> multipleHeadersMap;
1812 for (int i = 0; i < newHeaders.size(); ++i) {
1813 const auto name = newHeaders.nameAt(i);
1814 const auto value = newHeaders.valueAt(i);
1815
1816 const int parsedKeyAsInt = parseHeaderName(name);
1817 if (parsedKeyAsInt == -1)
1818 continue;
1819
1820 const QNetworkRequest::KnownHeaders parsedKey
1821 = static_cast<QNetworkRequest::KnownHeaders>(parsedKeyAsInt);
1822
1823 auto &list = multipleHeadersMap[parsedKey];
1824 list.append(value.toByteArray());
1825 }
1826
1827 for (auto i = multipleHeadersMap.cbegin(), end = multipleHeadersMap.cend(); i != end; ++i)
1828 cookedHeaders.insert(i.key(), parseHeaderValue(i.key(), i.value()));
1829}
1830
1832
1833#include "moc_qnetworkrequest.cpp"
\inmodule QtCore
static Q_CORE_EXPORT int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
Compares the string view lhs with the string view rhs and returns a negative integer if lhs is less t...
Definition qstring.cpp:1599
bool startsWith(QByteArrayView other) const noexcept
qlonglong toLongLong(bool *ok=nullptr, int base=10) const
bool endsWith(QByteArrayView other) const noexcept
constexpr qsizetype size() const noexcept
constexpr void chop(qsizetype n)
QByteArrayView trimmed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
\inmodule QtCore\reentrant
Definition qdatetime.h:283
\inmodule QtCore \reentrant
Definition qdatetime.h:29
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:958
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1007
T value(const Key &key) const noexcept
Definition qhash.h:1054
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:951
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
The QHttp1Configuration class controls HTTP/1 parameters and settings.
The QHttp2Configuration class controls HTTP/2 parameters and settings.
Q_NETWORK_EXPORT qsizetype size() const noexcept
Returns the number of header entries.
Q_NETWORK_EXPORT void clear()
Clears all header entries.
bool isEmpty() const noexcept
Returns true if the headers have size 0; otherwise returns false.
Q_NETWORK_EXPORT bool contains(QAnyStringView name) const
Returns whether the headers contain header with name.
Q_NETWORK_EXPORT bool append(QAnyStringView name, QAnyStringView value)
Appends a header entry with name and value and returns true if successful.
Q_NETWORK_EXPORT void removeAll(QAnyStringView name)
Removes the header name.
Q_NETWORK_EXPORT bool replaceOrAppend(QAnyStringView name, QAnyStringView newValue)
Q_NETWORK_EXPORT QLatin1StringView nameAt(qsizetype i) const noexcept
Returns the header name at index i.
WellKnownHeader
List of well known headers as per \l {https://www.iana.org/assignments/http-fields}{IANA registry}.
Q_NETWORK_EXPORT void reserve(qsizetype size)
Attempts to allocate memory for at least size header entries.
Q_NETWORK_EXPORT QByteArrayView value(QAnyStringView name, QByteArrayView defaultValue={}) const noexcept
Returns the value of the (first) header name, or defaultValue if it doesn't exist.
Q_NETWORK_EXPORT QByteArray combinedValue(QAnyStringView name) const
Returns the values of header name in a comma-combined string.
Q_NETWORK_EXPORT QByteArrayView valueAt(qsizetype i) const noexcept
Returns the header value at index i.
static Q_NETWORK_EXPORT QByteArrayView wellKnownHeaderName(WellKnownHeader name) noexcept
Returns a header name corresponding to the provided name as a view.
constexpr auto tokenize(Needle &&needle, Flags...flags) const noexcept(noexcept(qTokenize(std::declval< const QLatin1StringView & >(), std::forward< Needle >(needle), flags...))) -> decltype(qTokenize(*this, std::forward< Needle >(needle), flags...))
qsizetype size() const noexcept
Definition qlist.h:397
reference emplaceBack(Args &&... args)
Definition qlist.h:882
void reserve(qsizetype size)
Definition qlist.h:753
void append(parameter_type t)
Definition qlist.h:458
static QLocale c()
Returns a QLocale object initialized to the "C" locale.
Definition qlocale.h:1146
The QNetworkCookie class holds one network cookie.
static QList< QNetworkCookie > parseCookies(QByteArrayView cookieString)
Parses the cookie string cookieString as received from a server response in the "Set-Cookie:" header.
RawForm
This enum is used with the toRawForm() function to declare which form of a cookie shall be returned.
QByteArray rawHeader(QAnyStringView headerName) const
struct QNetworkHeadersPrivate::@400 rawHeaderCache
static std::optional< qint64 > toInt(QByteArrayView value)
static QHttpHeaders fromRawToHttp(const RawHeadersList &raw)
static QByteArray fromCookieList(const NetworkCookieList &cookies)
void setCookedHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
QPointer< QObject > originatingObject
QList< QByteArray > rawHeadersKeys() const
static RawHeadersList fromHttpToRaw(const QHttpHeaders &headers)
static std::optional< NetworkCookieList > toCookieList(const QList< QByteArray > &values)
QHttpHeaders headers() const
static std::optional< NetworkCookieList > toSetCookieList(const QList< QByteArray > &values)
void setHeaders(const QHttpHeaders &newHeaders)
const RawHeadersList & allRawHeaders() const
void setRawHeader(const QByteArray &key, const QByteArray &value)
void setHeader(QHttpHeaders::WellKnownHeader name, QByteArrayView value)
static QByteArray toHttpDate(const QDateTime &dt)
static QDateTime fromHttpDate(QByteArrayView value)
CookedHeadersMap cookedHeaders
\variable QNetworkRequest::DefaultTransferTimeout
std::chrono::milliseconds transferTimeout
QSslConfiguration * sslConfiguration
bool operator==(const QNetworkRequestPrivate &other) const
QNetworkRequest::Priority priority
QNetworkRequestPrivate(const QNetworkRequestPrivate &other)
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
bool operator==(const QNetworkRequest &other) const
Returns true if this object is the same as other (i.e., if they have the same URL,...
void setOriginatingObject(QObject *object)
KnownHeaders
List of known header types that QNetworkRequest parses.
void setHeaders(const QHttpHeaders &newHeaders)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void setSslConfiguration(const QSslConfiguration &configuration)
Sets this network request's SSL configuration to be config.
~QNetworkRequest()
Disposes of the QNetworkRequest object.
void setHeader(KnownHeaders header, const QVariant &value)
Sets the value of the known header header to be value, overriding any previously set headers.
bool hasRawHeader(QAnyStringView headerName) const
Returns true if the raw header headerName is present in this network request.
void setAttribute(Attribute code, const QVariant &value)
Sets the attribute associated with code code to be value value.
Priority priority() const
QVariant attribute(Attribute code, const QVariant &defaultValue=QVariant()) const
Returns the attribute associated with the code code.
QVariant header(KnownHeaders header) const
Returns the value of the known network header header if it is present in this request.
void setRawHeader(const QByteArray &headerName, const QByteArray &value)
Sets the header headerName to be of value headerValue.
QNetworkRequest()
Constructs a QNetworkRequest object with no URL to be requested.
QObject * originatingObject() const
static constexpr auto DefaultTransferTimeout
int maximumRedirectsAllowed() const
QByteArray rawHeader(QAnyStringView headerName) const
Returns the raw form of header headerName.
QList< QByteArray > rawHeaderList() const
Returns a list of all raw headers that are set in this network request.
QNetworkRequest & operator=(QNetworkRequest &&other) noexcept
void setPeerVerifyName(const QString &peerName)
QHttpHeaders headers() const
void setMaximumRedirectsAllowed(int maximumRedirectsAllowed)
void setUrl(const QUrl &url)
Sets the URL this network request is referring to be url.
QUrl url() const
Returns the URL this network request is referring to.
void setPriority(Priority priority)
QString peerVerifyName() const
QSslConfiguration sslConfiguration() const
Returns this network request's SSL configuration.
\inmodule QtCore
Definition qobject.h:103
T * data() const noexcept
Definition qpointer.h:73
\inmodule QtCore
Definition qshareddata.h:19
The QSslConfiguration class holds the configuration and state of an SSL connection.
static QSslConfiguration defaultConfiguration()
Returns the default SSL configuration to be used in new SSL connections.
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
\inmodule QtCore \reentrant
Definition qdatetime.h:215
\inmodule QtCore
Definition qurl.h:94
@ StrictMode
Definition qurl.h:98
static QUrl fromEncoded(QByteArrayView input, ParsingMode mode=TolerantMode)
Parses input and returns the corresponding QUrl.
Definition qurl.cpp:2988
\inmodule QtCore
Definition qvariant.h:65
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:536
QSet< QString >::iterator it
const qint32 qtDefaultStreamReceiveWindowSize
const qint32 maxSessionReceiveWindowSize((quint32(1)<< 31) - 1)
Q_NETWORK_EXPORT bool compareStrict(const QHttpHeaders &left, const QHttpHeaders &right)
Combined button and popup list for selecting options.
constexpr char toAsciiLower(char ch) noexcept
Definition qtools_p.h:87
@ TextDate
@ CaseInsensitive
constexpr bool is_sorted(ForwardIterator first, ForwardIterator last, BinaryPredicate p={})
QList< QString > QStringList
Constructs a string list that contains the given string, str.
static QString header(const QString &name)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLConfig config
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1384
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1390
static int parseHeaderName(const QByteArray &headerName)
static int name_to_month(const char *month_str)
static QStringList parseMatchImpl(QByteArrayView raw, T op)
static constexpr HeaderPair knownHeadersArr[]
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)
GLenum GLsizei GLsizei GLint * values
[15]
GLuint64 key
GLuint GLuint end
GLuint object
[3]
GLenum type
GLuint name
GLdouble s
[6]
Definition qopenglext.h:235
GLuint res
const GLubyte * c
GLuint GLfloat * val
GLuint64EXT * result
[6]
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
#define QStringLiteral(str)
ptrdiff_t qsizetype
Definition qtypes.h:165
long long qint64
Definition qtypes.h:60
QList< int > list
[14]
QUrl url("example.com")
[constructor-url-reference]
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]