mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
allow DS to handle incoming HTTPS requests
This commit is contained in:
parent
0bc17b0852
commit
4a68c2e9c4
6 changed files with 157 additions and 118 deletions
|
@ -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();
|
||||
|
|
|
@ -23,21 +23,21 @@
|
|||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include <Assignment.h>
|
||||
#include <HTTPManager.h>
|
||||
#include <HTTPSManager.h>
|
||||
#include <HTTPSConnection.h>
|
||||
#include <LimitedNodeList.h>
|
||||
|
||||
#include "DTLSServerSession.h"
|
||||
|
||||
typedef QSharedPointer<Assignment> 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);
|
||||
|
||||
|
|
|
@ -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<QByteArray, QByteArray> 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 <!--#include virtual ... --> and <!--#include file .. --> directives
|
||||
const QString includeRegExpString = "<!--\\s*#include\\s+(virtual|file)\\s?=\\s?\"(\\S+)\"\\s*-->";
|
||||
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<QByteArray, QByteArray> 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 <!--#include virtual ... --> and <!--#include file .. --> directives
|
||||
const QString includeRegExpString = "<!--\\s*#include\\s+(virtual|file)\\s?=\\s?\"(\\S+)\"\\s*-->";
|
||||
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);
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
#include <QtNetwork/QTcpServer>
|
||||
|
||||
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;
|
||||
|
|
|
@ -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<HTTPSConnection*>(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<HTTPSConnection*>(connection), url);
|
||||
}
|
|
@ -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
|
Loading…
Reference in a new issue