diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 943895a4a0..1bad7d72f5 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -968,6 +968,12 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return false; } +bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &url) { + qDebug() << "HTTPS request received at" << url; + qDebug() << "not handling"; + return false; +} + void DomainServer::refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment) { QUuid oldUUID = assignment->getUUID(); assignment->resetUUID(); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 5c970748f1..40429e23ea 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -23,21 +23,21 @@ #include #include -#include -#include +#include #include #include "DTLSServerSession.h" typedef QSharedPointer SharedAssignmentPointer; -class DomainServer : public QCoreApplication, public HTTPRequestHandler { +class DomainServer : public QCoreApplication, public HTTPSRequestHandler { Q_OBJECT public: DomainServer(int argc, char* argv[]); ~DomainServer(); bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url); + bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url); void exit(int retCode = 0); diff --git a/libraries/embedded-webserver/src/HTTPManager.cpp b/libraries/embedded-webserver/src/HTTPManager.cpp index ff4ea9e6b4..ec5f16012e 100755 --- a/libraries/embedded-webserver/src/HTTPManager.cpp +++ b/libraries/embedded-webserver/src/HTTPManager.cpp @@ -18,116 +18,6 @@ #include "HTTPConnection.h" #include "HTTPManager.h" -bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url) { - if (_requestHandler && _requestHandler->handleHTTPRequest(connection, url)) { - // this request was handled by our _requestHandler object - // so we don't need to attempt to do so in the document root - return true; - } - - // check to see if there is a file to serve from the document root for this path - QString subPath = url.path(); - - // remove any slash at the beginning of the path - if (subPath.startsWith('/')) { - subPath.remove(0, 1); - } - - QString filePath; - - if (QFileInfo(_documentRoot + subPath).isFile()) { - filePath = _documentRoot + subPath; - } else if (subPath.size() > 0 && !subPath.endsWith('/')) { - // this could be a directory with a trailing slash - // send a redirect to the path with a slash so we can - QString redirectLocation = '/' + subPath + '/'; - - if (!url.query().isEmpty()) { - redirectLocation += "?" + url.query(); - } - - QHash redirectHeader; - redirectHeader.insert(QByteArray("Location"), redirectLocation.toUtf8()); - - connection->respond(HTTPConnection::StatusCode301, "", HTTPConnection::DefaultContentType, redirectHeader); - } - - // if the last thing is a trailing slash then we want to look for index file - if (subPath.endsWith('/') || subPath.size() == 0) { - QStringList possibleIndexFiles = QStringList() << "index.html" << "index.shtml"; - - foreach (const QString& possibleIndexFilename, possibleIndexFiles) { - if (QFileInfo(_documentRoot + subPath + possibleIndexFilename).exists()) { - filePath = _documentRoot + subPath + possibleIndexFilename; - break; - } - } - } - - if (!filePath.isEmpty()) { - // file exists, serve it - static QMimeDatabase mimeDatabase; - - QFile localFile(filePath); - localFile.open(QIODevice::ReadOnly); - QByteArray localFileData = localFile.readAll(); - - QFileInfo localFileInfo(filePath); - - if (localFileInfo.completeSuffix() == "shtml") { - // this is a file that may have some SSI statements - // the only thing we support is the include directive, but check the contents for that - - // setup our static QRegExp that will catch and directives - const QString includeRegExpString = ""; - QRegExp includeRegExp(includeRegExpString); - - int matchPosition = 0; - - QString localFileString(localFileData); - - while ((matchPosition = includeRegExp.indexIn(localFileString, matchPosition)) != -1) { - // check if this is a file or vitual include - bool isFileInclude = includeRegExp.cap(1) == "file"; - - // setup the correct file path for the included file - QString includeFilePath = isFileInclude - ? localFileInfo.canonicalPath() + "/" + includeRegExp.cap(2) - : _documentRoot + includeRegExp.cap(2); - - QString replacementString; - - if (QFileInfo(includeFilePath).isFile()) { - - QFile includedFile(includeFilePath); - includedFile.open(QIODevice::ReadOnly); - - replacementString = QString(includedFile.readAll()); - } else { - qDebug() << "SSI include directive referenced a missing file:" << includeFilePath; - } - - // replace the match with the contents of the file, or an empty string if the file was not found - localFileString.replace(matchPosition, includeRegExp.matchedLength(), replacementString); - - // push the match position forward so we can check the next match - matchPosition += includeRegExp.matchedLength(); - } - - localFileData = localFileString.toLocal8Bit(); - } - - connection->respond(HTTPConnection::StatusCode200, localFileData, - qPrintable(mimeDatabase.mimeTypeForFile(filePath).name())); - } else { - - // respond with a 404 - connection->respond(HTTPConnection::StatusCode404, "Resource not found."); - } - - return true; -} - HTTPManager::HTTPManager(quint16 port, const QString& documentRoot, HTTPRequestHandler* requestHandler, QObject* parent) : QTcpServer(parent), _documentRoot(documentRoot), @@ -149,3 +39,120 @@ void HTTPManager::incomingConnection(qintptr socketDescriptor) { delete socket; } } + +bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url) { + if (requestHandledByRequestHandler(connection, url)) { + // this request was handled by our request handler object + // so we don't need to attempt to do so in the document root + return true; + } + + if (!_documentRoot.isEmpty()) { + // check to see if there is a file to serve from the document root for this path + QString subPath = url.path(); + + // remove any slash at the beginning of the path + if (subPath.startsWith('/')) { + subPath.remove(0, 1); + } + + QString filePath; + + if (QFileInfo(_documentRoot + subPath).isFile()) { + filePath = _documentRoot + subPath; + } else if (subPath.size() > 0 && !subPath.endsWith('/')) { + // this could be a directory with a trailing slash + // send a redirect to the path with a slash so we can + QString redirectLocation = '/' + subPath + '/'; + + if (!url.query().isEmpty()) { + redirectLocation += "?" + url.query(); + } + + QHash redirectHeader; + redirectHeader.insert(QByteArray("Location"), redirectLocation.toUtf8()); + + connection->respond(HTTPConnection::StatusCode301, "", HTTPConnection::DefaultContentType, redirectHeader); + } + + // if the last thing is a trailing slash then we want to look for index file + if (subPath.endsWith('/') || subPath.size() == 0) { + QStringList possibleIndexFiles = QStringList() << "index.html" << "index.shtml"; + + foreach (const QString& possibleIndexFilename, possibleIndexFiles) { + if (QFileInfo(_documentRoot + subPath + possibleIndexFilename).exists()) { + filePath = _documentRoot + subPath + possibleIndexFilename; + break; + } + } + } + + if (!filePath.isEmpty()) { + // file exists, serve it + static QMimeDatabase mimeDatabase; + + QFile localFile(filePath); + localFile.open(QIODevice::ReadOnly); + QByteArray localFileData = localFile.readAll(); + + QFileInfo localFileInfo(filePath); + + if (localFileInfo.completeSuffix() == "shtml") { + // this is a file that may have some SSI statements + // the only thing we support is the include directive, but check the contents for that + + // setup our static QRegExp that will catch and directives + const QString includeRegExpString = ""; + QRegExp includeRegExp(includeRegExpString); + + int matchPosition = 0; + + QString localFileString(localFileData); + + while ((matchPosition = includeRegExp.indexIn(localFileString, matchPosition)) != -1) { + // check if this is a file or vitual include + bool isFileInclude = includeRegExp.cap(1) == "file"; + + // setup the correct file path for the included file + QString includeFilePath = isFileInclude + ? localFileInfo.canonicalPath() + "/" + includeRegExp.cap(2) + : _documentRoot + includeRegExp.cap(2); + + QString replacementString; + + if (QFileInfo(includeFilePath).isFile()) { + + QFile includedFile(includeFilePath); + includedFile.open(QIODevice::ReadOnly); + + replacementString = QString(includedFile.readAll()); + } else { + qDebug() << "SSI include directive referenced a missing file:" << includeFilePath; + } + + // replace the match with the contents of the file, or an empty string if the file was not found + localFileString.replace(matchPosition, includeRegExp.matchedLength(), replacementString); + + // push the match position forward so we can check the next match + matchPosition += includeRegExp.matchedLength(); + } + + localFileData = localFileString.toLocal8Bit(); + } + + connection->respond(HTTPConnection::StatusCode200, localFileData, + qPrintable(mimeDatabase.mimeTypeForFile(filePath).name())); + + return true; + } + } + + // respond with a 404 + connection->respond(HTTPConnection::StatusCode404, "Resource not found."); + + return true; +} + +bool HTTPManager::requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url) { + return _requestHandler && _requestHandler->handleHTTPRequest(connection, url); +} \ No newline at end of file diff --git a/libraries/embedded-webserver/src/HTTPManager.h b/libraries/embedded-webserver/src/HTTPManager.h index ea2936f464..e8745521dc 100755 --- a/libraries/embedded-webserver/src/HTTPManager.h +++ b/libraries/embedded-webserver/src/HTTPManager.h @@ -19,6 +19,7 @@ #include class HTTPConnection; +class HTTPSConnection; class HTTPRequestHandler { public: @@ -38,6 +39,7 @@ public: protected: /// Accepts all pending connections virtual void incomingConnection(qintptr socketDescriptor); + virtual bool requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url); protected: QString _documentRoot; HTTPRequestHandler* _requestHandler; diff --git a/libraries/embedded-webserver/src/HTTPSManager.cpp b/libraries/embedded-webserver/src/HTTPSManager.cpp index 0f5b94de64..4e40a0e02c 100644 --- a/libraries/embedded-webserver/src/HTTPSManager.cpp +++ b/libraries/embedded-webserver/src/HTTPSManager.cpp @@ -16,10 +16,11 @@ #include "HTTPSManager.h" HTTPSManager::HTTPSManager(quint16 port, const QSslCertificate& certificate, const QSslKey& privateKey, - const QString& documentRoot, HTTPRequestHandler* requestHandler, QObject* parent) : + const QString& documentRoot, HTTPSRequestHandler* requestHandler, QObject* parent) : HTTPManager(port, documentRoot, requestHandler, parent), _certificate(certificate), - _privateKey(privateKey) + _privateKey(privateKey), + _sslRequestHandler(requestHandler) { } @@ -35,4 +36,16 @@ void HTTPSManager::incomingConnection(qintptr socketDescriptor) { } else { delete sslSocket; } +} + +bool HTTPSManager::handleHTTPRequest(HTTPConnection* connection, const QUrl &url) { + return handleHTTPSRequest(reinterpret_cast(connection), url); +} + +bool HTTPSManager::handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url) { + return HTTPManager::handleHTTPRequest(connection, url); +} + +bool HTTPSManager::requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url) { + return _sslRequestHandler && _sslRequestHandler->handleHTTPSRequest(reinterpret_cast(connection), url); } \ No newline at end of file diff --git a/libraries/embedded-webserver/src/HTTPSManager.h b/libraries/embedded-webserver/src/HTTPSManager.h index 8940b2e79d..fe7c4dc065 100644 --- a/libraries/embedded-webserver/src/HTTPSManager.h +++ b/libraries/embedded-webserver/src/HTTPSManager.h @@ -17,23 +17,34 @@ #include "HTTPManager.h" -class HTTPSManager : public HTTPManager { +class HTTPSRequestHandler : public HTTPRequestHandler { +public: + /// Handles an HTTPS request + virtual bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url) = 0; +}; + +class HTTPSManager : public HTTPManager, public HTTPSRequestHandler { Q_OBJECT public: HTTPSManager(quint16 port, const QSslCertificate& certificate, const QSslKey& privateKey, const QString& documentRoot, - HTTPRequestHandler* requestHandler = NULL, QObject* parent = 0); + HTTPSRequestHandler* requestHandler = NULL, QObject* parent = 0); void setCertificate(const QSslCertificate& certificate) { _certificate = certificate; } void setPrivateKey(const QSslKey& privateKey) { _privateKey = privateKey; } + bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url); + bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url); + protected: - virtual void incomingConnection(qintptr socketDescriptor); + void incomingConnection(qintptr socketDescriptor); + bool requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url); private: QSslCertificate _certificate; QSslKey _privateKey; + HTTPSRequestHandler* _sslRequestHandler; }; #endif // hifi_HTTPSManager_h \ No newline at end of file