8 Commits

Author SHA1 Message Date
4b590a4388 Fixes for TirugaDashboard 2026-04-08 22:22:50 +02:00
Philipp Swoboda
a01974171f Add runtime libraries during install steps 2025-03-03 09:34:22 +01:00
Philipp Swoboda
75dc1cc25d Add LabMCT install instructions 2025-02-28 15:13:21 +01:00
ef3942807f Add special install rules for LabMCT 2024-03-20 15:35:56 +01:00
a814dea032 Add HTTP PATCH request 2023-06-12 18:56:23 +02:00
4aba620039 Add remove user function in basicauthmiddleware 2023-06-09 12:51:42 +02:00
0960b2c7f7 Update 'CMakeLists.txt' 2023-06-08 12:37:05 +02:00
Philipp Swoboda
90fc0a01b0 Make qhttpengine compatible with Qt6 2023-06-07 22:31:55 +02:00
17 changed files with 151 additions and 171 deletions

View File

@@ -13,6 +13,10 @@ set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_
# Build a shared library by default # Build a shared library by default
option(BUILD_SHARED_LIBS "Build QHttpEngine as a shared library" ON) option(BUILD_SHARED_LIBS "Build QHttpEngine as a shared library" ON)
option(BUILD_AGAINST_QT6 "Build against Qt6" ON)
option(BUILD_FOR_LABMCT "Build for LabMCT" OFF)
set(BUILD_FOR_LABMCT ON)
set(BIN_INSTALL_DIR bin CACHE STRING "Binary runtime installation directory relative to the install prefix") set(BIN_INSTALL_DIR bin CACHE STRING "Binary runtime installation directory relative to the install prefix")
set(LIB_INSTALL_DIR lib CACHE STRING "Library installation directory relative to the install prefix") set(LIB_INSTALL_DIR lib CACHE STRING "Library installation directory relative to the install prefix")
@@ -21,8 +25,14 @@ set(INCLUDE_INSTALL_DIR include CACHE STRING "Header installation directory rela
set(DOC_INSTALL_DIR share/doc/qhttpengine CACHE STRING "Documentation installation directory relative to the install prefix") set(DOC_INSTALL_DIR share/doc/qhttpengine CACHE STRING "Documentation installation directory relative to the install prefix")
set(EXAMPLES_INSTALL_DIR "${LIB_INSTALL_DIR}/qhttpengine/examples" CACHE STRING "Examples installation directory relative to the install prefix") set(EXAMPLES_INSTALL_DIR "${LIB_INSTALL_DIR}/qhttpengine/examples" CACHE STRING "Examples installation directory relative to the install prefix")
find_package(Qt5Network 5.4 REQUIRED)
if(BUILD_AGAINST_QT6)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Core5Compat Network REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Core5Compat Network REQUIRED)
else()
find_package(QT NAMES Qt5 COMPONENTS Core Network REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED)
endif()
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
add_subdirectory(src) add_subdirectory(src)
@@ -38,22 +48,22 @@ if(BUILD_EXAMPLES)
add_subdirectory(examples) add_subdirectory(examples)
endif() endif()
option(BUILD_TESTS "Build the test suite" OFF) #option(BUILD_TESTS "Build the test suite" OFF)
if(BUILD_TESTS) #if(BUILD_TESTS)
find_package(Qt5Test 5.4 REQUIRED) # find_package(Qt${QT_VERSION_MAJOR}Test REQUIRED)
enable_testing() # enable_testing()
add_subdirectory(tests) # add_subdirectory(tests)
endif() #endif()
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}") #set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "${PROJECT_AUTHOR}") #set(CPACK_PACKAGE_VENDOR "${PROJECT_AUTHOR}")
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) #set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) #set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) #set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "Documentation") #set(CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "Documentation")
set(CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION "Documentation generated for the library") #set(CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION "Documentation generated for the library")
set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Examples") #set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Examples")
set(CPACK_COMPONENT_EXAMPLES_DESCRIPTION "Sample applications using the library") #set(CPACK_COMPONENT_EXAMPLES_DESCRIPTION "Sample applications using the library")
include(CPack) #include(CPack)

View File

