HttpServer: use settings structure as an object not a pointer

This commit is contained in:
f4exb 2017-11-13 13:46:02 +01:00
parent 583712a3d5
commit cf9c7eb8bb
12 changed files with 151 additions and 82 deletions

View File

@ -5,7 +5,6 @@
#include "httpconnectionhandler.h"
#include "httpresponse.h"
#include "httplistenersettings.h"
using namespace qtwebapp;
@ -15,7 +14,6 @@ HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHan
Q_ASSERT(settings!=0);
Q_ASSERT(requestHandler!=0);
this->settings=settings;
this->listenerSettings=0;
this->requestHandler=requestHandler;
this->sslConfiguration=sslConfiguration;
currentRequest=0;
@ -39,13 +37,12 @@ HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHan
this->start();
}
HttpConnectionHandler::HttpConnectionHandler(HttpListenerSettings* settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration)
HttpConnectionHandler::HttpConnectionHandler(const HttpListenerSettings& settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration)
: QThread(), useQtSettings(false)
{
Q_ASSERT(settings!=0);
Q_ASSERT(requestHandler!=0);
this->settings=0;
this->listenerSettings=settings;
listenerSettings=settings;
this->requestHandler=requestHandler;
this->sslConfiguration=sslConfiguration;
currentRequest=0;
@ -141,7 +138,7 @@ void HttpConnectionHandler::handleConnection(tSocketDescriptor socketDescriptor)
#endif
// Start timer for read timeout
int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings->readTimeout;
int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings.readTimeout;
readTimer.start(readTimeout);
// delete previous request
delete currentRequest;
@ -205,7 +202,7 @@ void HttpConnectionHandler::read()
{
// Restart timer for read timeout, otherwise it would
// expire during large file uploads.
int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings->readTimeout;
int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings.readTimeout;
readTimer.start(readTimeout);
}
}
@ -299,7 +296,7 @@ void HttpConnectionHandler::read()
else
{
// Start timer for next request
int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings->readTimeout;
int readTimeout = useQtSettings ? settings->value("readTimeout",10000).toInt() : listenerSettings.readTimeout;
readTimer.start(readTimeout);
}
delete currentRequest;

View File

