Qt httpserver 理解与使用

目录

概述

核心概念-路由

多线程处理

Qt Https Server


概述

Qt提供了创建简单web服务器的拓展模块,即qthttpserver

关于该模块的一些信息:

Introducing the Qt Http Server

QtHttpServer routing API

 

该模块的代码位于Qt官方的代码仓库中,但是目前还为正式加入到Qt发行版中,预计Qt6版本会加入该模块。

Qt Project Git Repository Browser

可以看到,存在两个基本相同的代码

qt-extensions/qthttpserver.git - Qt Extension: Qt HTTP Server

qt-labs/qthttpserver.git - Qt HTTP Server

一个归属于Qt扩展模块中,一个归属于Qt实验模块中,尚不清楚具体用意!

 

核心概念-路由

Qt http server借鉴了现代大多数流行web服务器的概念,最为典型的是Flask。

使用路由技巧,可以方便地处理一个url的请求。一个路由就是一个特定的URL对应的特定规则,也就是执行特定的回调函数!

静态路由:就是将一个固定的URL路径绑定到一个回调函数

一个例子:

QHttpServer server;

server.route("/blog/", []() {

      return "blogs";

});

而且,URL路径是严格的,客户端必须按照规定格式去请求才能得到响应。

如:客户请求:127.0.0.1:12345/blog/   能得到响应消息,"blogs"

而请求:127.0.0.1:12345/blog  将拒绝服务。

 

动态路由就是URL中含有参数,可以动态捕获参数,并将参数转换到程序中需要的类型

如:

server.route( "/blog/" , [] (int year) {

      return blogs_by_year(year);

});

Qt http server对带参数的路由规则做了一些改进。URL中不需要像其他框架那样,明确指明参数类型和参数名,因为在C++中不能将捕获的参数绑定到回调参数中,而且也无法对路径格式类型和回调参数进行编译时检查。我们可以使用静态类型。这样我们就可以将编译器用作为“控制器”,确保我们得到的类型是我们支持的类型。

这样客户端请求时只管传入参数(必须得传入参数),如果类型匹配会自动转换得到参数,否则会转换失败,不执行回调函数,拒绝服务。

   如:客户请求:127.0.0.1:12345/blog/   未传入参数,不执行回调函数,无法服务

请求:127.0.0.1:12345/blog/20.21  参数类型有误,不执行回调函数,无法服务

请求:127.0.0.1:12345/blog/2021   参数类型正确,执行回调函数   

 

对于含有多个参数或明确指明参数的情况:

需要使用关键字。它的工作原理与QString::arg()类似,但不支持排序。

如:

server.route( "/blog//" , [] ( int year, int month) {  // seconnd  is not neccesary

     return blogs_by_year_and_month(year, month);

    // return QString("query blogs written in %1, %2").arg(year).arg(month);

});

server.route( "/blog//detail" , [] (int year) {

      return blogs_by_year(year);

});

 

另外,还支持创建REST API。为此,我们需要拆分GET/POST/PUT/DELETE请求。

如:

server.route( "/blog/" , QHttpServerRequest::Method::GET, [] ( int year) {

     return blogs_by_year(year);

});

这样的话,客户端向该URL发起请求,但是使用POST方法的话,是无法得到响应的。

 

如果希望自定义HTTP响应的头,则可以使用底层API,QHttpServerResponder。

如:

server.route( "/blog/" , [] ( int year, QHttpServerResponder &&responder) {

    responder.write(blogs_by_year(year), "text/plain" );

});

备注:QHttpServerResponder和QHttpServerRequest是特殊参数,只能用作回调函数的最后一个参数。

多线程处理

最后,提供一个使用多线程处理请求的例子以供参考。这里使用了Qt Concurrent命名空间里的多线程,这是一种高级多线程API,详见 Qt的四种多线程讲解。

server.route("/submitReport", QHttpServerRequest::Method::POST, [this](const QHttpServerRequest &request) -> QHttpServerFutureResponse {
    auto future = QtConcurrent::run(this, &MyServer::onSubmit, request.body());
    return future;
});

QHttpServerResponse MyServer::onSubmit(const QByteArray &request)
{
    return QHttpServerResponse(Database::updateSubmit(request));
}

Qt Https Server

Qt http server还支持创建https server,只需要在listen()之前调用sslSetup()进行QSslSocket设置即可。

需要提前使用openssl生成证书和密钥。

一般使用方法如下:

QHttpServer httpsServer;

    QSslConfiguration sslConfiguration;

    QFile certFile(QStringLiteral(":/cert/localhost.cert"));

    QFile keyFile(QStringLiteral(":/cert/localhost.key"));

    certFile.open(QIODevice::ReadOnly);

    keyFile.open(QIODevice::ReadOnly);

    QSslCertificate certificate(&certFile, QSsl::Pem);

    QSslKey sslKey(&keyFile, QSsl::Rsa, QSsl::Pem);

    certFile.close();

    keyFile.close();

    sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);

    //sslConfiguration.setProtocol(QSsl::TlsV1_0);

    sslConfiguration.setLocalCertificate(certificate);

    sslConfiguration.setPrivateKey(sslKey);

httpsServer.sslSetup();

httpsServer.listen(QHostAddress::Any, 6666);

 

通过查看源码,即可明白缘由。

sslSetup()

Qt httpserver 理解与使用_第1张图片

 

listen()

Qt httpserver 理解与使用_第2张图片

 

你可能感兴趣的:(自学Qt系列,http,https,qt5)