新增内置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
@ -10,12 +10,15 @@ CONFIG += c++11 link_pkgconfig
PKGCONFIG += dtkwidget
SOURCES += main.cpp\
httpd.cpp \
mainwindow.cpp \
webenginepage.cpp \
widget.cpp
HEADERS += mainwindow.h \
globaldefine.h \
httpd.h \
httplib.h \
webenginepage.h \
widget.h

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

@ -29,6 +29,8 @@
-i, --ico <ico> 设置程序运行的图标.
-d, --desc <desc> 设置程序的描述信息.
-c, --cfg <cfg> 设置程序运行的配置文件.
-r, --root <root> 设置内置WebServer的根路径.
-P, --port <port> 设置内置WebServer的监听端口号.
</xmp>
<br/>
<span style="color: red">需要注意的是, 命令行会覆盖配置文件的配置信息.</span>
@ -59,6 +61,8 @@
-i, --ico <ico> The ICON of Application.
-d, --desc <desc> The Description 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>
<br/>
<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 <QCommandLineOption>
#include "globaldefine.h"
#include <QTranslator>
#include <QFileInfo>
#include <QSettings>
#include "globaldefine.h"
#include "httpd.h"
DWIDGET_USE_NAMESPACE
int main(int argc, char *argv[])
@ -109,6 +111,27 @@ int main(int argc, char *argv[])
DEFAULT_CFG);
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);
QString szTitle = DEFAULT_TITLE;
@ -117,6 +140,11 @@ int main(int argc, char *argv[])
int height = DEFAULT_HEIGHT;
QString szIcon = DEFAULT_ICON;
QString szDesc = DEFAULT_DESC;
QString szRootPath = DEFAULT_ROOT;
quint16 u16Port = DEFAULT_PORT;
#if SSL_SERVER
quint16 u16sslPort = 0;
#endif
QString szCfgFile = DEFAULT_CFG;
if (parser.isSet(optCfgFile))
@ -136,6 +164,11 @@ int main(int argc, char *argv[])
szDesc = QString("%1<br/><br/>%2")
.arg(settings.value("SpartWebAppRuntime/Desc", QString()).toString())
.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);
}
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))
{
do
{
// 按照固定顺序级别最优先
if (argc != 7)
{
#if 0
QMessageBox::information(nullptr, QObject::tr("Usage:"),
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;
#if SSL_SERVER
if (argc != 10)
#else
if (argc != 9)
#endif
{
break;
}
@ -192,12 +234,32 @@ int main(int argc, char *argv[])
szIcon = QString(argv[5]);
szDesc = QString("%1<br/><br/>%2").arg(QString(argv[6]))
.arg(szDefaultDesc);;
szRootPath = QString(argv[7]);
u16Port = QString(argv[8]).toUInt();
#if SSL_SERVER
u16sslPort = QString(argv[9]).toUInt();
#endif
}
while (false);
}
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))
{
szIcon = parser.value(optIcon);

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

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

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