@@ -3,7 +3,7 @@ set(SRC
main.cpp main.cpp
) )
qt5_add_resources(QRC resources.qrc) qt_add_resources(QRC resources.qrc)
add_executable(chatserver ${SRC} ${QRC}) add_executable(chatserver ${SRC} ${QRC})
target_link_libraries(chatserver qhttpengine) target_link_libraries(chatserver qhttpengine)

View File

@@ -42,13 +42,13 @@ endif()
add_library(qhttpengine ${HEADERS} ${SRC}) add_library(qhttpengine ${HEADERS} ${SRC})
set_target_properties(qhttpengine PROPERTIES set_target_properties(qhttpengine PROPERTIES
CXX_STANDARD 11 CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON CXX_STANDARD_REQUIRED ON
DEFINE_SYMBOL QT_NO_SIGNALS_SLOTS_KEYWORDS DEFINE_SYMBOL QT_NO_SIGNALS_SLOTS_KEYWORDS
DEFINE_SYMBOL QHTTPENGINE_LIBRARY DEFINE_SYMBOL QHTTPENGINE_LIBRARY
PUBLIC_HEADER "${HEADERS}" PUBLIC_HEADER "${HEADERS}"
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR} #SOVERSION ${PROJECT_VERSION_MAJOR}
) )
target_include_directories(qhttpengine PUBLIC target_include_directories(qhttpengine PUBLIC
@@ -57,8 +57,20 @@ target_include_directories(qhttpengine PUBLIC
"$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>" "$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>"
) )
target_link_libraries(qhttpengine Qt5::Network) if(BUILD_AGAINST_QT6)
target_link_libraries(qhttpengine Qt${QT_VERSION_MAJOR}::Network Qt6::Core5Compat)
else()
target_link_libraries(qhttpengine Qt${QT_VERSION_MAJOR}::Network)
endif()
if(BUILD_FOR_LABMCT)
set_target_properties(qhttpengine PROPERTIES
INSTALL_RPATH "${LABMCT_RPATH}")
install(FILES $<TARGET_RUNTIME_DLLS:qhttpengine> DESTINATION ./)
install(TARGETS qhttpengine
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
else()
install(TARGETS qhttpengine EXPORT qhttpengine-export install(TARGETS qhttpengine EXPORT qhttpengine-export
RUNTIME DESTINATION "${BIN_INSTALL_DIR}" RUNTIME DESTINATION "${BIN_INSTALL_DIR}"
LIBRARY DESTINATION "${LIB_INSTALL_DIR}" LIBRARY DESTINATION "${LIB_INSTALL_DIR}"
@@ -86,3 +98,4 @@ configure_file(qhttpengine.pc.in "${CMAKE_CURRENT_BINARY_DIR}/qhttpengine.pc" @O
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qhttpengine.pc" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qhttpengine.pc"
DESTINATION "${LIB_INSTALL_DIR}/pkgconfig" DESTINATION "${LIB_INSTALL_DIR}/pkgconfig"
) )
endif()

View File

@@ -61,6 +61,7 @@ public:
* with the new one provided. * with the new one provided.
*/ */
void add(const QString &username, const QString &password); void add(const QString &username, const QString &password);
void remove(const QString &username);
/** /**
* @brief Process the request * @brief Process the request

View File

@@ -24,11 +24,10 @@
#define QHTTPENGINE_HANDLER_H #define QHTTPENGINE_HANDLER_H
#include <QObject> #include <QObject>
#include <QRegularExpression>
#include "qhttpengine_export.h" #include "qhttpengine_export.h"
class QRegExp;
namespace QHttpEngine namespace QHttpEngine
{ {
@@ -49,24 +48,24 @@ class QHTTPENGINE_EXPORT HandlerPrivate;
* match. * match.
* *
* To add a redirect, use the addRedirect() method. The first parameter is a * To add a redirect, use the addRedirect() method. The first parameter is a
* QRegExp pattern that the request path will be tested against. If it * QRegularExpression pattern that the request path will be tested against. If it
* matches, an HTTP 302 redirect will be written to the socket and the request * matches, an HTTP 302 redirect will be written to the socket and the request
* closed. For example, to have the root path "/" redirect to "/index.html": * closed. For example, to have the root path "/" redirect to "/index.html":
* *
* @code * @code
* QHttpEngine::Handler handler; * QHttpEngine::Handler handler;
* handler.addRedirect(QRegExp("^$"), "/index.html"); * handler.addRedirect(QRegularExpression("^$"), "/index.html");
* @endcode * @endcode
* *
* To add a sub-handler, use the addSubHandler() method. Again, the first * To add a sub-handler, use the addSubHandler() method. Again, the first
* parameter is a QRegExp pattern. If the pattern matches, the portion of the * parameter is a QRegularExpression pattern. If the pattern matches, the portion of the
* path that matched the pattern is removed from the path and it is passed to * path that matched the pattern is removed from the path and it is passed to
* the sub-handler's route() method. For example, to have a sub-handler * the sub-handler's route() method. For example, to have a sub-handler
* invoked when the path begins with "/api/": * invoked when the path begins with "/api/":
* *
* @code * @code
* QHttpEngine::Handler handler, subHandler; * QHttpEngine::Handler handler, subHandler;
* handler.addSubHandler(QRegExp("^api/"), &subHandler); * handler.addSubHandler(QRegularExpression("^api/"), &subHandler);
* @endcode * @endcode
* *
* If the request doesn't match any redirect or sub-handler patterns, it is * If the request doesn't match any redirect or sub-handler patterns, it is
@@ -100,7 +99,7 @@ public:
* The destination path may use "%1", "%2", etc. to refer to captured * The destination path may use "%1", "%2", etc. to refer to captured
* parts of the pattern. The client will receive an HTTP 302 redirect. * parts of the pattern. The client will receive an HTTP 302 redirect.
*/ */
void addRedirect(const QRegExp &pattern, const QString &path); void addRedirect(const QRegularExpression &pattern, const QString &path);
/** /**
* @brief Add a handler for a specific pattern * @brief Add a handler for a specific pattern
@@ -109,7 +108,7 @@ public:
* used when the route() method is invoked to determine whether the * used when the route() method is invoked to determine whether the
* request matches any patterns. The order of the list is preserved. * request matches any patterns. The order of the list is preserved.
*/ */
void addSubHandler(const QRegExp &pattern, Handler *handler); void addSubHandler(const QRegularExpression &pattern, Handler *handler);
/** /**
* @brief Route an incoming request * @brief Route an incoming request
@@ -137,4 +136,4 @@ private:
} }
#endif // QHTTPENGINE_HANDLER_H #endif // QHTTPENGINE_HANDLER_H

View File

@@ -25,6 +25,8 @@
#include <qhttpengine/handler.h> #include <qhttpengine/handler.h>
#include <functional>
#include "qhttpengine_export.h" #include "qhttpengine_export.h"
namespace QHttpEngine namespace QHttpEngine
@@ -56,10 +58,7 @@ class QHTTPENGINE_EXPORT QObjectHandlerPrivate;
* *
* QHttpEngine::QObjectHandler handler; * QHttpEngine::QObjectHandler handler;
* Object object; * Object object;
* // Old connection syntax
* handler.registerMethod("something", &object, SLOT(something(QHttpEngine::Socket*))); * handler.registerMethod("something", &object, SLOT(something(QHttpEngine::Socket*)));
* // New connection syntax
* handler.registerMethod("something", &object, &Object::something);
* @endcode * @endcode
* *
* It is also possible to use this class with a functor, eliminating the need * It is also possible to use this class with a functor, eliminating the need
@@ -85,78 +84,39 @@ public:
explicit QObjectHandler(QObject *parent = 0); explicit QObjectHandler(QObject *parent = 0);
/** /**
* @brief Register a method * @brief Register a method using slot macro (Qt5/6 compatible)
*
* This overload uses the traditional connection syntax with macros.
*
* The readAll parameter determines whether all data must be received by
* the socket before invoking the slot.
*/ */
void registerMethod(const QString &name, QObject *receiver, const char *method, bool readAll = true); void registerMethod(const QString &name, QObject *receiver, const char *method, bool readAll = true);
#ifdef DOXYGEN
/** /**
* @brief Register a method * @brief Register a method using member function pointer
*
* This overload uses the new connection syntax with member pointers.
*/ */
void registerMethod(const QString &name, QObject *receiver, PointerToMemberFunction method, bool readAll = true); template <typename Func>
void registerMethod(const QString &name,
/** typename QtPrivate::FunctionPointer<Func>::Object *receiver,
* @brief Register a method Func slot,
* bool readAll = true) {
* This overload uses the new functor syntax (without context). // Wrap the member function call
*/ registerMethodImpl(name, receiver, [receiver, slot](Socket *socket) {
void registerMethod(const QString &name, Functor functor, bool readAll = true); (receiver->*slot)(socket);
}, readAll);
/**
* @brief Register a method
*
* This overload uses the new functor syntax (with context).
*/
void registerMethod(const QString &name, QObject *receiver, Functor functor, bool readAll = true);
#else
template <typename Func1>
inline void registerMethod(const QString &name,
typename QtPrivate::FunctionPointer<Func1>::Object *receiver,
Func1 slot,
bool readAll = true) {
typedef QtPrivate::FunctionPointer<Func1> SlotType;
// Ensure the slot doesn't have too many arguments
Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) == 1,
"The slot must have exactly one argument.");
// Ensure the argument is of the correct type
Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<Socket*, typename QtPrivate::List_Select<typename SlotType::Arguments, 0>::Value>::value),
"The slot parameters do not match");
// Invoke the implementation
registerMethodImpl(name, receiver, new QtPrivate::QSlotObject<Func1, typename SlotType::Arguments, void>(slot), readAll);
} }
template <typename Func1> /**
inline typename QtPrivate::QEnableIf<!QtPrivate::AreArgumentsCompatible<Func1, QObject*>::value, void>::Type * @brief Register a method using functor (Qt6 compatible)
registerMethod(const QString &name, Func1 slot, bool readAll = true) { */
registerMethod(name, Q_NULLPTR, slot, readAll); template <typename Func>
void registerMethod(const QString &name, Func slot, bool readAll = true) {
registerMethodImpl(name, Q_NULLPTR, slot, readAll);
} }
template <typename Func1> /**
inline typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction && * @brief Register a method using functor with context
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) */
!std::is_same<const char*, Func1>::value, template <typename Func>
#else void registerMethod(const QString &name, QObject *context, Func slot, bool readAll = true) {
!QtPrivate::is_same<const char*, Func1>::value, registerMethodImpl(name, context, slot, readAll);
#endif
void>::Type
registerMethod(const QString &name, QObject *context, Func1 slot, bool readAll = true) {
// There is an easier way to do this but then the header wouldn't
// compile on non-C++11 compilers
return registerMethod_functor(name, context, slot, &Func1::operator(), readAll);
} }
#endif
protected: protected:
@@ -167,25 +127,9 @@ protected:
private: private:
template <typename Func1, typename Func1Operator> // Store callbacks using std::function for Qt6 compatibility
inline void registerMethod_functor(const QString &name, QObject *context, Func1 slot, Func1Operator, bool readAll) { void registerMethodImpl(const QString &name, QObject *context,
std::function<void(Socket*)> callback, bool readAll);
typedef QtPrivate::FunctionPointer<Func1Operator> SlotType;
// Ensure the slot doesn't have too many arguments
Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) == 1,
"The slot must have exactly one argument.");
// Ensure the argument is of the correct type
Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<Socket*, typename QtPrivate::List_Select<typename SlotType::Arguments, 0>::Value>::value),
"The slot parameters do not match");
registerMethodImpl(name, context,
new QtPrivate::QFunctorSlotObject<Func1, 1, typename SlotType::Arguments, void>(slot),
readAll);
}
void registerMethodImpl(const QString &name, QObject *receiver, QtPrivate::QSlotObjectBase *slotObj, bool readAll);
QObjectHandlerPrivate *const d; QObjectHandlerPrivate *const d;
friend class QObjectHandlerPrivate; friend class QObjectHandlerPrivate;
@@ -193,4 +137,4 @@ private:
} }
#endif // QHTTPENGINE_QOBJECTHANDLER_H #endif // QHTTPENGINE_QOBJECTHANDLER_H

