Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support configuring WebUI URL base path #21471

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/base/preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,19 @@ void Preferences::setWebUITrustedReverseProxiesList(const QString &addr)
setValue(u"Preferences/WebUI/TrustedReverseProxiesList"_s, addr);
}

QString Preferences::getWebUIBasePath() const
{
return value(u"Preferences/WebUI/BasePath"_s, u"/"_s);
}

void Preferences::setWebUIBasePath(const QString &path)
{
if (path == getWebUIBasePath())
return;

setValue(u"Preferences/WebUI/BasePath"_s, path);
}

bool Preferences::isDynDNSEnabled() const
{
return value(u"Preferences/DynDNS/Enabled"_s, false);
Expand Down
2 changes: 2 additions & 0 deletions src/base/preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ class Preferences final : public QObject
void setWebUIReverseProxySupportEnabled(bool enabled);
QString getWebUITrustedReverseProxiesList() const;
void setWebUITrustedReverseProxiesList(const QString &addr);
QString getWebUIBasePath() const;
void setWebUIBasePath(const QString &path);

// Dynamic DNS
bool isDynDNSEnabled() const;
Expand Down
13 changes: 13 additions & 0 deletions src/gui/optionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,7 @@ void OptionsDialog::loadWebUITabOptions()
// Reverse proxy
m_ui->groupEnableReverseProxySupport->setChecked(pref->isWebUIReverseProxySupportEnabled());
m_ui->textTrustedReverseProxiesList->setText(pref->getWebUITrustedReverseProxiesList());
m_ui->textWebUIBasePath->setText(pref->getWebUIBasePath());
// DynDNS
m_ui->checkDynDNS->setChecked(pref->isDynDNSEnabled());
m_ui->comboDNSService->setCurrentIndex(static_cast<int>(pref->getDynDNSService()));
Expand Down Expand Up @@ -1354,6 +1355,7 @@ void OptionsDialog::loadWebUITabOptions()

connect(m_ui->groupEnableReverseProxySupport, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->textTrustedReverseProxiesList, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);
connect(m_ui->textWebUIBasePath, &QLineEdit::textChanged, this, &ThisType::enableApplyButton);

connect(m_ui->checkDynDNS, &QGroupBox::toggled, this, &ThisType::enableApplyButton);
connect(m_ui->comboDNSService, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton);
Expand Down Expand Up @@ -1400,6 +1402,17 @@ void OptionsDialog::saveWebUITabOptions() const
// Reverse proxy
pref->setWebUIReverseProxySupportEnabled(m_ui->groupEnableReverseProxySupport->isChecked());
pref->setWebUITrustedReverseProxiesList(m_ui->textTrustedReverseProxiesList->text());

QString path = m_ui->textWebUIBasePath->text();
if (!path.startsWith(u"/"_s))
path.prepend(u"/");
if (!path.endsWith(u"/"_s))
path.append(u"/");
QUrl url;
url.setPath(path, QUrl::StrictMode);
if (url.isValid())
pref->setWebUIBasePath(url.path());

// DynDNS
pref->setDynDNSEnabled(m_ui->checkDynDNS->isChecked());
pref->setDynDNSService(static_cast<DNS::Service>(m_ui->comboDNSService->currentIndex()));
Expand Down
18 changes: 18 additions & 0 deletions src/gui/optionsdialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -3814,6 +3814,24 @@ Use ';' to split multiple entries. Can use wildcard '*'.</string>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_132">
<item>
<widget class="QLabel" name="lblWebUIBasePath">
<property name="text">
<string>URL base path:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="textWebUIBasePath">
<property name="toolTip">
<string>Specify the URL path qBittorent will be made accessible at (e.g. '/qbittorrent/').</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelReverseProxyLink">
<property name="text">
Expand Down
13 changes: 13 additions & 0 deletions src/webui/api/appcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ void AppController::preferencesAction()
// Reverse proxy
data[u"web_ui_reverse_proxy_enabled"_s] = pref->isWebUIReverseProxySupportEnabled();
data[u"web_ui_reverse_proxies_list"_s] = pref->getWebUITrustedReverseProxiesList();
data[u"web_ui_base_path"_s] = pref->getWebUIBasePath();
// Update my dynamic domain name
data[u"dyndns_enabled"_s] = pref->isDynDNSEnabled();
data[u"dyndns_service"_s] = static_cast<int>(pref->getDynDNSService());
Expand Down Expand Up @@ -924,6 +925,18 @@ void AppController::setPreferencesAction()
pref->setWebUIReverseProxySupportEnabled(it.value().toBool());
if (hasKey(u"web_ui_reverse_proxies_list"_s))
pref->setWebUITrustedReverseProxiesList(it.value().toString());
if (hasKey(u"web_ui_base_path"_s))
{
QString path = it.value().toString();
if (!path.startsWith(u"/"_s))
path.prepend(u"/");
if (!path.endsWith(u"/"_s))
path.append(u"/");
QUrl url;
url.setPath(path, QUrl::StrictMode);
if (url.isValid())
pref->setWebUIBasePath(url.path());
}
// Update my dynamic domain name
if (hasKey(u"dyndns_enabled"_s))
pref->setDynDNSEnabled(it.value().toBool());
Expand Down
38 changes: 25 additions & 13 deletions src/webui/webapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ void WebApplication::configure()
{
m_isAltUIUsed = isAltUIUsed;
m_rootFolder = rootFolder;
m_translatedFiles.clear();
m_cachedFiles.clear();
if (!m_isAltUIUsed)
LogMsg(tr("Using built-in WebUI."));
else
Expand All @@ -423,7 +423,7 @@ void WebApplication::configure()
if (m_currentLocale != newLocale)
{
m_currentLocale = newLocale;
m_translatedFiles.clear();
m_cachedFiles.clear();

m_translationFileLoaded = m_translator.load((m_rootFolder / Path(u"translations/webui_"_s) + newLocale).data());
if (m_translationFileLoaded)
Expand Down Expand Up @@ -495,6 +495,13 @@ void WebApplication::configure()
}

m_isReverseProxySupportEnabled = pref->isWebUIReverseProxySupportEnabled();
const QString newBasePath = m_isReverseProxySupportEnabled ? pref->getWebUIBasePath() : u"/"_s;
if (m_basePath != newBasePath)
{
m_cachedFiles.clear();
m_basePath = newBasePath;
}

if (m_isReverseProxySupportEnabled)
{
const QStringList proxyList = pref->getWebUITrustedReverseProxiesList().split(u';', Qt::SkipEmptyParts);
Expand Down Expand Up @@ -539,8 +546,8 @@ void WebApplication::sendFile(const Path &path)
// find translated file in cache
if (!m_isAltUIUsed)
{
if (const auto it = m_translatedFiles.constFind(path);
(it != m_translatedFiles.constEnd()) && (lastModified <= it->lastModified))
if (const auto it = m_cachedFiles.constFind(path);
(it != m_cachedFiles.constEnd()) && (lastModified <= it->lastModified))
{
print(it->data, it->mimeType);
setHeader({Http::HEADER_CACHE_CONTROL, getCachingInterval(it->mimeType)});
Expand Down Expand Up @@ -576,20 +583,25 @@ void WebApplication::sendFile(const Path &path)

QByteArray data = readResult.value();
const QMimeType mimeType = QMimeDatabase().mimeTypeForFileNameAndData(path.data(), data);
const bool isTranslatable = !m_isAltUIUsed && mimeType.inherits(u"text/plain"_s);

if (isTranslatable)
const bool isTextFile = mimeType.inherits(u"text/plain"_s);
if (isTextFile)
{
auto dataStr = QString::fromUtf8(data);
// Translate the file
translateDocument(dataStr);
dataStr.replace(u"${BASE_PATH}"_s, m_basePath);

// Add the language options
if (path == (m_rootFolder / Path(PRIVATE_FOLDER) / Path(u"views/preferences.html"_s)))
dataStr.replace(u"${LANGUAGE_OPTIONS}"_s, createLanguagesOptionsHtml());
const bool isTranslatable = !m_isAltUIUsed;
if (isTranslatable)
{
// Translate the file
translateDocument(dataStr);

// Add the language options
if (path == (m_rootFolder / Path(PRIVATE_FOLDER) / Path(u"views/preferences.html"_s)))
dataStr.replace(u"${LANGUAGE_OPTIONS}"_s, createLanguagesOptionsHtml());
}

data = dataStr.toUtf8();
m_translatedFiles[path] = {data, mimeType.name(), lastModified}; // caching translated file
m_cachedFiles[path] = {data, mimeType.name(), lastModified};
}

print(data, mimeType.name());
Expand Down
5 changes: 3 additions & 2 deletions src/webui/webapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,15 @@ class WebApplication final : public ApplicationComponent<QObject>
};
bool m_isAltUIUsed = false;
Path m_rootFolder;
QString m_basePath;

struct TranslatedFile
struct CachedFile
{
QByteArray data;
QString mimeType;
QDateTime lastModified;
};
QHash<Path, TranslatedFile> m_translatedFiles;
QHash<Path, CachedFile> m_cachedFiles;
QString m_currentLocale;
QTranslator m_translator;
bool m_translationFileLoaded = false;
Expand Down
12 changes: 6 additions & 6 deletions src/webui/www/private/addpeers.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="UTF-8">
<title>QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<link rel="stylesheet" href="${BASE_PATH}css/style.css?v=${CACHEID}" type="text/css">
<script src="${BASE_PATH}scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="${BASE_PATH}scripts/color-scheme.js?v=${CACHEID}"></script>
<script>
"use strict";

Expand Down Expand Up @@ -42,7 +42,7 @@
return;

new Request({
url: "api/v2/torrents/addPeers",
url: "${BASE_PATH}api/v2/torrents/addPeers",
method: "post",
data: {
hashes: hash,
Expand Down
12 changes: 6 additions & 6 deletions src/webui/www/private/addtrackers.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="UTF-8">
<title>QBT_TR(Add trackers)QBT_TR[CONTEXT=TrackersAdditionDialog]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<link rel="stylesheet" href="${BASE_PATH}css/style.css?v=${CACHEID}" type="text/css">
<script src="${BASE_PATH}scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="${BASE_PATH}scripts/color-scheme.js?v=${CACHEID}"></script>
<script>
"use strict";

Expand All @@ -34,7 +34,7 @@

const hash = new URI().getData("hash");
new Request({
url: "api/v2/torrents/addTrackers",
url: "${BASE_PATH}api/v2/torrents/addTrackers",
method: "post",
data: {
hash: hash,
Expand Down
12 changes: 6 additions & 6 deletions src/webui/www/private/addwebseeds.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="UTF-8">
<title>QBT_TR(Add web seeds)QBT_TR[CONTEXT=HttpServer]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<link rel="stylesheet" href="${BASE_PATH}css/style.css?v=${CACHEID}" type="text/css">
<script src="${BASE_PATH}scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="${BASE_PATH}scripts/color-scheme.js?v=${CACHEID}"></script>
<script>
"use strict";

Expand All @@ -32,7 +32,7 @@
e.stopPropagation();
const hash = new URI().getData("hash");
new Request({
url: "api/v2/torrents/addWebSeeds",
url: "${BASE_PATH}api/v2/torrents/addWebSeeds",
method: "post",
data: {
hash: hash,
Expand Down
12 changes: 6 additions & 6 deletions src/webui/www/private/confirmfeeddeletion.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="UTF-8">
<title>QBT_TR(Deletion confirmation)QBT_TR[CONTEXT=RSSWidget]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<link rel="stylesheet" href="${BASE_PATH}css/style.css?v=${CACHEID}" type="text/css">
<script src="${BASE_PATH}scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="${BASE_PATH}scripts/color-scheme.js?v=${CACHEID}"></script>
<script>
"use strict";

Expand All @@ -27,7 +27,7 @@
let completionCount = 0;
paths.forEach((path) => {
new Request({
url: "api/v2/rss/removeItem",
url: "${BASE_PATH}api/v2/rss/removeItem",
method: "post",
data: {
path: decodeURIComponent(path)
Expand Down
10 changes: 5 additions & 5 deletions src/webui/www/private/confirmruleclear.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="UTF-8">
<title>QBT_TR(Clear downloaded episodes)QBT_TR[CONTEXT=AutomatedRssDownloader]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<link rel="stylesheet" href="${BASE_PATH}css/style.css?v=${CACHEID}" type="text/css">
<script src="${BASE_PATH}scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="${BASE_PATH}scripts/color-scheme.js?v=${CACHEID}"></script>
<script>
"use strict";

Expand Down
12 changes: 6 additions & 6 deletions src/webui/www/private/confirmruledeletion.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="UTF-8">
<title>QBT_TR(Rule deletion confirmation)QBT_TR[CONTEXT=AutomatedRssDownloader]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<link rel="stylesheet" href="${BASE_PATH}css/style.css?v=${CACHEID}" type="text/css">
<script src="${BASE_PATH}scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="${BASE_PATH}scripts/color-scheme.js?v=${CACHEID}"></script>
<script>
"use strict";

Expand All @@ -28,7 +28,7 @@
let completionCount = 0;
rules.forEach((rule) => {
new Request({
url: "api/v2/rss/removeRule",
url: "${BASE_PATH}api/v2/rss/removeRule",
method: "post",
data: {
ruleName: decodeURIComponent(rule)
Expand Down
12 changes: 6 additions & 6 deletions src/webui/www/private/confirmtrackerdeletion.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset="UTF-8">
<title>QBT_TR(Remove tracker)QBT_TR[CONTEXT=confirmDeletionDlg]</title>
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
<script src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="scripts/color-scheme.js?v=${CACHEID}"></script>
<link rel="stylesheet" href="${BASE_PATH}css/style.css?v=${CACHEID}" type="text/css">
<script src="${BASE_PATH}scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
<script src="${BASE_PATH}scripts/localpreferences.js?v=${CACHEID}"></script>
<script src="${BASE_PATH}scripts/color-scheme.js?v=${CACHEID}"></script>
<script>
"use strict";

Expand All @@ -24,7 +24,7 @@
});
$("confirmBtn").addEvent("click", (e) => {
e.stopPropagation();
const cmd = "api/v2/torrents/removeTrackers";
const cmd = "${BASE_PATH}api/v2/torrents/removeTrackers";
new Request({
url: cmd,
method: "post",
Expand Down
Loading
Loading