mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Add a function in NetworkCommon parseHeaderList
which parses a header list as a string into a vector of header pairs (#2623)
This commit is contained in:
parent
cceadf473a
commit
2f906c5504
9 changed files with 119 additions and 11 deletions
|
@ -134,6 +134,7 @@ SOURCES += \
|
|||
src/common/Env.cpp \
|
||||
src/common/LinkParser.cpp \
|
||||
src/common/Modes.cpp \
|
||||
src/common/NetworkCommon.cpp \
|
||||
src/common/NetworkManager.cpp \
|
||||
src/common/NetworkPrivate.cpp \
|
||||
src/common/NetworkRequest.cpp \
|
||||
|
|
|
@ -30,6 +30,8 @@ set(SOURCE_FILES main.cpp
|
|||
common/LinkParser.hpp
|
||||
common/Modes.cpp
|
||||
common/Modes.hpp
|
||||
common/NetworkCommon.cpp
|
||||
common/NetworkCommon.hpp
|
||||
common/NetworkManager.cpp
|
||||
common/NetworkManager.hpp
|
||||
common/NetworkPrivate.cpp
|
||||
|
|
35
src/common/NetworkCommon.cpp
Normal file
35
src/common/NetworkCommon.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "common/NetworkCommon.hpp"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
std::vector<std::pair<QByteArray, QByteArray>> parseHeaderList(
|
||||
const QString &headerListString)
|
||||
{
|
||||
std::vector<std::pair<QByteArray, QByteArray>> res;
|
||||
|
||||
// Split the string into a list of header pairs
|
||||
// e.g. "Authorization:secretkey;NextHeader:boo" turning into ["Authorization:secretkey","NextHeader:boo"]
|
||||
auto headerPairs = headerListString.split(";");
|
||||
|
||||
for (const auto &headerPair : headerPairs)
|
||||
{
|
||||
const auto headerName =
|
||||
headerPair.section(":", 0, 0).trimmed().toUtf8();
|
||||
const auto headerValue = headerPair.section(":", 1).trimmed().toUtf8();
|
||||
|
||||
if (headerName.isEmpty() || headerValue.isEmpty())
|
||||
{
|
||||
// The header part either didn't contain a : or the name/value was empty
|
||||
// Skip the value
|
||||
continue;
|
||||
}
|
||||
|
||||
res.emplace_back(headerName, headerValue);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
|
@ -1,6 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
|
@ -22,4 +25,13 @@ enum class NetworkRequestType {
|
|||
Patch,
|
||||
};
|
||||
|
||||
// parseHeaderList takes a list of headers in string form,
|
||||
// where each header pair is separated by semicolons (;) and the header name and value is divided by a colon (:)
|
||||
//
|
||||
// We return a vector of pairs, where the first value is the header name and the second value is the header value
|
||||
//
|
||||
// e.g. "Authorization:secretkey;NextHeader:boo" will return [{"Authorization", "secretkey"}, {"NextHeader", "boo"}]
|
||||
std::vector<std::pair<QByteArray, QByteArray>> parseHeaderList(
|
||||
const QString &headerListString);
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -106,16 +106,12 @@ NetworkRequest NetworkRequest::header(const char *headerName,
|
|||
return std::move(*this);
|
||||
}
|
||||
|
||||
NetworkRequest NetworkRequest::headerList(const QStringList &headers) &&
|
||||
NetworkRequest NetworkRequest::headerList(
|
||||
const std::vector<std::pair<QByteArray, QByteArray>> &headers) &&
|
||||
{
|
||||
for (const QString &header : headers)
|
||||
for (const auto &[headerName, headerValue] : headers)
|
||||
{
|
||||
const QStringList thisHeader = header.trimmed().split(":");
|
||||
if (thisHeader.size() == 2)
|
||||
{
|
||||
this->data->request_.setRawHeader(thisHeader[0].trimmed().toUtf8(),
|
||||
thisHeader[1].trimmed().toUtf8());
|
||||
}
|
||||
this->data->request_.setRawHeader(headerName, headerValue);
|
||||
}
|
||||
return std::move(*this);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ public:
|
|||
NetworkRequest header(const char *headerName, const char *value) &&;
|
||||
NetworkRequest header(const char *headerName, const QByteArray &value) &&;
|
||||
NetworkRequest header(const char *headerName, const QString &value) &&;
|
||||
NetworkRequest headerList(const QStringList &headers) &&;
|
||||
NetworkRequest headerList(
|
||||
const std::vector<std::pair<QByteArray, QByteArray>> &headers) &&;
|
||||
NetworkRequest timeout(int ms) &&;
|
||||
NetworkRequest concurrent() &&;
|
||||
NetworkRequest authorizeTwitchV5(const QString &clientID,
|
||||
|
|
|
@ -128,8 +128,8 @@ void uploadImageToNuuls(RawImageData imageData, ChannelPtr channel,
|
|||
getSettings()->imageUploaderFormField.getValue().isEmpty()
|
||||
? getSettings()->imageUploaderFormField.getDefaultValue()
|
||||
: getSettings()->imageUploaderFormField);
|
||||
QStringList extraHeaders(
|
||||
getSettings()->imageUploaderHeaders.getValue().split(";"));
|
||||
auto extraHeaders =
|
||||
parseHeaderList(getSettings()->imageUploaderHeaders.getValue());
|
||||
QString originalFilePath = imageData.filePath;
|
||||
|
||||
QHttpMultiPart *payload = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
|
|
|
@ -9,6 +9,7 @@ set(chatterino_SOURCES
|
|||
|
||||
${CMAKE_SOURCE_DIR}/src/common/ChatterinoSetting.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/common/Modes.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/common/NetworkCommon.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/common/NetworkManager.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/common/NetworkPrivate.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/common/NetworkRequest.cpp
|
||||
|
@ -35,6 +36,7 @@ set(chatterino_SOURCES
|
|||
|
||||
set(test_SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/main.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/NetworkCommon.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/NetworkRequest.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/UsernameSet.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/HighlightPhrase.cpp
|
||||
|
|
59
tests/src/NetworkCommon.cpp
Normal file
59
tests/src/NetworkCommon.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "common/NetworkCommon.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace chatterino;
|
||||
|
||||
TEST(NetworkCommon, parseHeaderList1)
|
||||
{
|
||||
const QString input = "Authorization:secretKey;NextHeader:boo";
|
||||
const std::vector<std::pair<QByteArray, QByteArray>> expected = {
|
||||
{"Authorization", "secretKey"},
|
||||
{"NextHeader", "boo"},
|
||||
};
|
||||
|
||||
const auto actual = parseHeaderList(input);
|
||||
|
||||
ASSERT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
TEST(NetworkCommon, parseHeaderListTrimmed)
|
||||
{
|
||||
const QString input = "Authorization: secretKey; NextHeader :boo";
|
||||
const std::vector<std::pair<QByteArray, QByteArray>> expected = {
|
||||
{"Authorization", "secretKey"},
|
||||
{"NextHeader", "boo"},
|
||||
};
|
||||
|
||||
const auto actual = parseHeaderList(input);
|
||||
|
||||
ASSERT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
TEST(NetworkCommon, parseHeaderListColonInValue)
|
||||
{
|
||||
// The input values first header pair contains an invalid value, too many colons. We expect this value to be skipped
|
||||
const QString input = "Authorization: secretKey:hehe; NextHeader :boo";
|
||||
const std::vector<std::pair<QByteArray, QByteArray>> expected = {
|
||||
{"Authorization", "secretKey:hehe"},
|
||||
{"NextHeader", "boo"},
|
||||
};
|
||||
|
||||
const auto actual = parseHeaderList(input);
|
||||
|
||||
ASSERT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
TEST(NetworkCommon, parseHeaderListBadPair)
|
||||
{
|
||||
// The input values first header pair doesn't have a colon, so we don't know where the header name and value start/end
|
||||
const QString input = "Authorization secretKeybad; NextHeader :boo";
|
||||
const std::vector<std::pair<QByteArray, QByteArray>> expected = {
|
||||
{"NextHeader", "boo"},
|
||||
};
|
||||
|
||||
const auto actual = parseHeaderList(input);
|
||||
|
||||
ASSERT_EQ(expected, actual);
|
||||
ASSERT_EQ(1, actual.size());
|
||||
}
|
Loading…
Reference in a new issue