View File

@@ -135,7 +135,9 @@ public:
/// Diagnostic trace /// Diagnostic trace
TRACE = 1 << 6, TRACE = 1 << 6,
/// Proxy connection /// Proxy connection
CONNECT = 1 << 7 CONNECT = 1 << 7,
/// Store partial resource
PATCH = 1 << 8
}; };
/** /**

View File

@@ -46,6 +46,11 @@ void BasicAuthMiddleware::add(const QString &username, const QString &password)
d->map.insert(username, password); d->map.insert(username, password);
} }
void BasicAuthMiddleware::remove(const QString &username)
{
d->map.remove(username);
}
bool BasicAuthMiddleware::verify(const QString &username, const QString &password) bool BasicAuthMiddleware::verify(const QString &username, const QString &password)
{ {
return d->map.contains(username) && d->map.value(username) == password; return d->map.contains(username) && d->map.value(username) == password;

View File

@@ -45,12 +45,12 @@ void Handler::addMiddleware(Middleware *middleware)
d->middleware.append(middleware); d->middleware.append(middleware);
} }
void Handler::addRedirect(const QRegExp &pattern, const QString &path) void Handler::addRedirect(const QRegularExpression &pattern, const QString &path)
{ {
d->redirects.append(Redirect(pattern, path)); d->redirects.append(Redirect(pattern, path));
} }
void Handler::addSubHandler(const QRegExp &pattern, Handler *handler) void Handler::addSubHandler(const QRegularExpression &pattern, Handler *handler)
{ {
d->subHandlers.append(SubHandler(pattern, handler)); d->subHandlers.append(SubHandler(pattern, handler));
} }
@@ -58,18 +58,20 @@ void Handler::addSubHandler(const QRegExp &pattern, Handler *handler)
void Handler::route(Socket *socket, const QString &path) void Handler::route(Socket *socket, const QString &path)
{ {
// Run through each of the middleware // Run through each of the middleware
foreach (Middleware *middleware, d->middleware) { for (Middleware *middleware : d->middleware) {
if (!middleware->process(socket)) { if (!middleware->process(socket)) {
return; return;
} }
} }
// Check each of the redirects for a match // Check each of the redirects for a match
foreach (Redirect redirect, d->redirects) { for (Redirect &redirect : d->redirects) {
if (redirect.first.indexIn(path) != -1) { QRegularExpressionMatch match = redirect.first.match(path);
if (match.hasMatch()) {
QString newPath = redirect.second; QString newPath = redirect.second;
foreach (QString replacement, redirect.first.capturedTexts().mid(1)) { QStringList captured = match.capturedTexts();
newPath = newPath.arg(replacement); for (int i = 1; i < captured.size(); ++i) {
newPath = newPath.arg(captured.at(i));
} }
socket->writeRedirect(newPath.toUtf8()); socket->writeRedirect(newPath.toUtf8());
return; return;
@@ -77,9 +79,10 @@ void Handler::route(Socket *socket, const QString &path)
} }
// Check each of the sub-handlers for a match // Check each of the sub-handlers for a match
foreach (SubHandler subHandler, d->subHandlers) { for (SubHandler &subHandler : d->subHandlers) {
if (subHandler.first.indexIn(path) != -1) { QRegularExpressionMatch match = subHandler.first.match(path);
subHandler.second->route(socket, path.mid(subHandler.first.matchedLength())); if (match.hasMatch()) {
subHandler.second->route(socket, path.mid(match.capturedLength()));
return; return;
} }
} }
@@ -92,4 +95,4 @@ void Handler::process(Socket *socket, const QString &)
{ {
// The default response is simply a 404 error // The default response is simply a 404 error
socket->writeError(Socket::NotFound); socket->writeError(Socket::NotFound);
} }

View File

@@ -26,15 +26,15 @@
#include <QList> #include <QList>
#include <QObject> #include <QObject>
#include <QPair> #include <QPair>
#include <QRegExp> #include <QRegularExpression>
#include <qhttpengine/handler.h> #include <qhttpengine/handler.h>
namespace QHttpEngine namespace QHttpEngine
{ {
typedef QPair<QRegExp, QString> Redirect; typedef QPair<QRegularExpression, QString> Redirect;
typedef QPair<QRegExp, Handler*> SubHandler; typedef QPair<QRegularExpression, Handler*> SubHandler;
class HandlerPrivate : public QObject class HandlerPrivate : public QObject
{ {

View File

@@ -125,6 +125,8 @@ bool Parser::parseRequestHeaders(const QByteArray &data, Socket::Method &method,
method = Socket::TRACE; method = Socket::TRACE;
} else if (parts[0] == "CONNECT") { } else if (parts[0] == "CONNECT") {
method = Socket::CONNECT; method = Socket::CONNECT;
} else if (parts[0] == "PATCH") {
method = Socket::PATCH;
} else { } else {
return false; return false;
} }

View File

@@ -38,13 +38,12 @@ ProxySocket::ProxySocket(Socket *socket, const QString &path, const QHostAddress
connect(&mUpstreamSocket, &QTcpSocket::connected, this, &ProxySocket::onUpstreamConnected); connect(&mUpstreamSocket, &QTcpSocket::connected, this, &ProxySocket::onUpstreamConnected);
connect(&mUpstreamSocket, &QTcpSocket::readyRead, this, &ProxySocket::onUpstreamReadyRead); connect(&mUpstreamSocket, &QTcpSocket::readyRead, this, &ProxySocket::onUpstreamReadyRead);
connect( #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
&mUpstreamSocket, connect(&mUpstreamSocket, &QAbstractSocket::error,this, &ProxySocket::onUpstreamError);
static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), #else
this, connect(&mUpstreamSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
&ProxySocket::onUpstreamError this, &ProxySocket::onUpstreamError);
); #endif
mUpstreamSocket.connectToHost(address, port); mUpstreamSocket.connectToHost(address, port);
} }
@@ -135,7 +134,7 @@ void ProxySocket::onUpstreamReadyRead()
} }
} }
void ProxySocket::onUpstreamError(QAbstractSocket::SocketError socketError) void ProxySocket::onUpstreamError()
{ {
if (mHeadersParsed) { if (mHeadersParsed) {
mDownstreamSocket->close(); mDownstreamSocket->close();

View File

@@ -51,7 +51,7 @@ private Q_SLOTS:
void onUpstreamConnected(); void onUpstreamConnected();
void onUpstreamReadyRead(); void onUpstreamReadyRead();
void onUpstreamError(QTcpSocket::SocketError socketError); void onUpstreamError();
private: private:

View File

@@ -48,7 +48,7 @@ void QObjectHandlerPrivate::invokeSlot(Socket *socket, Method m)
if (m.oldSlot) { if (m.oldSlot) {
// Obtain the slot index // Obtain the slot index
int index = m.receiver->metaObject()->indexOfSlot(m.slot.method + 1); int index = m.receiver->metaObject()->indexOfMethod(m.slotMethod + 1);
if (index == -1) { if (index == -1) {
socket->writeError(Socket::InternalServerError); socket->writeError(Socket::InternalServerError);
return; return;
@@ -64,17 +64,17 @@ void QObjectHandlerPrivate::invokeSlot(Socket *socket, Method m)
} }
// Invoke the method // Invoke the method
if (!m.receiver->metaObject()->method(index).invoke( if (!method.invoke(m.receiver, Q_ARG(Socket*, socket))) {
m.receiver, Q_ARG(Socket*, socket))) {
socket->writeError(Socket::InternalServerError); socket->writeError(Socket::InternalServerError);
return; return;
} }
} else { } else {
void *args[] = { // Call the std::function callback
Q_NULLPTR, if (m.callback) {
&socket m.callback(socket);
}; } else {
m.slot.slotObj->call(m.receiver, args); socket->writeError(Socket::InternalServerError);
}
} }
} }
@@ -104,7 +104,8 @@ void QObjectHandler::registerMethod(const QString &name, QObject *receiver, cons
d->map.insert(name, QObjectHandlerPrivate::Method(receiver, method, readAll)); d->map.insert(name, QObjectHandlerPrivate::Method(receiver, method, readAll));
} }
void QObjectHandler::registerMethodImpl(const QString &name, QObject *receiver, QtPrivate::QSlotObjectBase *slotObj, bool readAll) void QObjectHandler::registerMethodImpl(const QString &name, QObject *context,
std::function<void(Socket*)> callback, bool readAll)
{ {
d->map.insert(name, QObjectHandlerPrivate::Method(receiver, slotObj, readAll)); d->map.insert(name, QObjectHandlerPrivate::Method(callback, readAll));
} }

View File

@@ -25,6 +25,7 @@
#include <QMap> #include <QMap>
#include <QObject> #include <QObject>
#include <functional>
namespace QHttpEngine namespace QHttpEngine
{ {
@@ -47,23 +48,18 @@ public:
public: public:
Method() {} Method() {}
Method(QObject *receiver, const char *method, bool readAll) Method(QObject *receiver, const char *method, bool readAll)
: receiver(receiver), oldSlot(true), slot(method), readAll(readAll) {} : receiver(receiver), oldSlot(true), slotMethod(method), readAll(readAll) {}
Method(QObject *receiver, QtPrivate::QSlotObjectBase *slotObj, bool readAll) Method(std::function<void(Socket*)> callback, bool readAll)
: receiver(receiver), oldSlot(false), slot(slotObj), readAll(readAll) {} : receiver(nullptr), oldSlot(false), callback(callback), readAll(readAll) {}
QObject *receiver; QObject *receiver = nullptr;
bool oldSlot; bool oldSlot;
union slot{ const char *slotMethod = nullptr;
slot() {} std::function<void(Socket*)> callback;
slot(const char *method) : method(method) {}
slot(QtPrivate::QSlotObjectBase *slotObj) : slotObj(slotObj) {}
const char *method;
QtPrivate::QSlotObjectBase *slotObj;
} slot;
bool readAll; bool readAll;
}; };
void invokeSlot(Socket*socket, Method m); void invokeSlot(Socket *socket, Method m);
QMap<QString, Method> map; QMap<QString, Method> map;
@@ -74,4 +70,4 @@ private:
} }
#endif // QHTTPENGINE_QOBJECTHANDLER_P_H #endif // QHTTPENGINE_QOBJECTHANDLER_P_H

View File

@@ -20,7 +20,7 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
#include <QRegExp> #include <QRegularExpression>
#include <qhttpengine/range.h> #include <qhttpengine/range.h>
@@ -44,13 +44,14 @@ Range::Range()
Range::Range(const QString &range, qint64 dataSize) Range::Range(const QString &range, qint64 dataSize)
: d(new RangePrivate(this)) : d(new RangePrivate(this))
{ {
QRegExp regExp("^(\\d*)-(\\d*)$"); QRegularExpression regExp("^(\\d*)-(\\d*)$");
int from = 0, to = -1; int from = 0, to = -1;
if (regExp.indexIn(range.trimmed()) != -1) { QRegularExpressionMatch match = regExp.match(range.trimmed());
QString fromStr = regExp.cap(1); if (match.hasMatch()) {
QString toStr = regExp.cap(2); QString fromStr = match.captured(1);
QString toStr = match.captured(2);
// If both strings are empty - range is invalid. Setting to out of // If both strings are empty - range is invalid. Setting to out of
// bounds range and returning. // bounds range and returning.
@@ -281,4 +282,4 @@ QString Range::contentRange() const
} }
return QString("%1-%2/%3").arg(fromStr, toStr, sizeStr); return QString("%1-%2/%3").arg(fromStr, toStr, sizeStr);
} }

View File

@@ -91,8 +91,12 @@ void Server::incomingConnection(qintptr socketDescriptor)
}); });
// If an error occurs, delete the socket // If an error occurs, delete the socket
connect(socket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
socket, &QSslSocket::deleteLater); connect(socket, &QAbstractSocket::error, socket, &QSslSocket::deleteLater);
#else
connect(socket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
socket, &QSslSocket::deleteLater);
#endif
socket->setSocketDescriptor(socketDescriptor); socket->setSocketDescriptor(socketDescriptor);
socket->setSslConfiguration(d->configuration); socket->setSslConfiguration(d->configuration);