@ -16,11 +16,10 @@
#include "httpglobal.h"
#include "httprequest.h"
#include "httprequesthandler.h"
#include "httplistenersettings.h"
namespace qtwebapp {
class HttpListenerSettings;
/** Alias type definition, for compatibility to different Qt versions */
#if QT_VERSION >= 0x050000
typedef qintptr tSocketDescriptor;
@ -56,12 +55,19 @@ public:
/**
Constructor.
@param settings Configuration settings of the HTTP webserver
@param settings Configuration settings of the HTTP webserver as Qt settings
@param requestHandler Handler that will process each incoming HTTP request
@param sslConfiguration SSL (HTTPS) will be used if not NULL
*/
HttpConnectionHandler(QSettings* settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration=NULL);
HttpConnectionHandler(HttpListenerSettings* settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration=NULL);
/**
Constructor.
@param settings Configuration settings of the HTTP webserver as a structure
@param requestHandler Handler that will process each incoming HTTP request
@param sslConfiguration SSL (HTTPS) will be used if not NULL
*/
HttpConnectionHandler(const HttpListenerSettings& settings, HttpRequestHandler* requestHandler, QSslConfiguration* sslConfiguration=NULL);
/** Destructor */
virtual ~HttpConnectionHandler();
@ -72,11 +78,26 @@ public:
/** Mark this handler as busy */
void setBusy();
/**
* Get a listener settings copy
* @return The current listener settings
*/
HttpListenerSettings getListenerSettings() const { return listenerSettings; }
/**
* Set new listener settings data
* @param Listener settings to replace current data
*/
void setListenerSettings(const HttpListenerSettings& settings) { listenerSettings = settings; }
private:
/** Configuration settings */
QSettings* settings;
HttpListenerSettings* listenerSettings;
/** Configuration settings */
HttpListenerSettings listenerSettings;
/** TCP socket of the current connection */
QTcpSocket* socket;

View File

@ -6,7 +6,6 @@
#endif
#include <QDir>
#include "httpconnectionhandlerpool.h"
#include "httplistenersettings.h"
using namespace qtwebapp;
@ -15,7 +14,6 @@ HttpConnectionHandlerPool::HttpConnectionHandlerPool(QSettings* settings, HttpRe
{
Q_ASSERT(settings!=0);
this->settings=settings;
this->listenerSettings=0;
this->requestHandler=requestHandler;
this->sslConfiguration=NULL;
loadSslConfig();
@ -23,16 +21,15 @@ HttpConnectionHandlerPool::HttpConnectionHandlerPool(QSettings* settings, HttpRe
connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup()));
}
HttpConnectionHandlerPool::HttpConnectionHandlerPool(HttpListenerSettings* settings, HttpRequestHandler* requestHandler)
: QObject()
HttpConnectionHandlerPool::HttpConnectionHandlerPool(const HttpListenerSettings& settings, HttpRequestHandler* requestHandler)
: QObject(), useQtSettings(false)
{
Q_ASSERT(settings!=0);
this->settings=0;
this->listenerSettings=settings;
listenerSettings=settings;
this->requestHandler=requestHandler;
this->sslConfiguration=NULL;
loadSslConfig();
cleanupTimer.start(settings->cleanupInterval);
cleanupTimer.start(settings.cleanupInterval);
connect(&cleanupTimer, SIGNAL(timeout()), SLOT(cleanup()));
}
@ -66,7 +63,7 @@ HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler()
// create a new handler, if necessary
if (!freeHandler)
{
int maxConnectionHandlers = useQtSettings ? settings->value("maxThreads",100).toInt() : listenerSettings->maxThreads;
int maxConnectionHandlers = useQtSettings ? settings->value("maxThreads",100).toInt() : listenerSettings.maxThreads;
if (pool.count()<maxConnectionHandlers)
{
freeHandler=new HttpConnectionHandler(settings,requestHandler,sslConfiguration);
@ -81,7 +78,7 @@ HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler()
void HttpConnectionHandlerPool::cleanup()
{
int maxIdleHandlers = useQtSettings ? settings->value("minThreads",1).toInt() : listenerSettings->minThreads;
int maxIdleHandlers = useQtSettings ? settings->value("minThreads",1).toInt() : listenerSettings.minThreads;
int idleCounter=0;
mutex.lock();
foreach(HttpConnectionHandler* handler, pool)
@ -104,8 +101,8 @@ void HttpConnectionHandlerPool::cleanup()
void HttpConnectionHandlerPool::loadSslConfig()
{
// If certificate and key files are configured, then load them
QString sslKeyFileName = useQtSettings ? settings->value("sslKeyFile","").toString() : listenerSettings->sslKeyFile;
QString sslCertFileName = useQtSettings ? settings->value("sslCertFile","").toString() : listenerSettings->sslCertFile;
QString sslKeyFileName = useQtSettings ? settings->value("sslKeyFile","").toString() : listenerSettings.sslKeyFile;
QString sslCertFileName = useQtSettings ? settings->value("sslCertFile","").toString() : listenerSettings.sslCertFile;
if (!sslKeyFileName.isEmpty() && !sslCertFileName.isEmpty())
{
#ifdef QT_NO_OPENSSL

View File

@ -7,6 +7,7 @@
#include <QMutex>
#include "httpglobal.h"
#include "httpconnectionhandler.h"
#include "httplistenersettings.h"
namespace qtwebapp {
@ -45,8 +46,6 @@ namespace qtwebapp {
@see HttpRequest for description of config settings maxRequestSize and maxMultiPartSize
*/
class HttpListenerSettings;
class DECLSPEC HttpConnectionHandlerPool : public QObject {
Q_OBJECT
Q_DISABLE_COPY(HttpConnectionHandlerPool)
@ -59,7 +58,14 @@ public:
@warning The requestMapper gets deleted by the destructor of this pool
*/
HttpConnectionHandlerPool(QSettings* settings, HttpRequestHandler* requestHandler);
HttpConnectionHandlerPool(HttpListenerSettings* settings, HttpRequestHandler* requestHandler);
/**
Constructor.
@param settings Configuration settings for the HTTP server as structure
@param requestHandler The handler that will process each received HTTP request.
@warning The requestMapper gets deleted by the destructor of this pool
*/
HttpConnectionHandlerPool(const HttpListenerSettings& settings, HttpRequestHandler* requestHandler);
/** Destructor */
virtual ~HttpConnectionHandlerPool();
@ -67,11 +73,25 @@ public:
/** Get a free connection handler, or 0 if not available. */
HttpConnectionHandler* getConnectionHandler();
/**
* Get a listener settings copy
* @return The current listener settings
*/
HttpListenerSettings getListenerSettings() const { return listenerSettings; }
/**
* Set new listener settings data
* @param Listener settings to replace current data
*/
void setListenerSettings(const HttpListenerSettings& settings) { listenerSettings = settings; }
private:
/** Settings for this pool */
/** Settings for this pool as Qt settings*/
QSettings* settings;
HttpListenerSettings* listenerSettings;
/** Settings for this pool as structure*/
HttpListenerSettings listenerSettings;
/** Will be assigned to each Connectionhandler during their creation */
HttpRequestHandler* requestHandler;

View File

@ -6,7 +6,6 @@
#include "httplistener.h"
#include "httpconnectionhandler.h"
#include "httpconnectionhandlerpool.h"
#include "httplistenersettings.h"
#include <QCoreApplication>
@ -19,7 +18,6 @@ HttpListener::HttpListener(QSettings* settings, HttpRequestHandler* requestHandl
Q_ASSERT(requestHandler != 0);
pool = 0;
this->settings = settings;
this->listenerSettings = 0;
this->requestHandler = requestHandler;
// Reqister type of socketDescriptor for signal/slot handling
qRegisterMetaType<tSocketDescriptor>("tSocketDescriptor");
@ -27,14 +25,13 @@ HttpListener::HttpListener(QSettings* settings, HttpRequestHandler* requestHandl
listen();
}
HttpListener::HttpListener(HttpListenerSettings* settings, HttpRequestHandler* requestHandler, QObject *parent)
HttpListener::HttpListener(const HttpListenerSettings& settings, HttpRequestHandler* requestHandler, QObject *parent)
: QTcpServer(parent), useQtSettings(false)
{
Q_ASSERT(settings != 0);
Q_ASSERT(requestHandler != 0);
pool = 0;
this->settings = 0;
this->listenerSettings = settings;
listenerSettings = settings;
this->requestHandler = requestHandler;
// Reqister type of socketDescriptor for signal/slot handling
qRegisterMetaType<tSocketDescriptor>("tSocketDescriptor");
@ -56,8 +53,8 @@ void HttpListener::listen()
{
pool=new HttpConnectionHandlerPool(settings,requestHandler);
}
QString host = useQtSettings ? settings->value("host").toString() : listenerSettings->host;
int port = useQtSettings ? settings->value("port").toInt() : listenerSettings->port;
QString host = useQtSettings ? settings->value("host").toString() : listenerSettings.host;
int port = useQtSettings ? settings->value("port").toInt() : listenerSettings.port;
QTcpServer::listen(host.isEmpty() ? QHostAddress::Any : QHostAddress(host), port);
if (!isListening())
{

View File

@ -13,6 +13,7 @@
#include "httpconnectionhandler.h"
#include "httpconnectionhandlerpool.h"
#include "httprequesthandler.h"
#include "httplistenersettings.h"
namespace qtwebapp {
@ -41,8 +42,6 @@ namespace qtwebapp {
@see HttpRequest for description of config settings maxRequestSize and maxMultiPartSize
*/
class HttpListenerSettings;
class DECLSPEC HttpListener : public QTcpServer {
Q_OBJECT
Q_DISABLE_COPY(HttpListener)
@ -57,7 +56,16 @@ public:
@warning Ensure to close or delete the listener before deleting the request handler.
*/
HttpListener(QSettings* settings, HttpRequestHandler* requestHandler, QObject* parent = NULL);
HttpListener(HttpListenerSettings* settings, HttpRequestHandler* requestHandler, QObject* parent = NULL);
/**
Constructor.
Creates a connection pool and starts listening on the configured host and port.
@param settings Configuration settings for the HTTP server as a structure.
@param requestHandler Processes each received HTTP request, usually by dispatching to controller classes.
@param parent Parent object.
@warning Ensure to close or delete the listener before deleting the request handler.
*/
HttpListener(const HttpListenerSettings& settings, HttpRequestHandler* requestHandler, QObject* parent = NULL);
/** Destructor */
virtual ~HttpListener();
@ -73,6 +81,18 @@ public:
*/
void close();
/**
* Get a listener settings copy
* @return The current listener settings
*/
HttpListenerSettings getListenerSettings() const { return listenerSettings; }
/**
* Set new listener settings data
* @param Listener settings to replace current data
*/
void setListenerSettings(const HttpListenerSettings& settings) { listenerSettings = settings; }
protected:
/** Serves new incoming connection requests */
@ -82,7 +102,9 @@ private:
/** Configuration settings for the HTTP server */
QSettings* settings;
HttpListenerSettings* listenerSettings;
/** Configuration settings for the HTTP server as a structure */
HttpListenerSettings listenerSettings;
/** Point to the reuqest handler which processes all HTTP requests */
HttpRequestHandler* requestHandler;

View File

@ -12,24 +12,24 @@
using namespace qtwebapp;
HttpRequest::HttpRequest(QSettings* settings) : useQtSettings(true)
HttpRequest::HttpRequest(QSettings* settings)
{
status=waitForRequest;
currentSize=0;
expectedBodySize=0;
maxSize=settings->value("maxRequestSize","16000").toInt();
maxMultiPartSize=settings->value("maxMultiPartSize","1000000").toInt();
tempFile=NULL;
tempFile=0;
}
HttpRequest::HttpRequest(HttpListenerSettings* settings) : useQtSettings(false)
HttpRequest::HttpRequest(const HttpListenerSettings& settings)
{
status=waitForRequest;
currentSize=0;
expectedBodySize=0;
maxSize=settings->maxRequestSize;
maxMultiPartSize=settings->maxMultiPartSize;
tempFile=NULL;
maxSize=settings.maxRequestSize;
maxMultiPartSize=settings.maxMultiPartSize;
tempFile=0;
}

View File

@ -15,6 +15,7 @@
#include <QTemporaryFile>
#include <QUuid>
#include "httpglobal.h"
#include "httplistenersettings.h"
namespace qtwebapp {
@ -35,8 +36,6 @@ namespace qtwebapp {
The body is always a little larger than the file itself.
*/
class HttpListenerSettings;
class DECLSPEC HttpRequest {
Q_DISABLE_COPY(HttpRequest)
friend class HttpSessionStore;
@ -51,7 +50,12 @@ public:
@param settings Configuration settings
*/
HttpRequest(QSettings* settings);
HttpRequest(HttpListenerSettings* settings);
/**
Constructor.
@param settings Configuration settings as a structure
*/
HttpRequest(const HttpListenerSettings& settings);
/**
Destructor.
@ -235,9 +239,6 @@ private:
/** Buffer for collecting characters of request and header lines */
QByteArray lineBuffer;
/** settings flag */
bool useQtSettings;
};
} // end of namespace

View File

@ -4,7 +4,6 @@
*/
#include "httpsessionstore.h"
#include "httpsessionssettings.h"
#include <QDateTime>
#include <QUuid>
@ -12,7 +11,7 @@
using namespace qtwebapp;
HttpSessionStore::HttpSessionStore(QSettings* settings, QObject* parent)
:QObject(parent), sessionsSettings(0), useQtSettings(true)
:QObject(parent), useQtSettings(true)
{
this->settings=settings;
connect(&cleanupTimer,SIGNAL(timeout()),this,SLOT(sessionTimerEvent()));
@ -22,14 +21,14 @@ HttpSessionStore::HttpSessionStore(QSettings* settings, QObject* parent)
qDebug("HttpSessionStore: Sessions expire after %i milliseconds",expirationTime);
}
HttpSessionStore::HttpSessionStore(HttpSessionsSettings* settings, QObject* parent)
HttpSessionStore::HttpSessionStore(const HttpSessionsSettings& settings, QObject* parent)
:QObject(parent), settings(0), useQtSettings(false)
{
this->sessionsSettings=settings;
sessionsSettings=settings;
connect(&cleanupTimer,SIGNAL(timeout()),this,SLOT(sessionTimerEvent()));
cleanupTimer.start(60000);
cookieName=QByteArray(qPrintable(settings->cookieName));
expirationTime=settings->expirationTime;
cookieName=QByteArray(qPrintable(settings.cookieName));
expirationTime=settings.expirationTime;
qDebug("HttpSessionStore: Sessions expire after %i milliseconds",expirationTime);
}
@ -73,10 +72,10 @@ HttpSession HttpSessionStore::getSession(HttpRequest& request, HttpResponse& res
{
mutex.unlock();
// Refresh the session cookie
QByteArray cookieName = useQtSettings ? settings->value("cookieName","sessionid").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookieName));
QByteArray cookiePath = useQtSettings ? settings->value("cookiePath").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookiePath));
QByteArray cookieComment = useQtSettings ? settings->value("cookieComment").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookieComment));
QByteArray cookieDomain = useQtSettings ? settings->value("cookieDomain").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookieDomain));
QByteArray cookieName = useQtSettings ? settings->value("cookieName","sessionid").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookieName));
QByteArray cookiePath = useQtSettings ? settings->value("cookiePath").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookiePath));
QByteArray cookieComment = useQtSettings ? settings->value("cookieComment").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookieComment));
QByteArray cookieDomain = useQtSettings ? settings->value("cookieDomain").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookieDomain));
response.setCookie(HttpCookie(cookieName,session.getId(),expirationTime/1000,cookiePath,cookieComment,cookieDomain));
session.setLastAccess();
return session;
@ -85,10 +84,10 @@ HttpSession HttpSessionStore::getSession(HttpRequest& request, HttpResponse& res
// Need to create a new session
if (allowCreate)
{
QByteArray cookieName = useQtSettings ? settings->value("cookieName","sessionid").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookieName));
QByteArray cookiePath = useQtSettings ? settings->value("cookiePath").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookiePath));
QByteArray cookieComment = useQtSettings ? settings->value("cookieComment").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookieComment));
QByteArray cookieDomain = useQtSettings ? settings->value("cookieDomain").toByteArray() : QByteArray(qPrintable(sessionsSettings->cookieDomain));
QByteArray cookieName = useQtSettings ? settings->value("cookieName","sessionid").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookieName));
QByteArray cookiePath = useQtSettings ? settings->value("cookiePath").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookiePath));
QByteArray cookieComment = useQtSettings ? settings->value("cookieComment").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookieComment));
QByteArray cookieDomain = useQtSettings ? settings->value("cookieDomain").toByteArray() : QByteArray(qPrintable(sessionsSettings.cookieDomain));
HttpSession session(true);
qDebug("HttpSessionStore: create new session with ID %s",session.getId().data());
sessions.insert(session.getId(),session);

