新增内置WEB Server功能.

This commit is contained in:
hxhlb 2020-10-31 17:34:34 +08:00
parent 5af6a1de3c
commit e7761e6509
11 changed files with 6842 additions and 47 deletions

@ -1,4 +1,4 @@
QT += core widgets gui webengine webenginewidgets svg QT += core widgets gui webengine webenginewidgets svg concurrent
greaterThan(QT_MAJOR_VERSION, 5): QT += widgets greaterThan(QT_MAJOR_VERSION, 5): QT += widgets
@ -10,12 +10,15 @@ CONFIG += c++11 link_pkgconfig
PKGCONFIG += dtkwidget PKGCONFIG += dtkwidget
SOURCES += main.cpp\ SOURCES += main.cpp\
httpd.cpp \
mainwindow.cpp \ mainwindow.cpp \
webenginepage.cpp \ webenginepage.cpp \
widget.cpp widget.cpp
HEADERS += mainwindow.h \ HEADERS += mainwindow.h \
globaldefine.h \ globaldefine.h \
httpd.h \
httplib.h \
webenginepage.h \ webenginepage.h \
widget.h widget.h

@ -13,4 +13,7 @@
#define DEFAULT_ICON QString() #define DEFAULT_ICON QString()
#define DEFAULT_CFG QString() #define DEFAULT_CFG QString()
#define DEFAULT_ROOT QString()
#define DEFAULT_PORT 0
#endif // GLOBALDEFINE_H #endif // GLOBALDEFINE_H

@ -29,6 +29,8 @@
-i, --ico <ico> 设置程序运行的图标. -i, --ico <ico> 设置程序运行的图标.
-d, --desc <desc> 设置程序的描述信息. -d, --desc <desc> 设置程序的描述信息.
-c, --cfg <cfg> 设置程序运行的配置文件. -c, --cfg <cfg> 设置程序运行的配置文件.
-r, --root <root> 设置内置WebServer的根路径.
-P, --port <port> 设置内置WebServer的监听端口号.
</xmp> </xmp>
<br/> <br/>
<span style="color: red">需要注意的是, 命令行会覆盖配置文件的配置信息.</span> <span style="color: red">需要注意的是, 命令行会覆盖配置文件的配置信息.</span>
@ -59,6 +61,8 @@
-i, --ico <ico> The ICON of Application. -i, --ico <ico> The ICON of Application.
-d, --desc <desc> The Description of Application. -d, --desc <desc> The Description of Application.
-c, --cfg <cfg> The Configuration file of Application. -c, --cfg <cfg> The Configuration file of Application.
-r, --root <root> The root path of the program web service.
-P, --port <port> The port number of the program web service.
</xmp> </xmp>
<br/> <br/>
<span style="color: red">It should be noted that the command line will overwrite the configuration information of the configuration file.</span> <span style="color: red">It should be noted that the command line will overwrite the configuration information of the configuration file.</span>

