Exemplo n.º 1
0
/*! \class TorcHTTPService
 *
 * \todo Support for complex parameter types via RPC (e.g. array etc).
 * \todo ProcessRequest implicitly assumes JSON-RPC (though applies to much of the RPC code).
*/
TorcHTTPService::TorcHTTPService(QObject *Parent, const QString &Signature, const QString &Name,
                                 const QMetaObject &MetaObject, const QString &Blacklist)
  : TorcHTTPHandler(SERVICES_DIRECTORY + Signature, Name),
    m_parent(Parent),
    m_version("Unknown"),
    m_metaObject(MetaObject),
    m_subscriberLock(new QMutex(QMutex::Recursive))
{
    QStringList blacklist = Blacklist.split(",");

    m_parent->setObjectName(Name);

    // the parent MUST implement SubscriberDeleted.
    if (MetaObject.indexOfSlot(QMetaObject::normalizedSignature("SubscriberDeleted(QObject*)")) < 0)
    {
        LOG(VB_GENERAL, LOG_ERR, QString("Service '%1' disabled - no SubscriberDeleted slot").arg(Name));
        return;
    }

    // determine version
    int index = MetaObject.indexOfClassInfo("Version");
    if (index > -1)
        m_version = MetaObject.classInfo(index).value();
    else
        LOG(VB_GENERAL, LOG_WARNING, QString("Service '%1' is missing version information").arg(Name));

    // analyse available methods
    for (int i = 0; i < m_metaObject.methodCount(); ++i)
    {
        QMetaMethod method = m_metaObject.method(i);

        if ((method.methodType() == QMetaMethod::Slot) &&
            (method.access()     == QMetaMethod::Public))
        {
            QString name(method.methodSignature());
            name = name.section('(', 0, 0);

            // discard unwanted slots
            if (name == "deleteLater" || name == "SubscriberDeleted" || blacklist.contains(name))
                continue;

            // any Q_CLASSINFO for this method?
            // current 'schema' allows specification of allowed HTTP methods (PUT, GET etc)
            // and custom return types, which are used to improve the usability of maps and
            // lists when returned via XML, JSON, PLIST etc
            QString returntype;
            int customallowed = HTTPUnknownType;

            int index = m_metaObject.indexOfClassInfo(name.toLatin1());
            if (index > -1)
            {
                QStringList infos = QString(m_metaObject.classInfo(index).value()).split(",", QString::SkipEmptyParts);
                foreach (QString info, infos)
                {
                    if (info.startsWith("methods="))
                        customallowed = TorcHTTPRequest::StringToAllowed(info.mid(8));
                    else if (info.startsWith("type="))
                        returntype = info.mid(5);
                }
            }

            // determine allowed request types
            int allowed = HTTPOptions;
            if (customallowed != HTTPUnknownType)
            {
                allowed |= customallowed;
            }
            else if (name.startsWith("Get", Qt::CaseInsensitive))
            {
                allowed += HTTPGet | HTTPHead;
            }
            else if (name.startsWith("Set", Qt::CaseInsensitive))
            {
                // TODO Put or Post?? How to handle head requests for setters...
                allowed += HTTPPut;
            }
            else
            {
                LOG(VB_GENERAL, LOG_ERR, QString("Unable to determine request types of method '%1' for '%2' - ignoring").arg(name).arg(m_name));
                continue;
            }

            MethodParameters *parameters = new MethodParameters(i, method, allowed, returntype);

            if (parameters->m_valid)
                m_methods.insert(name, parameters);
            else
                delete parameters;
        }