View File

@ -14,11 +14,10 @@
#include "httpsession.h"
#include "httpresponse.h"
#include "httprequest.h"
#include "httpsessionssettings.h"
namespace qtwebapp {
class HttpSessionsSettings;
/**
Stores HTTP sessions and deletes them when they have expired.
The following configuration settings are required in the config file:
@ -39,9 +38,11 @@ class DECLSPEC HttpSessionStore : public QObject {
Q_DISABLE_COPY(HttpSessionStore)
public:
/** Constructor. */
/** Constructor with Qt settings. */
HttpSessionStore(QSettings* settings, QObject* parent=NULL);
HttpSessionStore(HttpSessionsSettings* settings, QObject* parent=NULL);
/** Constructor with settings structure. */
HttpSessionStore(const HttpSessionsSettings& settings, QObject* parent=NULL);
/** Destructor */
virtual ~HttpSessionStore();
@ -81,15 +82,29 @@ public:
/** Delete a session */
void removeSession(HttpSession session);
/**
* Get a sessions settings copy
* @return The current sessions settings
*/
HttpSessionsSettings getListenerSettings() const { return sessionsSettings; }
/**
* Set new sessions settings data
* @param sessions settings to replace current data
*/
void setListenerSettings(const HttpSessionsSettings& settings) { sessionsSettings = settings; }
protected:
/** Storage for the sessions */
QMap<QByteArray,HttpSession> sessions;
private:
/** Configuration settings */
/** Configuration settings as Qt settings*/
QSettings* settings;
HttpSessionsSettings *sessionsSettings;
/** Configuration settings as a structure*/
HttpSessionsSettings sessionsSettings;
/** Timer to remove expired sessions */
QTimer cleanupTimer;

View File

@ -38,12 +38,12 @@ StaticFileController::StaticFileController(QSettings* settings, QObject* parent)
qDebug("StaticFileController: cache timeout=%i, size=%i",cacheTimeout,cache.maxCost());
}
StaticFileController::StaticFileController(HttpDocrootSettings* settings, QObject* parent)
StaticFileController::StaticFileController(const HttpDocrootSettings& settings, QObject* parent)
:HttpRequestHandler(parent), useQtSettings(false)
{
maxAge=settings->maxAge;
encoding=settings->encoding;
docroot=settings->path;
maxAge=settings.maxAge;
encoding=settings.encoding;
docroot=settings.path;
if(!(docroot.startsWith(":/") || docroot.startsWith("qrc://")))
{
// Convert relative path to absolute, based on the directory of the config file.
@ -53,9 +53,9 @@ StaticFileController::StaticFileController(HttpDocrootSettings* settings, QObjec
}
}
qDebug("StaticFileController: docroot=%s, encoding=%s, maxAge=%i",qPrintable(docroot),qPrintable(encoding),maxAge);
maxCachedFileSize=settings->maxCachedFileSize;
cache.setMaxCost(settings->cacheSize);
cacheTimeout=settings->cacheTime;
maxCachedFileSize=settings.maxCachedFileSize;
cache.setMaxCost(settings.cacheSize);
cacheTimeout=settings.cacheTime;
qDebug("StaticFileController: cache timeout=%i, size=%i",cacheTimeout,cache.maxCost());
}

View File

@ -49,11 +49,11 @@ class DECLSPEC StaticFileController : public HttpRequestHandler {
Q_DISABLE_COPY(StaticFileController)
public:
/** Constructor */
/** Constructor with Qt settings*/
StaticFileController(QSettings* settings, QObject* parent = NULL);
/** Constructor */
StaticFileController(HttpDocrootSettings* settings, QObject* parent = NULL);
/** Constructor with settings structure */
StaticFileController(const HttpDocrootSettings& settings, QObject* parent = NULL);
/** Generates the response */
void service(HttpRequest& request, HttpResponse& response);