Implementación de servidor HTTP con QtHttpServer

Introducción

QtHttpServer es un módulo que permite crear servidores HTTP utilizando el framework Qt. Una característica destacable es su capacidad de integrarse con bibliotecas JavaScript como socket.io para implementar mecanismos de polling o conmutación automática entre WebSocket y HTTP. De esta manera, mediante acceso HTTP convencional se puede establecer una comunicación bidireccional utilizando WebSocket.

El autor de este artículo tuvo la necesidad de migrar un proyecto H5+Node.js debido a que los archivos compilados para una placa ARM64 dependían de librerías de terceros que no podían compilarse correctamente. Optó por implementar el backend utilizando Qt, con el cual tenía mayor familiaridad.

Obtención del código fuente

El código fuente de QtHttpServer está disponible en el repositorio oficial de Qt Labs:

La dependencia externa http-parser debe colocarse en la ubicación especificada dentro del proyecto.

Compilación del proyecto

Configuración del entorno

Se recomienda uitlizar Qt Creator junto con el compilador MSVC 2015 de 64 bits para construir el proyecto.

Resolución de errores de compilación

Archivos de cabecera no encontrados

Al intentar compilar, es posible encontrar errores relacionados con archivos de cabecera privados como qsslserver y qsslserver_p.h. Estos archivos se encuentran en rutas relativas dentro del proyecto. La solución consiste en modificar las rutas de inclusión para que apunten correctamente a la ubicación de dichos archivos.

Cualquier error del tipo "No such file or directory" relacionado con archivos de cabecera privados puede resolverse de manera similar.

Error de inclusión de QtSslServer

Puede aparecer el siguiente error durante la compilación:

..\..\include\QtHttpServer\QtHttpServerDepends(6): fatal error C1083: 
no se puede abrir el archivo de inclusión "QtSslServer/QtSslServer"

Para resolverlo, es necesario verificar la estrutura de directorios en include/QtHttpServer y ajustar las rutas de inclusión. Se debe modificar progresivamente todas las directivas <QtHttpServer/xxxx.h> por inclusiones locales "xxxx.h".

Es recomendable resolver los errores de cabecera de uno en uno y recompilar después de cada corrección para identificar problemas adicionales.

Errores con QLatin1Char

Este error puede aparecer en versiones de Qt anteriores a la 5.12.

Compatibilidad con Qt 5.12 y versiones anteriores

Error: "compare" no es miembro de "QByteArray"

En versiones anteriores a Qt 5.12, el método compare no está disponible para QByteArray. El código original utiliza:

if (i->lastHeader.compare(QByteArrayLiteral("host"), Qt::CaseInsensitive) == 0)
    parseUrl(at, length, true, &i->url);

Se puede adaptar para mantener compatibilidad:

int HttpTransactionPrivate::procesarCabecera(http_parser *parser, const char *dato, size_t longitud)
{
    qCDebug(logHttp) << parser << QString::fromUtf8(dato, int(longitud));
    auto instancia = obtenerInstancia(parser);
    instancia->estado = Estado::EncabezadosRecibidos;
    Q_ASSERT(!instancia->ultimaCabecera.isEmpty());
    
    const auto valor = QByteArray(dato, int(longitud));
    instanc_instancia->encabezados[instancia->obtenerHashCabecera(instancia->ultimaCabecera)] = qMakePair(instancia->ultimaCabecera, valor);
    
#if QT_VERSION >= QT_VERSION_CHECK(5,12,0)
    if (instancia->ultimaCabecera.compare(QByteArrayLiteral("host"), Qt::CaseInsensitive) == 0)
        procesarUrl(dato, longitud, true, &instancia->url);
#else
    if(instancia->ultimaCabecera.contains(QByteArrayLiteral("host"))){
        procesarUrl(dato, longitud, true, &instancia->url);
    }
#endif

#if defined(QT_DEBUG)
    instancia->ultimaCabecera.clear();
#endif
    return 0;
}

Error: "isEmpty" no es miembro de "QLatin1String"

Este error surge al utilizar iteradores con tipos QLatin1String en versiones anteriores a Qt 5.12. La solución consiste en comprobar el tamaño mediante el método size() en lugar de isEmpty():

// Cambiar de:
if (it->isEmpty())
    continue;

// Por:
if(!it->size())
    continue;

Error: "xxx" no es miembro de "QFlags"

Este tipo de error relacionados con enumeraciones no definidas correctamente puede resolverse añadiendo las definiciones de flags correspondientes o actualizando a Qt 5.12 o superior.

Utilisation du module

QtHttpServer proporciona una API de enrutamiento flexible que permite gestionar diferentes rutas y métodos HTTP. La documentación oficial sobre la API de enrutamiento está disponible en el blog de Qt.

Ejemplo práctico

Se puede descargar un ejemplo funcional que ha sido probado con Qt 5.12.12 combinado con VS2017 y también con MinGW. El ejecutable se encuentra disponible en el directorio /bin/release/mingw_x64/.

Alternativas

Existen otras implementaciones de servidores HTTP escritas en Qt que pueden considerarse como alternativas, como JQHttpServer, disponible en GitHub.

Etiquetas: Qt qthttpserver http-server C++ WebSocket

Publicado el 7-9 22:28