Redesign Web API

Normalize Web API method names.
Allow to use alternative Web UI.
Switch Web API version to standard form (i.e. "2.0").
Improve Web UI translation code.
Retranslate changed files.
Add Web API for RSS subsystem.
This commit is contained in:
Vladimir Golovnev (Glassez) 2017-10-14 16:27:21 +03:00
commit 27d8dbf13b
No known key found for this signature in database
GPG key ID: 52A2C7DEE2DFA6F7
90 changed files with 4817 additions and 3038 deletions

View file

@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2014, 2017 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -26,95 +26,118 @@
* exception statement from your version.
*/
#ifndef WEBAPPLICATION_H
#define WEBAPPLICATION_H
#pragma once
#include <QStringList>
#include "abstractwebapplication.h"
#include <QDateTime>
#include <QHash>
#include <QMap>
#include <QObject>
#include <QRegularExpression>
#include <QSet>
class WebApplication : public AbstractWebApplication
#include "api/isessionmanager.h"
#include "base/http/irequesthandler.h"
#include "base/http/responsebuilder.h"
#include "base/http/types.h"
#include "base/utils/version.h"
constexpr Utils::Version<int, 3, 2> API_VERSION {2, 0, 0};
constexpr int COMPAT_API_VERSION = 18;
constexpr int COMPAT_API_VERSION_MIN = 18;
class APIController;
class WebApplication;
constexpr char C_SID[] = "SID"; // name of session id cookie
constexpr int INACTIVE_TIME = 900; // Session inactive time (in secs = 15 min.)
class WebSession : public ISession
{
friend class WebApplication;
public:
explicit WebSession(const QString &sid);
QString id() const override;
uint timestamp() const;
QVariant getData(const QString &id) const override;
void setData(const QString &id, const QVariant &data) override;
private:
void updateTimestamp();
const QString m_sid;
uint m_timestamp;
QVariantHash m_data;
};
class WebApplication
: public QObject, public Http::IRequestHandler, public ISessionManager
, private Http::ResponseBuilder
{
Q_OBJECT
Q_DISABLE_COPY(WebApplication)
#ifndef Q_MOC_RUN
#define WEBAPI_PUBLIC
#define WEBAPI_PRIVATE
#endif
public:
explicit WebApplication(QObject *parent = nullptr);
~WebApplication() override;
Http::Response processRequest(const Http::Request &request, const Http::Environment &env);
QString clientId() const override;
WebSession *session() override;
void sessionStart() override;
void sessionEnd() override;
const Http::Request &request() const;
const Http::Environment &env() const;
private:
// Actions
void action_public_webui();
void action_public_index();
void action_public_login();
void action_public_logout();
void action_public_theme();
void action_public_images();
void action_query_torrents();
void action_query_preferences();
void action_query_transferInfo();
void action_query_propertiesGeneral();
void action_query_propertiesTrackers();
void action_query_propertiesWebSeeds();
void action_query_propertiesFiles();
void action_query_getLog();
void action_query_getPeerLog();
void action_query_getPieceHashes();
void action_query_getPieceStates();
void action_sync_maindata();
void action_sync_torrent_peers();
void action_command_shutdown();
void action_command_download();
void action_command_upload();
void action_command_addTrackers();
void action_command_resumeAll();
void action_command_pauseAll();
void action_command_resume();
void action_command_pause();
void action_command_setPreferences();
void action_command_setFilePrio();
void action_command_getGlobalUpLimit();
void action_command_getGlobalDlLimit();
void action_command_setGlobalUpLimit();
void action_command_setGlobalDlLimit();
void action_command_getTorrentsUpLimit();
void action_command_getTorrentsDlLimit();
void action_command_setTorrentsUpLimit();
void action_command_setTorrentsDlLimit();
void action_command_alternativeSpeedLimitsEnabled();
void action_command_toggleAlternativeSpeedLimits();
void action_command_toggleSequentialDownload();
void action_command_toggleFirstLastPiecePrio();
void action_command_setSuperSeeding();
void action_command_setForceStart();
void action_command_delete();
void action_command_deletePerm();
void action_command_increasePrio();
void action_command_decreasePrio();
void action_command_topPrio();
void action_command_bottomPrio();
void action_command_setLocation();
void action_command_rename();
void action_command_setAutoTMM();
void action_command_recheck();
void action_command_setCategory();
void action_command_addCategory();
void action_command_removeCategories();
void action_command_getSavePath();
void action_version_api();
void action_version_api_min();
void action_version_qbittorrent();
void doProcessRequest();
void configure();
typedef void (WebApplication::*Action)();
void registerAPIController(const QString &scope, APIController *controller);
void declarePublicAPI(const QString &apiPath);
QString scope_;
QString action_;
QStringList args_;
void sendFile(const QString &path);
void sendWebUIFile();
void doProcessRequest() override;
// Session management
QString generateSid() const;
void sessionInitialize();
bool isAuthNeeded();
bool isPublicAPI(const QString &scope, const QString &action) const;
bool isPublicScope();
void parsePath();
bool isCrossSiteRequest(const Http::Request &request) const;
bool validateHostHeader(const QStringList &domains) const;
static QMap<QString, QMap<QString, Action> > initializeActions();
static QMap<QString, QMap<QString, Action> > actions_;
// Persistent data
QMap<QString, WebSession *> m_sessions;
// Current data
WebSession *m_currentSession = nullptr;
Http::Request m_request;
Http::Environment m_env;
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|control|query)/[A-Za-z_][A-Za-z_0-9]*|login|logout))(/(?<hash>[^/]+))?$")};
QHash<QString, APIController *> m_apiControllers;
QSet<QString> m_publicAPIs;
bool m_isAltUIUsed = false;
QString m_rootFolder;
QStringList m_domainList;
struct TranslatedFile
{
QByteArray data;
QDateTime lastModified;
};
QMap<QString, TranslatedFile> m_translatedFiles;
};
#endif // WEBAPPLICATION_H