And adjust the encoding of 'name' parameter to always
use UTF-8 / ASCII. This aligns with how other frameworks
behave. Also amended docs to recommend ASCII for 'name'.
Found in API review.
Change-Id: I54d1148bf95dece54b75c76914c49985da05e0b2
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit 6b23a3c5e4316c5f889ea5e9bbfd785b78716268)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
The RFCs around these encodings are loose and allow
several ways for dealing with non-ASCII characters.
The encoding introduced in this commit should be
interoperable and aligns with other frameworks
(checked Curl, JS FormData, Postman, and Python
requests).
This consists of several adjustments:
1. Enclose the filename attribute in double quotes
2. If filename contains only ASCII characters, use them as-is
3. If filename contains characters beyond ASCII:
3.1. Encode them directly as raw UTF-8 to filename=
3.2. Set an additional filename*= parameter with
percent encoded UTF-8. This is a legacy encoding
for compatibility.
Task-number: QTBUG-125985
Change-Id: I5a6ad5388e4bb69e142caa7f6de7127526f441ad
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 8c8a0c06d4f77ba8a707ec0a101b423543bf30f0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Hide the construction details of QFormDataPartBuilder, change
the verification to be QString based instead of QByteArray based,
and use raw string literals (where useful) for readability.
Task-number: QTBUG-114647
Change-Id: I16fb6c943cf6fd7385e78bbffe3b2780ab0a6ac8
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit cb8abb718da4e18232de525ef1bb611f3a5dd929)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
UTF-8 doesn't per se contain illegal characters from
an HTTP header RFC point of view. UTF-8 is the dominant
character encoding outside of ASCII, and is used
directly at least with HTTP multipart headers.
[ChangeLog][QtNetwork][QHttpHeaders] Allows UTF-8 in header
values now.
Task-number: QTBUG-125985
Pick-to: 6.7
Change-Id: I2d8d8f00855c96c1d2ba190f2e27e2d48fcd4975
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit f39b39b8c72b5c3428396d5e74cf15cafd5bbc42)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
The test requires allocating 4GB of memory to handle a big file.
On a 32b architecture, this leads to a std::bad_alloc exception and
abort in result (tested on VxWorks 24.03 on an imx6 board).
Because of that, the test can't work properly and it can't be
blacklisted.
Work around the issue by skipping the test.
Pick-to: 6.7
Task-number: QTBUG-115777
Change-Id: I46002a27aed09706cd61d2e2c8d4bd1e12a16c36
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 4d2744e4345193cdf7ec2bbf06b0a0d169827d8b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Test the setHeaders method and the option of manually setting the mime
type.
Task-number: QTBUG-114647
Change-Id: I86644b243830259156e60239adf370e5894450dc
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
(cherry picked from commit 132498a69a626be6feaf1855cf63dd79d1ac9445)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Version 903a83ff7bfc3148e3692e09396f9f3bdc9462ef, fetched on
2024-06-05.
[ChangeLog][Third-Party Code] Updated the public suffix list to upstream
SHA 903a83ff7bfc3148e3692e09396f9f3bdc9462ef.
Pick-to: 6.7 6.5 6.2 5.15
Task-number: QTBUG-126060
Change-Id: I96320b5df1a3573ab9198ad412fc1eca55204c02
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit c0d5c1b2fef140a44b6512ee79ba7fb67187a39c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
We don't need the bodyName member, because it's the same as
originalBodyName, just encoded, and we can delay the encoding to
build() time.
This is not worse than the old code, since we anyway toString() the
QAnyStringView unconditionally.
So we don't need to visit the QASV and implement RFC2232 encoding for
all three view types, we can just use the QString version, after
toString().
This not only has the advantage of less code and not storing duplicate
data, but we now also encode u8"ä.txt" the same as "ä.txt"_L1 and
u"ä.txt", ie. using latin1, as required by Postel's Law, and not as
UTF-8, as the old code did.
Change-Id: If82a33a1cd09b859b3a4450a60083b1d3aedf7bc
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Constructing and composing a QHttpMultipart contains some aspects that
are possible candidates for automating, such as setting the headers
manually for each included part. As a reference, when issuing a default
multipart with CURL, one does not need to manually set the headers.
Add the class QFormDataPartBuilder to simplify the construction of
QHttpPart objects.
Add the class QFormDataBuilder to simplify the construction of
QHttpMultiPart objects.
[ChangeLog][QtNetwork][QFormDataBuilder] New class to help constructing
multipart/form-data QHttpMultiParts.
Fixes: QTBUG-114647
Change-Id: Ie035dabc01a9818d65a67c239807b50001fd984a
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
[ChangeLog][QtNetwork][QNetworkAccessManager] QNetworkAccessManager now
supports using full local server name, as in, named pipes on Windows or path to
socket objects on Unix.
Task-number: QTBUG-102855
Change-Id: Ifc743f5025b3d8d0b558ecffff437881897915d9
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Nothing there should rely on the network testing server.
Part of this will also be testing the local/unix domain socket support.
Task-number: QTBUG-102855
Change-Id: Icf3b0bd9370ec62e003862caf4cd3ed38d875bac
Reviewed-by: Mate Barany <mate.barany@qt.io>
Functional fix will come later via separate tasks.
Task-number: QTBUG-122999
Change-Id: Ib805740c87ff21cea5a186add71cc594ab4d4df1
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
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>
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>
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>
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>
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>