Remove all JSON marshalling code from QObjectHandler.

This commit is contained in:
Nathan Osman
2016-10-13 00:38:39 -07:00
parent e8b076bdc4
commit c1fc8a115d
5 changed files with 107 additions and 235 deletions

View File

@@ -21,9 +21,6 @@
*/
#include <QGenericArgument>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMetaMethod>
#include <QHttpEngine/QObjectHandler>
@@ -36,75 +33,6 @@ QObjectHandlerPrivate::QObjectHandlerPrivate(QObjectHandler *handler)
{
}
void QObjectHandlerPrivate::invokeSlot(QHttpSocket *socket, const QString &path)
{
Method m = map.value(path);
QVariantMap parameters;
// If data was supplied, decode it as JSON
if (socket->bytesAvailable()) {
QJsonParseError error;
QJsonDocument document = QJsonDocument::fromJson(socket->readAll(), &error);
// Ensure that the document is valid
if (error.error != QJsonParseError::NoError) {
socket->writeError(QHttpSocket::BadRequest);
return;
}
parameters = document.object().toVariantMap();
}
QVariantMap retVal;
// Invoke the slot
if (m.oldSlot) {
// Obtain the slot index
int index = m.receiver->metaObject()->indexOfSlot(m.slot.method + 1);
if (index == -1) {
socket->writeError(QHttpSocket::InternalServerError);
return;
}
QMetaMethod method = m.receiver->metaObject()->method(index);
// Ensure the parameters are correct
QList<QByteArray> params = method.parameterTypes();
if (params.count() > 0 && params.at(0) != "QHttpSocket*" ||
params.count() > 1 && params.at(1) != "QVariantMap" ||
params.count() > 2 ||
method.returnType() != QMetaType::QVariantMap) {
socket->writeError(QHttpSocket::InternalServerError);
return;
}
// Invoke the method
if (!m.receiver->metaObject()->method(index).invoke(
m.receiver,
Q_RETURN_ARG(QVariantMap, retVal),
Q_ARG(QHttpSocket*, socket),
Q_ARG(QVariantMap, parameters))) {
socket->writeError(QHttpSocket::InternalServerError);
return;
}
} else {
void *args[3] = {
&retVal,
&socket,
&parameters
};
m.slot.slotObj->call(m.receiver, args);
}
// Convert the return value to JSON and write it to the socket
QByteArray data = QJsonDocument(QJsonObject::fromVariantMap(retVal)).toJson();
socket->setHeader("Content-Length", QByteArray::number(data.length()));
socket->setHeader("Content-Type", "application/json");
socket->write(data);
socket->close();
}
QObjectHandler::QObjectHandler(QObject *parent)
: QHttpHandler(parent),
d(new QObjectHandlerPrivate(this))
@@ -119,31 +47,48 @@ void QObjectHandler::process(QHttpSocket *socket, const QString &path)
return;
}
// Ensure the method is accepted
QObjectHandlerPrivate::Method m = d->map.value(path);
if (!(m.acceptedMethods & socket->method())) {
// TODO: accept header
socket->writeError(QHttpSocket::MethodNotAllowed);
return;
}
// If the slot has finished receiving all of the data, jump directly to
// invokeSlot(), otherwise, wait until we have the rest of it
if (socket->bytesAvailable() >= socket->contentLength()) {
d->invokeSlot(socket, path);
// Invoke the slot
if (m.oldSlot) {
// Obtain the slot index
int index = m.receiver->metaObject()->indexOfSlot(m.slot.method + 1);
if (index == -1) {
socket->writeError(QHttpSocket::InternalServerError);
return;
}
QMetaMethod method = m.receiver->metaObject()->method(index);
// Ensure the parameter is correct
QList<QByteArray> params = method.parameterTypes();
if (params.count() != 1 || params.at(0) != "QHttpSocket*") {
socket->writeError(QHttpSocket::InternalServerError);
return;
}
// Invoke the method
if (!m.receiver->metaObject()->method(index).invoke(
m.receiver, Q_ARG(QHttpSocket*, socket))) {
socket->writeError(QHttpSocket::InternalServerError);
return;
}
} else {
connect(socket, &QHttpSocket::readChannelFinished, [this, socket, path]() {
d->invokeSlot(socket, path);
});
void *args[] = {
Q_NULLPTR,
&socket
};
m.slot.slotObj->call(m.receiver, args);
}
}
void QObjectHandler::registerMethod(const QString &name, QObject *receiver, const char *method, int acceptedStatusCodes)
void QObjectHandler::registerMethod(const QString &name, QObject *receiver, const char *method)
{
d->map.insert(name, QObjectHandlerPrivate::Method(receiver, method, acceptedStatusCodes));
d->map.insert(name, QObjectHandlerPrivate::Method(receiver, method));
}
void QObjectHandler::registerMethodImpl(const QString &name, QObject *receiver, QtPrivate::QSlotObjectBase *slotObj, int acceptedStatusCodes)
void QObjectHandler::registerMethodImpl(const QString &name, QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
{
d->map.insert(name, QObjectHandlerPrivate::Method(receiver, slotObj, acceptedStatusCodes));
d->map.insert(name, QObjectHandlerPrivate::Method(receiver, slotObj));
}