mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-02-04 10:54:35 +00:00
Merge pull request #10145 from glassez/drop-legacy-webapi
Drop legacy WebAPI support
This commit is contained in:
commit
198034f976
@ -248,165 +248,55 @@ const Http::Environment &WebApplication::env() const
|
|||||||
|
|
||||||
void WebApplication::doProcessRequest()
|
void WebApplication::doProcessRequest()
|
||||||
{
|
{
|
||||||
QString scope, action;
|
const QRegularExpressionMatch match = m_apiPathPattern.match(request().path);
|
||||||
|
if (!match.hasMatch()) {
|
||||||
|
sendWebUIFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto findAPICall = [&]() -> bool
|
const QString action = match.captured(QLatin1String("action"));
|
||||||
{
|
const QString scope = match.captured(QLatin1String("scope"));
|
||||||
QRegularExpressionMatch match = m_apiPathPattern.match(request().path);
|
|
||||||
if (!match.hasMatch()) return false;
|
|
||||||
|
|
||||||
action = match.captured(QLatin1String("action"));
|
|
||||||
scope = match.captured(QLatin1String("scope"));
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto findLegacyAPICall = [&]() -> bool
|
|
||||||
{
|
|
||||||
QRegularExpressionMatch match = m_apiLegacyPathPattern.match(request().path);
|
|
||||||
if (!match.hasMatch()) return false;
|
|
||||||
|
|
||||||
struct APICompatInfo
|
|
||||||
{
|
|
||||||
QString scope;
|
|
||||||
QString action;
|
|
||||||
std::function<void ()> convertFunc;
|
|
||||||
};
|
|
||||||
const QMap<QString, APICompatInfo> APICompatMapping {
|
|
||||||
{"sync/maindata", {"sync", "maindata", nullptr}},
|
|
||||||
{"sync/torrent_peers", {"sync", "torrentPeers", nullptr}},
|
|
||||||
|
|
||||||
{"login", {"auth", "login", nullptr}},
|
|
||||||
{"logout", {"auth", "logout", nullptr}},
|
|
||||||
|
|
||||||
{"command/shutdown", {"app", "shutdown", nullptr}},
|
|
||||||
{"query/preferences", {"app", "preferences", nullptr}},
|
|
||||||
{"command/setPreferences", {"app", "setPreferences", nullptr}},
|
|
||||||
{"command/getSavePath", {"app", "defaultSavePath", nullptr}},
|
|
||||||
|
|
||||||
{"query/getLog", {"log", "main", nullptr}},
|
|
||||||
{"query/getPeerLog", {"log", "peers", nullptr}},
|
|
||||||
|
|
||||||
{"query/torrents", {"torrents", "info", nullptr}},
|
|
||||||
{"query/propertiesGeneral", {"torrents", "properties", nullptr}},
|
|
||||||
{"query/propertiesTrackers", {"torrents", "trackers", nullptr}},
|
|
||||||
{"query/propertiesWebSeeds", {"torrents", "webseeds", nullptr}},
|
|
||||||
{"query/propertiesFiles", {"torrents", "files", nullptr}},
|
|
||||||
{"query/getPieceHashes", {"torrents", "pieceHashes", nullptr}},
|
|
||||||
{"query/getPieceStates", {"torrents", "pieceStates", nullptr}},
|
|
||||||
{"command/resume", {"torrents", "resume", [this]() { m_params["hashes"] = m_params.take("hash"); }}},
|
|
||||||
{"command/pause", {"torrents", "pause", [this]() { m_params["hashes"] = m_params.take("hash"); }}},
|
|
||||||
{"command/recheck", {"torrents", "recheck", [this]() { m_params["hashes"] = m_params.take("hash"); }}},
|
|
||||||
{"command/resumeAll", {"torrents", "resume", [this]() { m_params["hashes"] = "all"; }}},
|
|
||||||
{"command/pauseAll", {"torrents", "pause", [this]() { m_params["hashes"] = "all"; }}},
|
|
||||||
{"command/rename", {"torrents", "rename", nullptr}},
|
|
||||||
{"command/download", {"torrents", "add", nullptr}},
|
|
||||||
{"command/upload", {"torrents", "add", nullptr}},
|
|
||||||
{"command/delete", {"torrents", "delete", [this]() { m_params["deleteFiles"] = "false"; }}},
|
|
||||||
{"command/deletePerm", {"torrents", "delete", [this]() { m_params["deleteFiles"] = "true"; }}},
|
|
||||||
{"command/addTrackers", {"torrents", "addTrackers", nullptr}},
|
|
||||||
{"command/setFilePrio", {"torrents", "filePrio", nullptr}},
|
|
||||||
{"command/setCategory", {"torrents", "setCategory", nullptr}},
|
|
||||||
{"command/addCategory", {"torrents", "createCategory", nullptr}},
|
|
||||||
{"command/removeCategories", {"torrents", "removeCategories", nullptr}},
|
|
||||||
{"command/getTorrentsUpLimit", {"torrents", "uploadLimit", nullptr}},
|
|
||||||
{"command/getTorrentsDlLimit", {"torrents", "downloadLimit", nullptr}},
|
|
||||||
{"command/setTorrentsUpLimit", {"torrents", "setUploadLimit", nullptr}},
|
|
||||||
{"command/setTorrentsDlLimit", {"torrents", "setDownloadLimit", nullptr}},
|
|
||||||
{"command/increasePrio", {"torrents", "increasePrio", nullptr}},
|
|
||||||
{"command/decreasePrio", {"torrents", "decreasePrio", nullptr}},
|
|
||||||
{"command/topPrio", {"torrents", "topPrio", nullptr}},
|
|
||||||
{"command/bottomPrio", {"torrents", "bottomPrio", nullptr}},
|
|
||||||
{"command/setLocation", {"torrents", "setLocation", nullptr}},
|
|
||||||
{"command/setAutoTMM", {"torrents", "setAutoManagement", nullptr}},
|
|
||||||
{"command/setSuperSeeding", {"torrents", "setSuperSeeding", nullptr}},
|
|
||||||
{"command/setForceStart", {"torrents", "setForceStart", nullptr}},
|
|
||||||
{"command/toggleSequentialDownload", {"torrents", "toggleSequentialDownload", nullptr}},
|
|
||||||
{"command/toggleFirstLastPiecePrio", {"torrents", "toggleFirstLastPiecePrio", nullptr}},
|
|
||||||
|
|
||||||
{"query/transferInfo", {"transfer", "info", nullptr}},
|
|
||||||
{"command/alternativeSpeedLimitsEnabled", {"transfer", "speedLimitsMode", nullptr}},
|
|
||||||
{"command/toggleAlternativeSpeedLimits", {"transfer", "toggleSpeedLimitsMode", nullptr}},
|
|
||||||
{"command/getGlobalUpLimit", {"transfer", "uploadLimit", nullptr}},
|
|
||||||
{"command/getGlobalDlLimit", {"transfer", "downloadLimit", nullptr}},
|
|
||||||
{"command/setGlobalUpLimit", {"transfer", "setUploadLimit", nullptr}},
|
|
||||||
{"command/setGlobalDlLimit", {"transfer", "setDownloadLimit", nullptr}}
|
|
||||||
};
|
|
||||||
|
|
||||||
const QString legacyAction {match.captured(QLatin1String("action"))};
|
|
||||||
const APICompatInfo compatInfo = APICompatMapping.value(legacyAction);
|
|
||||||
|
|
||||||
scope = compatInfo.scope;
|
|
||||||
action = compatInfo.action;
|
|
||||||
if (compatInfo.convertFunc)
|
|
||||||
compatInfo.convertFunc();
|
|
||||||
|
|
||||||
const QString hash {match.captured(QLatin1String("hash"))};
|
|
||||||
if (!hash.isEmpty())
|
|
||||||
m_params[QLatin1String("hash")] = hash;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!findAPICall())
|
|
||||||
findLegacyAPICall();
|
|
||||||
|
|
||||||
APIController *controller = m_apiControllers.value(scope);
|
APIController *controller = m_apiControllers.value(scope);
|
||||||
if (!controller) {
|
if (!controller)
|
||||||
if (request().path == QLatin1String("/version/api")) {
|
throw NotFoundHTTPError();
|
||||||
print(QString::number(COMPAT_API_VERSION), Http::CONTENT_TYPE_TXT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request().path == QLatin1String("/version/api_min")) {
|
if (!session() && !isPublicAPI(scope, action))
|
||||||
print(QString::number(COMPAT_API_VERSION_MIN), Http::CONTENT_TYPE_TXT);
|
throw ForbiddenHTTPError();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request().path == QLatin1String("/version/qbittorrent")) {
|
DataMap data;
|
||||||
print(QString(QBT_VERSION), Http::CONTENT_TYPE_TXT);
|
for (const Http::UploadedFile &torrent : request().files)
|
||||||
return;
|
data[torrent.filename] = torrent.data;
|
||||||
}
|
|
||||||
|
|
||||||
sendWebUIFile();
|
try {
|
||||||
|
const QVariant result = controller->run(action, m_params, data);
|
||||||
|
switch (result.userType()) {
|
||||||
|
case QMetaType::QString:
|
||||||
|
print(result.toString(), Http::CONTENT_TYPE_TXT);
|
||||||
|
break;
|
||||||
|
case QMetaType::QJsonDocument:
|
||||||
|
print(result.toJsonDocument().toJson(QJsonDocument::Compact), Http::CONTENT_TYPE_JSON);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print(result.toString(), Http::CONTENT_TYPE_TXT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
catch (const APIError &error) {
|
||||||
if (!session() && !isPublicAPI(scope, action))
|
// re-throw as HTTPError
|
||||||
throw ForbiddenHTTPError();
|
switch (error.type()) {
|
||||||
|
case APIErrorType::AccessDenied:
|
||||||
DataMap data;
|
throw ForbiddenHTTPError(error.message());
|
||||||
for (const Http::UploadedFile &torrent : request().files)
|
case APIErrorType::BadData:
|
||||||
data[torrent.filename] = torrent.data;
|
throw UnsupportedMediaTypeHTTPError(error.message());
|
||||||
|
case APIErrorType::BadParams:
|
||||||
try {
|
throw BadRequestHTTPError(error.message());
|
||||||
const QVariant result = controller->run(action, m_params, data);
|
case APIErrorType::Conflict:
|
||||||
switch (result.userType()) {
|
throw ConflictHTTPError(error.message());
|
||||||
case QMetaType::QString:
|
case APIErrorType::NotFound:
|
||||||
print(result.toString(), Http::CONTENT_TYPE_TXT);
|
throw NotFoundHTTPError(error.message());
|
||||||
break;
|
default:
|
||||||
case QMetaType::QJsonDocument:
|
Q_ASSERT(false);
|
||||||
print(result.toJsonDocument().toJson(QJsonDocument::Compact), Http::CONTENT_TYPE_JSON);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
print(result.toString(), Http::CONTENT_TYPE_TXT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const APIError &error) {
|
|
||||||
// re-throw as HTTPError
|
|
||||||
switch (error.type()) {
|
|
||||||
case APIErrorType::AccessDenied:
|
|
||||||
throw ForbiddenHTTPError(error.message());
|
|
||||||
case APIErrorType::BadData:
|
|
||||||
throw UnsupportedMediaTypeHTTPError(error.message());
|
|
||||||
case APIErrorType::BadParams:
|
|
||||||
throw BadRequestHTTPError(error.message());
|
|
||||||
case APIErrorType::Conflict:
|
|
||||||
throw ConflictHTTPError(error.message());
|
|
||||||
case APIErrorType::NotFound:
|
|
||||||
throw NotFoundHTTPError(error.message());
|
|
||||||
default:
|
|
||||||
Q_ASSERT(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,6 @@
|
|||||||
#include "base/utils/version.h"
|
#include "base/utils/version.h"
|
||||||
|
|
||||||
constexpr Utils::Version<int, 3, 2> API_VERSION {2, 2, 0};
|
constexpr Utils::Version<int, 3, 2> API_VERSION {2, 2, 0};
|
||||||
constexpr int COMPAT_API_VERSION = 23;
|
|
||||||
constexpr int COMPAT_API_VERSION_MIN = 23;
|
|
||||||
|
|
||||||
class APIController;
|
class APIController;
|
||||||
class WebApplication;
|
class WebApplication;
|
||||||
@ -131,7 +129,6 @@ private:
|
|||||||
QMap<QString, QString> m_params;
|
QMap<QString, QString> m_params;
|
||||||
|
|
||||||
const QRegularExpression m_apiPathPattern {(QLatin1String("^/api/v2/(?<scope>[A-Za-z_][A-Za-z_0-9]*)/(?<action>[A-Za-z_][A-Za-z_0-9]*)$"))};
|
const QRegularExpression m_apiPathPattern {(QLatin1String("^/api/v2/(?<scope>[A-Za-z_][A-Za-z_0-9]*)/(?<action>[A-Za-z_][A-Za-z_0-9]*)$"))};
|
||||||
const QRegularExpression m_apiLegacyPathPattern {QLatin1String("^/(?<action>((sync|command|query)/[A-Za-z_][A-Za-z_0-9]*|login|logout))(/(?<hash>[^/]+))?$")};
|
|
||||||
|
|
||||||
QHash<QString, APIController *> m_apiControllers;
|
QHash<QString, APIController *> m_apiControllers;
|
||||||
QSet<QString> m_publicAPIs;
|
QSet<QString> m_publicAPIs;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user