fix(http): Send multipart body for PUT (#6746)
This commit is contained in:
@@ -89,6 +89,7 @@
|
|||||||
- Dev: Refactored types used for emoji parsing. (#6714)
|
- Dev: Refactored types used for emoji parsing. (#6714)
|
||||||
- Dev: `LinkParser` now parses `QStringView`s. (#6715)
|
- Dev: `LinkParser` now parses `QStringView`s. (#6715)
|
||||||
- Dev: Cleaned up `AccountController` connections. (#6735)
|
- Dev: Cleaned up `AccountController` connections. (#6735)
|
||||||
|
- Dev: Send multipart body for HTTP `PUT` requests. (#6746)
|
||||||
- Dev: Removed unused variables. (#6748)
|
- Dev: Removed unused variables. (#6748)
|
||||||
|
|
||||||
## 2.5.4
|
## 2.5.4
|
||||||
|
|||||||
@@ -87,12 +87,24 @@ QNetworkReply *NetworkTask::createReply()
|
|||||||
case NetworkRequestType::Get:
|
case NetworkRequestType::Get:
|
||||||
return accessManager->get(request);
|
return accessManager->get(request);
|
||||||
|
|
||||||
case NetworkRequestType::Put:
|
|
||||||
return accessManager->put(request, data->payload);
|
|
||||||
|
|
||||||
case NetworkRequestType::Delete:
|
case NetworkRequestType::Delete:
|
||||||
return accessManager->deleteResource(data->request);
|
return accessManager->deleteResource(data->request);
|
||||||
|
|
||||||
|
case NetworkRequestType::Put:
|
||||||
|
if (data->multiPartPayload)
|
||||||
|
{
|
||||||
|
assert(data->payload.isNull());
|
||||||
|
|
||||||
|
return accessManager->put(request,
|
||||||
|
data->multiPartPayload.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(data->multiPartPayload == nullptr);
|
||||||
|
|
||||||
|
return accessManager->put(request, data->payload);
|
||||||
|
}
|
||||||
|
|
||||||
case NetworkRequestType::Post:
|
case NetworkRequestType::Post:
|
||||||
if (data->multiPartPayload)
|
if (data->multiPartPayload)
|
||||||
{
|
{
|
||||||
@@ -103,8 +115,11 @@ QNetworkReply *NetworkTask::createReply()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
assert(data->multiPartPayload == nullptr);
|
||||||
|
|
||||||
return accessManager->post(request, data->payload);
|
return accessManager->post(request, data->payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
case NetworkRequestType::Patch:
|
case NetworkRequestType::Patch:
|
||||||
if (data->multiPartPayload)
|
if (data->multiPartPayload)
|
||||||
{
|
{
|
||||||
@@ -115,6 +130,8 @@ QNetworkReply *NetworkTask::createReply()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
assert(data->multiPartPayload == nullptr);
|
||||||
|
|
||||||
return NetworkManager::accessManager->sendCustomRequest(
|
return NetworkManager::accessManager->sendCustomRequest(
|
||||||
request, "PATCH", data->payload);
|
request, "PATCH", data->payload);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "common/network/NetworkResult.hpp"
|
#include "common/network/NetworkResult.hpp"
|
||||||
#include "NetworkHelpers.hpp"
|
#include "NetworkHelpers.hpp"
|
||||||
#include "Test.hpp"
|
#include "Test.hpp"
|
||||||
|
#include "util/QMagicEnum.hpp"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
@@ -25,6 +26,24 @@ QString getDelayURL(int delay)
|
|||||||
return QString("%1/delay/%2").arg(HTTPBIN_BASE_URL).arg(delay);
|
return QString("%1/delay/%2").arg(HTTPBIN_BASE_URL).arg(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString getHttpbinUrl(QStringView path)
|
||||||
|
{
|
||||||
|
return QString("%1/%2").arg(HTTPBIN_BASE_URL, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHttpMultiPart *makeMultipart()
|
||||||
|
{
|
||||||
|
auto *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||||
|
|
||||||
|
QHttpPart part;
|
||||||
|
part.setHeader(QNetworkRequest::ContentDispositionHeader,
|
||||||
|
QVariant("form-data; name=\"text\""));
|
||||||
|
part.setBody("my text");
|
||||||
|
|
||||||
|
multipart->append(part);
|
||||||
|
return multipart;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(NetworkRequest, Success)
|
TEST(NetworkRequest, Success)
|
||||||
@@ -281,3 +300,86 @@ TEST(NetworkRequest, BatchedTimeouts)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NetworkRequest, HttpGetHeaders)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(NetworkManager::workerThread->isRunning());
|
||||||
|
|
||||||
|
RequestWaiter waiter;
|
||||||
|
NetworkRequest(getHttpbinUrl(u"headers"), NetworkRequestType::Get)
|
||||||
|
.timeout(1000)
|
||||||
|
.onSuccess([&](const NetworkResult &result) {
|
||||||
|
// make sure we don't attempt to send a body
|
||||||
|
auto body = QString::fromUtf8(result.getData());
|
||||||
|
EXPECT_FALSE(body.contains("content-length", Qt::CaseInsensitive));
|
||||||
|
waiter.requestDone();
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
waiter.waitForRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NetworkRequest, HttpBody)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(NetworkManager::workerThread->isRunning());
|
||||||
|
|
||||||
|
for (auto ty : std::array{
|
||||||
|
NetworkRequestType::Post,
|
||||||
|
NetworkRequestType::Put,
|
||||||
|
NetworkRequestType::Patch,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
auto path = qmagicenum::enumNameString(ty).toLower();
|
||||||
|
RequestWaiter waiter;
|
||||||
|
bool success = false;
|
||||||
|
NetworkRequest(getHttpbinUrl(path), ty)
|
||||||
|
.timeout(1000)
|
||||||
|
.payload("foobar")
|
||||||
|
.header("Content-Type", "text/plain")
|
||||||
|
.onSuccess([&](const NetworkResult &result) {
|
||||||
|
EXPECT_EQ(result.getData(), "foobar") << path;
|
||||||
|
success = true;
|
||||||
|
})
|
||||||
|
.finally([&] {
|
||||||
|
waiter.requestDone();
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
waiter.waitForRequest();
|
||||||
|
ASSERT_TRUE(success) << path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NetworkRequest, HttpBodyMultipart)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(NetworkManager::workerThread->isRunning());
|
||||||
|
|
||||||
|
for (auto ty : std::array{
|
||||||
|
NetworkRequestType::Post,
|
||||||
|
NetworkRequestType::Put,
|
||||||
|
NetworkRequestType::Patch,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
auto path = qmagicenum::enumNameString(ty).toLower();
|
||||||
|
RequestWaiter waiter;
|
||||||
|
bool success = false;
|
||||||
|
NetworkRequest(getHttpbinUrl(path), ty)
|
||||||
|
.timeout(1000)
|
||||||
|
.multiPart(makeMultipart())
|
||||||
|
.onSuccess([&](const NetworkResult &result) {
|
||||||
|
auto body = QString::fromUtf8(result.getData());
|
||||||
|
EXPECT_TRUE(body.contains("Content-Disposition: form-data; "
|
||||||
|
"name=\"text\"\r\n\r\nmy text",
|
||||||
|
Qt::CaseInsensitive))
|
||||||
|
<< "Path:" << path << "Body:" << body;
|
||||||
|
success = true;
|
||||||
|
})
|
||||||
|
.finally([&] {
|
||||||
|
waiter.requestDone();
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
waiter.waitForRequest();
|
||||||
|
ASSERT_TRUE(success) << path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user