#include #include #include "webserver.h" #ifdef FEATURE_REDIS #include #include "redisqtadapter.h" #endif #include #include #include static QHostAddress parseHostAddress(const QString &str); int main(int argc, char *argv[]) { qSetMessagePattern("%{time dd.MM.yyyy HH:mm:ss.zzz} " "[" "%{if-debug}D%{endif}" "%{if-info}I%{endif}" "%{if-warning}W%{endif}" "%{if-critical}C%{endif}" "%{if-fatal}F%{endif}" "] " "%{function}(): " "%{message}"); QCoreApplication app{argc, argv}; QCoreApplication::setApplicationName("less_shitty_proxyjs"); QCoreApplication::setApplicationVersion("1.0"); QHostAddress listenAddress = QHostAddress::Any; if (auto str = qgetenv("PROXYJS_LISTEN_ADDR"); !str.isEmpty()) listenAddress = parseHostAddress(str); uint16_t port = 8080; if (auto str = qgetenv("PROXYJS_PORT"); !str.isEmpty()) port = str.toInt(); QString identity = "proxyjs_" + QUuid::createUuid().toString(QUuid::WithoutBraces); if (auto str = qgetenv("PROXYJS_IDENTITY"); !str.isEmpty()) identity = str; #ifdef FEATURE_REDIS QString redisHost = "localhost"; if (auto str = qgetenv("PROXYJS_REDIS_HOST"); !str.isEmpty()) redisHost = str; QString redisPassword; if (auto str = qgetenv("PROXYJS_REDIS_PASSWORD"); !str.isEmpty()) redisPassword = str; QString endpointAddr; if (auto str = qgetenv("PROXYJS_ENDPOINT_ADDR"); !str.isEmpty()) endpointAddr = str; #endif { QCommandLineParser parser; parser.setApplicationDescription("Test helper"); parser.addHelpOption(); parser.addVersionOption(); QCommandLineOption listenAddrOption{QStringList{ "l", "listenAddress" }, QCoreApplication::translate("main", "The address to listen on (Can be \"Any\" \"Localhost\" or any valid ip address)."), QCoreApplication::translate("main", "listenAddress")}; parser.addOption(listenAddrOption); QCommandLineOption portOption{QStringList{ "p", "port" }, QCoreApplication::translate("main", "The port to listen on (will only listen on localhost)."), QCoreApplication::translate("main", "port")}; parser.addOption(portOption); QCommandLineOption identityOption{QStringList{ "i", "identity" }, QCoreApplication::translate("main", "The name of this service instance"), QCoreApplication::translate("main", "identity")}; parser.addOption(identityOption); #ifdef FEATURE_REDIS QCommandLineOption redisHostOption{QStringList{ "H", "redisHost" }, QCoreApplication::translate("main", "The redis host"), QCoreApplication::translate("main", "redisHost")}; parser.addOption(redisHostOption); QCommandLineOption redisPasswordOption{QStringList{ "r", "redisPassword" }, QCoreApplication::translate("main", "The redis password"), QCoreApplication::translate("main", "redisPassword")}; parser.addOption(redisPasswordOption); QCommandLineOption endpointAddrOption{QStringList{ "e", "endpointAddr" }, QCoreApplication::translate("main", "Endpoint address for traefik"), QCoreApplication::translate("main", "endpointAddr")}; parser.addOption(endpointAddrOption); #endif parser.process(app); if (parser.isSet(listenAddrOption)) { listenAddress = parseHostAddress(parser.value(listenAddrOption)); } if (parser.isSet(portOption)) { const auto &str = parser.value(portOption); bool ok; port = str.toInt(&ok); if (!ok) { qCritical("could not parse port: %s", qPrintable(str)); return -1; } } if (parser.isSet(identityOption)) identity = parser.value(identityOption); #ifdef FEATURE_REDIS if (parser.isSet(redisHostOption)) redisHost = parser.value(redisHostOption); if (parser.isSet(redisPasswordOption)) redisPassword = parser.value(redisPasswordOption); if (parser.isSet(endpointAddrOption)) endpointAddr = parser.value(endpointAddrOption); #endif } #ifdef FEATURE_REDIS if (endpointAddr.isEmpty()) endpointAddr = QString{"http://localhost:%0"}.arg(port); #endif qSetMessagePattern(QString{"%{time dd.MM.yyyy HH:mm:ss.zzz} %0 " "[" "%{if-debug}D%{endif}" "%{if-info}I%{endif}" "%{if-warning}W%{endif}" "%{if-critical}C%{endif}" "%{if-fatal}F%{endif}" "] " "%{function}(): " "%{message}"}.arg(identity)); #ifdef FEATURE_REDIS redisAsyncContext * const redis = redisAsyncConnect(redisHost.toUtf8().constData(), 6379); if (redis->err) qFatal("error with redis connection: %s", redis->errstr); RedisQtAdapter redisAdapter; redisAdapter.setContext(redis); if (!redisPassword.isEmpty()) { qDebug() << "redis AUTH" << redisPassword; redisAsyncCommand(redis, NULL, NULL, "AUTH %s", redisPassword.toUtf8().constData()); } qDebug() << "redis connected"; #endif WebServer server{identity #ifdef FEATURE_REDIS , redis #endif }; QTcpServer tcpServer; if (!tcpServer.listen(listenAddress, port)) { qCritical("failed to start listening on addr %s port %hu: %s", qPrintable(listenAddress.toString()), port, qPrintable(tcpServer.errorString())); return -1; } if (!server.bind(&tcpServer)) { qCritical("failed to webserver on socket!"); return -2; } #ifdef FEATURE_REDIS redisAsyncCommand(redis, NULL, NULL, "SET %s %s", QString{"traefik/http/services/%0/loadbalancer/servers/0/url"} .arg(identity).toUtf8().constData(), endpointAddr.toUtf8().constData() ); #endif qDebug() << "server started on" << listenAddress << "port" << port; auto result = app.exec(); #ifdef FEATURE_REDIS redisAsyncCommand(redis, NULL, NULL, "DEL %s", QString{"traefik/http/services/%0/loadbalancer/servers/0/url"} .arg(identity).toUtf8().constData()); #endif qDebug() << "bey bey!"; return result; } static QHostAddress parseHostAddress(const QString &str) { if (str == "Any") return QHostAddress::Any; else if (str == "AnyIPv4") return QHostAddress::AnyIPv4; else if (str == "AnyIPv6") return QHostAddress::AnyIPv6; else if (str == "LocalHost") return QHostAddress::LocalHost; else if (str == "LocalHostIPv6") return QHostAddress::LocalHostIPv6; else return QHostAddress{str}; }