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:
- Repositorio principal: https://github.com/qt-labs/qthttpserver
- Dependencia externa http-parser: https://github.com/nodejs/http-parser
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.