Replace QNetworkHeadersPrivate's main headers storage, which was
RawHeadersList, with QHttpHeaders. Replace internal usage of raw and
cooked header methods with the QHttpHeaders API.
[ChangeLog][QtNetwork][QNetworkRequest] Header value added by
QNetworkRequest::setRawHeader() method is trimmed now.
Task-number: QTBUG-107751
Change-Id: I8882978afa430651e6c798a4fed00beef6c4cfd2
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Now developer build tests compile, but some are not working.
Functional fix will come later via separate tasks.
Task-number: QTBUG-122999
Change-Id: I70487b46c1b32ba4279cb02a4978e4f55ac0d310
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
As part of QTBUG-114647 we are planning to introduce a deduction
mechanism that could deduce the contentType header and the
contentDisposition headers based on the arguments (and the MIME
database).
In case of non-trivial types this deduction may give the wrong result
and without QDebug support it might be a bit tedious to check.
The debug output displays some information about the body device if
one is attached, otherwise it displays the size of the body.
Task-number: QTBUG-114647
Change-Id: Ia693b078ff5b9f8ea57fbf3c385edaec47886ff1
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
On Linux root user has access rights to all files so it makes no sense
to verify socket file permissions.
Task-number: QTBUG-118680
Change-Id: I94a95e80c311f8d5cd6c799b1a76ffaaab7d9167
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This is RFC2822 grammar (except that line folding is not
allowed).
RFC9110 doesn't allow it anymore, but it might make sense to accept it
nonetheless (Postel's Law).
Pick-to: 6.7
Task-number: QTBUG-123544
Change-Id: Ie990cd332c7603dbdae29c19b2804bd33a058ca0
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
[ChangeLog][QtNetwork][QNetworkCacheMetaData] Added headers() and
setHeaders() methods to QNetworkCacheMetaData to provide an interface
to work with QHttpHeaders.
Task-number: QTBUG-107751
Change-Id: I1dfed5c2e03f4912de0da96156425cd6b713c1d5
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Added headers() and setHeaders() methods to QNetworkRequest.
[ChangeLog][QtNetwork][QNetworkRequest] Added headers() and setHeaders()
methods to QNetworkRequest, which provide an interface to work with
QHttpHeaders.
Task-number: QTBUG-107751
Change-Id: I2e1dc7cb2efab5903eb7ff23b75d01aefe13273d
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
The old code was based on QString::split and e.g. didn't handle
escapes in quoted-strings.
Write a modern recursive-descent parser to parse out type/subtype and
charset parameter. Since we don't, yet, support CFWS (see below),
recursion depth is strictly limited, so we're not susceptible to
recursion bombs here.
It currently handles only RFC9110-style grammar, but can be easily
extended to support CFWS (RFC2822-style comments and folding
white-space) or RFC2231-style continuuations, if needed.
It's a bit more general than strictly required, because I expect this
to be reused elsewhere ere long.
Pick-to: 6.7
Fixes: QTBUG-120307
Change-Id: I309928dc350a043672dffb4a259b457764c031be
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
... incl. some that fail.
This is in preparation of a patch that makes the parser more
compliant.
Pick-to: 6.7
Task-number: QTBUG-120307
Change-Id: Ic47b23132f2a7ea81b6c480bfb036bc2daff05da
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
The DNS servers from Google and CloudFare are probably stable enough
over the long-term.
Change-Id: I455fe22ef4ad4b2f9b01fffd17c748dc1233bc1b
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
If the file exists, we are using systemd-resolved, so let's try directly
using the nameservers it uses.
Change-Id: I455fe22ef4ad4b2f9b01fffd17c7476a2385bf4b
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This is a major simplification to use only one column in the QtTest
tables for the results, which makes it far easier to read the code as
well as to add more record types.
Change-Id: I455fe22ef4ad4b2f9b01fffd17c745d13c9c4037
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This will allow making lookup() require positive results only.
Change-Id: I455fe22ef4ad4b2f9b01fffd17c740e36002d25e
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
When using writeDatagram(QNetworkDatagram), the sendmsg() call on
FreeBSD is failing. It works on Linux and on macOS, so my guess is that
IP_PKTINFO works to set the sender address but IP_SENDSRCADDR is not
allowed in this context for some reason.
Before:
recvmsg(5,{{ AF_INET 127.0.0.1:19530 },16,[{"H\M-p\^A\0\0\^A\0\0\0\0\0\^A\tso"...,49}],1,{{level=IPPROTO_IP,type=IP_RECVDSTADDR,data={0x7f,0x00,0x00,0x01}},{level=IPPROTO_IP,type=IP_RECVTTL,data={0x40}}},48,0},0) = 49 (0x31)
sendmsg(5,{{ AF_INET 127.0.0.1:19530 },16,[{"H\M-p\M^@\^C\0\^A\0\0\0\0\0\^A\t"...,49}],1,{{level=IPPROTO_IP,type=IP_RECVDSTADDR,data={0x7f,0x00,0x00,0x01}}},24,0},MSG_NOSIGNAL) ERR#22 'Invalid argument'
After:
recvmsg(5,{{ AF_INET 127.0.0.1:16018 },16,[{"\^U\M-X\^A\0\0\^A\0\0\0\0\0\^A\t"...,49}],1,{{level=IPPROTO_IP,type=IP_RECVDSTADDR,data={0x7f,0x00,0x00,0x01}},{level=IPPROTO_IP,type=IP_RECVTTL,data={0x40}}},48,0},0) = 49 (0x31)
sendmsg(5,{{ AF_INET 127.0.0.1:16018 },16,[{"\^U\M-X\M^@\^C\0\^A\0\0\0\0\0\^A"...,49}],1,{},0,0},MSG_NOSIGNAL) = 49 (0x31)
Pick-to: 6.7
Change-Id: I455fe22ef4ad4b2f9b01fffd17c77565e230ce31
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
0x80 is too big for a signed char (range is -0x80 to 0x7f).
Pick-to: 6.7
Change-Id: I455fe22ef4ad4b2f9b01fffd17c7746f4ea3c536
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
When adding/fixing parts earlier it was missed that it was not handling
the _unsupported_ case, when authentication is not handled and there is
no resend. But there _is_ a challenge header.
Pick-to: 6.7 6.6 6.5
Fixes: QTBUG-123891
Change-Id: I21470df0ce2528bad3babffc6e9f19b7afd29d20
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Virtually all callers of this function (will) pass rvalues, so take
the std::function by value (reaping C++17 guaranteed copy elision) and
std::move() into the member variable ("perfect sink").
Like for many owning types, moves are much cheaper than copies for
std::function, because the external state is merely tranferred between
objects, and not copied.
Amends e560adef21.
Pick-to: 6.7
Change-Id: I269b54e51ba09ac595ac4e4f255209778819adad
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
HttpTestServer::Handler is declared to take the first argument by
reference to const, not by value, so use the same parameter passing
for the lambdas passed to setHandler().
Avoids copying the (rather large) argument when invoked through the
std::function wrapper, and silences clazy-function-args-by-ref.
Pick-to: 6.7
Change-Id: I726d0b98a7fcb3b1b33c5bde203035f593c39bdd
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Move some deleteLater() calls to before the first QCOMPARE/QVERIFY
macros, so they get executed even if the macros return on failure.
This isn't an all-encompassing solution, but I lack the time to port
all this to smart pointers, and this is some improvement.
As a drive-by, port QVERIFY(opt.has_value()) to QCOMPARE(opt, nullopt).
Task-number: QTBUG-120307
Pick-to: 6.7
Change-Id: Ia5a2cabd273a779938b22badc91b109fcc545203
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
We want to get rid of the other one, it's all internal
API anyway.
Task-number: QTBUG-102855
Change-Id: I2b621c20f4dd7c8bf5f07db8db908c2b7b86976f
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
In some cases calls to QFile::open are made outside of a testfunction
(so we can't use QVERIFY), or even in standalone executables that are
executed by tests. Make them fail "visibly".
Change-Id: Iec4d56f6d874be16aa2e9ad6974eeec2a98caa3f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
It was overlooked in testing, but it would emit a signal for new
incoming stream even if the server was just replying with HEADERS on a
stream the client had initiated. Or vice-versa.
Pick-to: 6.7
Change-Id: Ie7b3a45729a78106da1d8c058e15705cc7dcc53b
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Wrap the call in QVERIFY.
tst_QTextStream::read0d0d0a was also faulty as it *never* opened
the file because of a broken path. Fix it with QFINDTESTDATA.
Change-Id: I61a8f83beddf098d37fda13cb3bfb4aaa4913fc5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
The old code allocated QSignalSpies on the heap and stored them in a
non-owning container, so if one of the many check macros trigger,
those objects would be leaked. Ditto QNetworkReplies. The code also
used dynamically-sized containers for statically-sized data; a common
anti-pattern.
Hold the sample QUrls in a C array instead, QSignalSpies in C arrays
of std::optional (to delay initialization) and QNetworkReplies in a C
array of std::unique_ptr with the existing QScopedPointerDeleteLater
deleter.
Pick-to: 6.7
Change-Id: I7305115af15c079abba6d45c5de8db2198ea7a6d
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Turn the QSignalSpy deletions from deferred (via deleteLater()) into
immediate ones. This is ok: QSignalSpy is using itself as a context
object in QMetaObject::connect(), so the connection thus established
to the monitored signal will be atomically severed if either sender or
receiver are destroyed. There never was a need to defer deletion of
the signal spy, so don't.
Found by making QSignalSpy's inheritance from QObject private.
Pick-to: 6.7 6.6 6.5
Change-Id: I962d28c3a78f356d234324fed68716f2f1052100
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
We have implemented the same functionality recently for POST, in this
patch implement it for PUT.
Task-number: QTBUG-108309
Change-Id: I34c41538054fec836d0d1d1dbb44fabab9bc0e9a
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Actually this has already worked if a nullptr was casted as a
QIODevice*. Add an overload with a nullptr_t type, that does
this behind the scenes.
Fixes: QTBUG-108309
Change-Id: I2d4b17ae94cf4de2c42257d471ef901c8994fee5
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
It is failing a bunch on macOS in CI, but not locally.
So just assuming the timings are too tight in CI and increasing
them.
Amends 8de1ed8979
Pick-to: 6.7
Change-Id: Icb44fdbd2aa117de7350c5df2e8351bb19c865c4
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
It was not setting the value _back_ to 0 when the function ended
and this caused qtbug68821proxyError to fail fairly consistently
on Windows when it was running in the same run.
qtbug68821proxyError was always succeeding when ran by itself so
it was quite odd.
Pick-to: 6.7
Change-Id: Ifa4982f1b10128674081136a30bdab4b0ce7004a
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
That seems to be enough for me when trying to reverse-resolve host names
inside the corporate network.
Pick-to: 6.7
Change-Id: I6818d78a57394e37857bfffd17bc6b0ebd39f51b
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Because QHostInfo is threaded, so if the look up times out and we exit a
given test, the results may still be delivered to the next test.
Especially if the next test is also about to time out -- in which case
it doesn't and prints a nonsensical output.
Before:
FAIL! : tst_QHostInfo::lookupIPv4(WithCache:literal_ip4) '!QTestEventLoop::instance().timeout()' returned FALSE. ()
Loc: [tst_qhostinfo.cpp(220)]
FAIL! : tst_QHostInfo::lookupIPv6(WithCache:aaaa-single) Compared values are not the same
Actual (tmp.join(' ').toLower()) : "192.0.2.1"
Expected (expected.join(' ').toLower()): "2001:db8::1"
Loc: [tst_qhostinfo.cpp(281)]
Now:
FAIL! : tst_QHostInfo::lookupIPv4(WithCache:literal_ip4) 'helper.waitForResults()' returned FALSE. ()
Loc: [tst_qhostinfo.cpp(278)]
PASS : tst_QHostInfo::lookupIPv6(WithCache:aaaa-single)
Pick-to: 6.7
Change-Id: I6818d78a57394e37857bfffd17bc66e241cab24d
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Because we will do a small wait after the final connection (to see
if there are any unexpected extra connections) we can save some time
by reducing _how long_ we wait for it.
In general we only need an extra long wait for the first connection,
subsequent connections are faster.
So we change the loop structure from looping until we hit 20(!)
connections, when anything larger than 6 will fail the test anyway!
And use qWaitFor instead of repeatedly calling enterLoop and checking
the state of an ElapsedTimer, the total wait time is not super
interesting, and made it a guarantee that the test would take 10
seconds.
While we are here, update the attribute we use to test HTTP/2
connections. We were previously enabling http/2, but this is the new
default so it's not needed. We do, however, need to enable h2c if we
want to see it trying to upgrade to http/2 over cleartext.
Not a big issue, so we don't pick it very far back.
Pick-to: 6.7
Change-Id: Ia314ae2827ab8a8baaa4af2c5136c5e531bcb1f8
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
There were a few issues to deal with. One of them was that we would
print a warning about an internal error if we tried to *set* an error
on the reply after it had been cancelled. That's kind of unavoidable
since these things happen in different threads, so just ignore the
error if we have been cancelled.
The other issue was that, for a request with data, we will buffer the
data to send, and _only then_ do we start the request. This happens
asynchronously, so the user can abort the request before it has finished
buffering. Once it finished buffering it would set the state of the
request to "Working", ignoring that it was already marked "Finished".
Fixes: QTBUG-118209
Fixes: QTBUG-36127
Pick-to: 6.7 6.6
Change-Id: Idbf1fd8a80530d802bee04c4b0a6783cba4992d3
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
The function replaces one of the found entries with the new value,
and removes any other entries. If no entries are found, a new entry
will be appended. The replacement search is done for performance
reasons; it's cheaper to replace an existing value.
All in all the function is a more convenient and performant
alternative for this sequence (which proved to be common while
porting QtNetwork internals to QHttpHeaders):
header.removeAll(<headername>);
header.append(<headername>, <value>);
[ChangeLog][QtNetwork][QHttpHeaders] Added replaceOrAppend()
convenience method, which either replaces previous entries with
a single entry, or appends a new one if no entries existed
Fixes: QTBUG-122175
Change-Id: I03957645d7e916a732ac7b8d3ae724bb6b16af87
Reviewed-by: Lena Biliaieva <lena.biliaieva@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
According to QUIP-18 [1], all tools file should be
LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
[1]: https://contribute.qt-project.org/quips/18
Pick-to: 6.7
Task-number: QTBUG-121787
Change-Id: Icd5d5be2e04819617e68ff142924de1773bebbad
Reviewed-by: Kai Köhne <kai.koehne@qt.io>
The current logic that we will disable the read notification if we
have any data at all doesn't make sense for users who use the
receiveDatagram functionality, since they will not make any calls
that trigger the read notifier to be re-enabled unless there is a
datagram ready for us to hand back.
Fixes: QTBUG-105871
Pick-to: 6.7 6.6 6.5
Change-Id: I0a1f1f8babb037d923d1124c2603b1cb466cfe18
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Make QHttp2ProtocolHandler discard all informational (1xx) replies with
the exception of 101.
According to RFC 9110:
"A client MUST be able to parse one or more 1xx responses received
prior to a final response, even if the client does not expect one.
A user agent MAY ignore unexpected 1xx responses."
Fixes: QTBUG-121755
Change-Id: I8b8d578f23d4fbe28929f8c54b3607bcaf85405f
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
The "HTTP RFC 9110 5.3 Field Order" states that the values combined
with comma can be followed up by an optional whitespace, and for
consistency recommends "comma SP". This is also what eg. 'MDN Web
Headers' class does.
Fixes: QTBUG-122650
Pick-to: 6.7
Change-Id: I3391c86018090f0b8721929b64a7e3029e98ac85
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
The test is a bit silly, it was originally written to make sure that
we produce meaningful errors when trying to connect to a proxy server
where the connection is refused or the server doesn't respond at all.
To test that, it creates a local QTcpServer and starts listening to any
free port (by specifying port 0) and then it closed the server and
uses the address-port of localhost:serverPort as the proxy to use, since
we know it _was_ unused, since we were able to bind to it.
However, just calling close() doesn't immediately tear down the internal
socket descriptor, so the OS may still have the port reserved for
some time.
By moving the QTcpServer to a narrower scope we will quickly destroy it
and the internal socket engine, which is parented to the server, and
this in turn releases the socket descriptor.
Pick-to: 6.7 6.6 6.5
Change-Id: If12128fc21d1f545df152f08f0d52c1b14ac6037
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
To enable setting a default priority for all requests to a given site.
Fixes: QTBUG-121669
Change-Id: Icd8a9c59e4afb0432c65f84cc8115ae0c7f85506
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
1XX statuses are not final statuses, and testing 'error' on it is not
necessarily very meaningful. Furthermore the internal handling of
these statuses changes in Qt 6.8.
Fixes: QTBUG-108068
Pick-to: 6.7
Change-Id: I9c18c579cd310266273eccd2aee2e032f60538e0
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Make QNetworkAccessManager to discard all informational (1xx) replies
from HTTP servers with the exception of 101.
According to RFC 9110:
"A client MUST be able to parse one or more 1xx responses received
prior to a final response, even if the client does not expect one.
A user agent MAY ignore unexpected 1xx responses."
Status code 101 is an exception because we use it to upgrade to http2
cleartext when it is enabled.
Fixes: QTBUG-108068
Change-Id: I415ff053180a43f0c7ff1b4b2a60fd114ce08ac9
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>