@ -0,0 +1,95 @@
#include "httpd.h"
#include "httplib.h"
#include <QtConcurrent>
#include <QDebug>
using namespace httplib;
#if SSL_SERVER
HttpD::HttpD(QString szRootPath, quint16 u16Port, quint16 u16sslPort, QObject *parent)
#else
HttpD::HttpD(QString szRootPath, quint16 u16Port, QObject *parent)
#endif
: QObject(parent)
, m_szRootPath(szRootPath)
#if SSL_SERVER
, m_httpsServer(new SSLServer(g_szClientCert.toStdString().c_str(), g_szClientCertKey.toStdString().c_str()))
, m_u16HttpsServerBindPort(u16sslPort)
#endif
, m_httpServer(new Server())
, m_u16HttpServerBindPort(u16Port)
{
#if SSL_SERVER
m_httpsServer->set_idle_interval(0, 500 * 1000);
m_httpsServer->set_read_timeout(1);
m_httpsServer->set_write_timeout(1);
#endif
m_httpServer->set_idle_interval(0, 500 * 1000);
m_httpServer->set_read_timeout(1);
m_httpServer->set_write_timeout(1);
#if SSL_SERVER
auto ret = m_httpsServer->set_mount_point("/", m_szRootPath.toStdString().c_str());
if (!ret)
{
qInfo("HTTP Server Mount root directory Fail!");
}
m_httpsServer->set_error_handler([](const Request &, Response & res)
{
auto fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), fmt, res.status);
res.set_content(buf, "text/html");
});
#endif
auto ret = m_httpServer->set_mount_point("/", m_szRootPath.toStdString().c_str());
if (!ret)
{
qInfo("HTTP Server Mount root directory Fail!");
}
m_httpServer->set_error_handler([](const Request &, Response & res)
{
auto fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), fmt, res.status);
res.set_content(buf, "text/html");
});
}
void HttpD::start()
{
#if SSL_SERVER
QtConcurrent::run([&]
{
if (m_u16HttpsServerBindPort > 0)
{
CommonTools::outputLog(QString("HTTPS Server Startup with [%1] listen to %2 ...")
.arg(m_szRootPath)
.arg(m_u16HttpServerBindPort);
m_httpsServer->listen("0.0.0.0", m_u16HttpsServerBindPort);
}
});
#endif
QtConcurrent::run([&]
{
if (m_u16HttpServerBindPort > 0)
{
qInfo() << QString("HTTP Server Startup with [%1] listen to %2 ...")
.arg(m_szRootPath)
.arg(m_u16HttpServerBindPort);
m_httpServer->listen("0.0.0.0", m_u16HttpServerBindPort);
}
});
}
void HttpD::stop()
{
#if SSL_SERVER
m_httpsServer->stop();
#endif
m_httpServer->stop();
}

@ -0,0 +1,45 @@
#ifndef HTTPSD_H
#define HTTPSD_H
#include <QObject>
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
#define SSL_SERVER 1
#else
#define SSL_SERVER 0
#endif
namespace httplib
{
class Server;
#if SSL_SERVER
class SSLServer;
#endif
}
class HttpD : public QObject
{
Q_OBJECT
public:
#if SSL_SERVER
explicit HttpD(QString szRootPath, quint16 u16Port, quint16 u16sslPort, QObject *parent = nullptr);
#else
explicit HttpD(QString szRootPath, quint16 u16Port, QObject *parent = nullptr);
#endif
public slots:
void start();
void stop();
private:
QString m_szRootPath;
#if SSL_SERVER
httplib::SSLServer *m_httpsServer;
quint16 m_u16HttpsServerBindPort;
#endif
httplib::Server *m_httpServer;
quint16 m_u16HttpServerBindPort;
};
#endif // HTTPSD_H

6590
SparkWebAppRuntime/httplib.h Normal file

File diff suppressed because it is too large Load Diff

@ -14,12 +14,14 @@
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCommandLineOption> #include <QCommandLineOption>
#include "globaldefine.h"
#include <QTranslator> #include <QTranslator>
#include <QFileInfo> #include <QFileInfo>
#include <QSettings> #include <QSettings>
#include "globaldefine.h"
#include "httpd.h"
DWIDGET_USE_NAMESPACE DWIDGET_USE_NAMESPACE
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -109,6 +111,27 @@ int main(int argc, char *argv[])
DEFAULT_CFG); DEFAULT_CFG);
parser.addOption(optCfgFile); parser.addOption(optCfgFile);
QCommandLineOption optRootPath(QStringList() << "r" << "root",
QObject::tr("The root path of the program web service."),
"root",
DEFAULT_ROOT);
parser.addOption(optRootPath);
QCommandLineOption optPort(QStringList() << "P" << "port",
QObject::tr("The port number of the program web service."),
"port",
DEFAULT_PORT);
parser.addOption(optPort);
#if SSL_SERVER
QCommandLineOption optSSLPort(QStringList() << "s" << "sslport",
QObject::tr("The ssl port number of the program web service."),
"sslport",
DEFAULT_PORT);
parser.addOption(optSSLPort);
#endif
parser.process(a); parser.process(a);
QString szTitle = DEFAULT_TITLE; QString szTitle = DEFAULT_TITLE;
@ -117,6 +140,11 @@ int main(int argc, char *argv[])
int height = DEFAULT_HEIGHT; int height = DEFAULT_HEIGHT;
QString szIcon = DEFAULT_ICON; QString szIcon = DEFAULT_ICON;
QString szDesc = DEFAULT_DESC; QString szDesc = DEFAULT_DESC;
QString szRootPath = DEFAULT_ROOT;
quint16 u16Port = DEFAULT_PORT;
#if SSL_SERVER
quint16 u16sslPort = 0;
#endif
QString szCfgFile = DEFAULT_CFG; QString szCfgFile = DEFAULT_CFG;
if (parser.isSet(optCfgFile)) if (parser.isSet(optCfgFile))
@ -136,6 +164,11 @@ int main(int argc, char *argv[])
szDesc = QString("%1<br/><br/>%2") szDesc = QString("%1<br/><br/>%2")
.arg(settings.value("SpartWebAppRuntime/Desc", QString()).toString()) .arg(settings.value("SpartWebAppRuntime/Desc", QString()).toString())
.arg(szDefaultDesc); .arg(szDefaultDesc);
szRootPath = settings.value("SpartWebAppRuntime/RootPath", QString()).toString();
u16Port = settings.value("SpartWebAppRuntime/Port", 0).toUInt();
#if SSL_SERVER
u16sslPort = settings.value("SpartWebAppRuntime/SSLPort", 0).toUInt();
#endif
} }
} }
} }
@ -164,24 +197,33 @@ int main(int argc, char *argv[])
.arg(szDefaultDesc); .arg(szDefaultDesc);
} }
if (parser.isSet(optRootPath))
{
szRootPath = parser.value(optRootPath);
}
if (parser.isSet(optPort))
{
u16Port = parser.value(optPort).toUInt();
}
#if SSL_SERVER
if (parser.isSet(optSSLPort))
{
u16sslPort = parser.value(optSSLPort).toUInt();
}
#endif
if (!parser.isSet(optParser)) if (!parser.isSet(optParser))
{ {
do do
{ {
// 按照固定顺序级别最优先 // 按照固定顺序级别最优先
if (argc != 7) #if SSL_SERVER
{ if (argc != 10)
#if 0 #else
QMessageBox::information(nullptr, QObject::tr("Usage:"), if (argc != 9)
QObject::tr("The first usage: \n"
"%1 %2\n"
"The second usage:\n"
"%1 %3")
.arg(argv[0])
.arg(QObject::tr("Title URL Width Height"))
.arg(QObject::tr("-h to view parameter list.")));
return 0;
#endif #endif
{
break; break;
} }
@ -192,12 +234,32 @@ int main(int argc, char *argv[])
szIcon = QString(argv[5]); szIcon = QString(argv[5]);
szDesc = QString("%1<br/><br/>%2").arg(QString(argv[6])) szDesc = QString("%1<br/><br/>%2").arg(QString(argv[6]))
.arg(szDefaultDesc);; .arg(szDefaultDesc);;
szRootPath = QString(argv[7]);
u16Port = QString(argv[8]).toUInt();
#if SSL_SERVER
u16sslPort = QString(argv[9]).toUInt();
#endif
} }
while (false); while (false);
} }
MainWindow w(szTitle, szUrl, width, height); MainWindow w(szTitle, szUrl, width, height);
#if SSL_SERVER
if (!szRootPath.isEmpty() && u16Port > 0 && u16sslPort > 0)
{
HttpD httpd(szRootPath, u16Port, u16sslPort);
httpd.start();
}
#else
if (!szRootPath.isEmpty() && u16Port > 0)
{
static HttpD httpd(szRootPath, u16Port);
QObject::connect(&w, &MainWindow::sigQuit, &httpd, &HttpD::stop);
httpd.start();
}
#endif
if (parser.isSet(optIcon)) if (parser.isSet(optIcon))
{ {
szIcon = parser.value(optIcon); szIcon = parser.value(optIcon);

@ -65,6 +65,7 @@ MainWindow::MainWindow(QString szTitle,
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
emit sigQuit();
if (m_widget) if (m_widget)
{ {
delete m_widget; delete m_widget;

@ -22,6 +22,9 @@ public:
void setIcon(QString); void setIcon(QString);
signals:
void sigQuit();
private: private:
Widget *m_widget; Widget *m_widget;
}; };

@ -4,90 +4,79 @@
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../main.cpp" line="51"/> <location filename="../main.cpp" line="53"/>
<source>Presented By Spark developers # HadesStudio</source> <source>Presented By Spark developers # HadesStudio</source>
<translation> @ </translation> <translation> @ </translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="36"/> <location filename="../main.cpp" line="38"/>
<source>This program is open source under GPLv3</source> <source>This program is open source under GPLv3</source>
<translation>GPL第三版开源</translation> <translation>GPL第三版开源</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="54"/> <location filename="../main.cpp" line="56"/>
<source>Version</source> <source>Version</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="62"/> <location filename="../main.cpp" line="64"/>
<source>Description: %1</source> <source>Description: %1</source>
<translation>: %1</translation> <translation>: %1</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="67"/> <location filename="../main.cpp" line="69"/>
<source>Enable CommandLineParser. Default is false.</source> <source>Enable CommandLineParser. Default is false.</source>
<translation>. .</translation> <translation>. .</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="71"/> <location filename="../main.cpp" line="73"/>
<source>The Title of Application. Default is %1.</source> <source>The Title of Application. Default is %1.</source>
<translation>. %1.</translation> <translation>. %1.</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="77"/> <location filename="../main.cpp" line="79"/>
<source>The target URL. Default is Blank.</source> <source>The target URL. Default is Blank.</source>
<translation>URL. .</translation> <translation>URL. .</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="83"/> <location filename="../main.cpp" line="85"/>
<source>The Width of Application. Default is %1.</source> <source>The Width of Application. Default is %1.</source>
<translation>. %1.</translation> <translation>. %1.</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="89"/> <location filename="../main.cpp" line="91"/>
<source>The Height of Application. Default is %1</source> <source>The Height of Application. Default is %1</source>
<translation>. %1</translation> <translation>. %1</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="95"/> <location filename="../main.cpp" line="97"/>
<source>The ICON of Application.</source> <source>The ICON of Application.</source>
<translation>.</translation> <translation>.</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="101"/> <location filename="../main.cpp" line="103"/>
<source>The Description of Application.</source> <source>The Description of Application.</source>
<translation>.</translation> <translation>.</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="107"/> <location filename="../main.cpp" line="109"/>
<source>The Configuration file of Application.</source> <source>The Configuration file of Application.</source>
<translation>.</translation> <translation>.</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="175"/> <location filename="../main.cpp" line="115"/>
<source>Usage:</source> <source>The root path of the program web service.</source>
<translation>:</translation> <translation>WebServer的根路径.</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="176"/> <location filename="../main.cpp" line="122"/>
<source>The first usage: <source>The port number of the program web service.</source>
%1 %2 <translation>WebServer的监听端口号.</translation>
The second usage:
%1 %3</source>
<translation>:
%1 %2
:
%1 %3</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="181"/> <location filename="../main.cpp" line="129"/>
<source>Title URL Width Height</source> <source>The ssl port number of the program web service.</source>
<translation> </translation> <translation>WebServer的SSL协议的监听端口号.</translation>
</message>
<message>
<location filename="../main.cpp" line="182"/>
<source>-h to view parameter list.</source>
<translation>-h .</translation>
</message> </message>
<message> <message>
<location filename="../globaldefine.h" line="7"/> <location filename="../globaldefine.h" line="7"/>