Qt httpserver 理解与使用

news/2024/7/4 9:41:28

目录

概述

核心概念-路由

多线程处理

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   参数类型正确,执行回调函数   

 

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

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

如:

server.route( "/blog/<arg>/<arg>" , [] ( int year, int month) {  // seconnd <arg> 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/<arg>/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()

 

listen()

 


http://www.niftyadmin.cn/n/3296586.html

相关文章

elasticsearch性能测试工具rally深入详解

elasticsearch性能测试研究了很久&#xff0c;自己想过通过批量导入数据&#xff0c;然后记录时间&#xff0c;统计CPU、内存等变化&#xff0c;计算得出某个性能指标。但显然&#xff0c;数据量起伏不定&#xff0c;非常不准确。 研究发现&#xff0c;github上提供了rally作为…

表面粗糙度的基本评定参数是_表面粗糙度知识大合集,讲得明明白白

以上3门视频系列课全面上线&#xff0c;由GD&T实战专家夏忠定老师讲解&#xff0c;线下每门课几千元&#xff0c;线上价格更实惠&#xff0c;而且可以重复播放观看。扫描去千聊平台获取免费试听内容&#xff0c;更多课程内容请扫描咨询工作人员1&#xff0e; 什么称为表面粗…

一个与或非感知机

分享个python实例&#xff0c;自己写的一个感知机&#xff0c;仅供学习&#xff0c;自行调整参数&#xff0c;修改代码&#xff01; 效果图&#xff1a; 代码分享&#xff1a; import numpy as np import matplotlib.pyplot as pltclass Perceptron(object):""&q…

spring 和 springmvc 的父子容器关系浅析

以###问题### 在工程项目中&#xff0c;一开始将所有的附件路径定义在工具类中。使用 static String 的形式&#xff1b;于是就在项目的开发过程中产生不便&#xff0c;也使得配置属性不灵活&#xff0c;不利于模块化的管理信息和提高项目的可扩展性以及维护性。因此就将项目的…

Struts2 Get传值乱码过滤器

问题的原因在于get传值的时候&#xff0c;getParameter方法使用的是ISO8859-1编码&#xff0c;。修改一下此方法 &#xff08;1&#xff09;java类1&#xff1a;EncodeRequestWrapper.java public class EncodeRequestWrapper extends HttpServletRequestWrapper { private Ht…

拖拽drag_html5的拖放(drag和drop)

<p>请把 W3School 的图片拖放到矩形中&#xff1a;</p><div id"div1" ondrop"drop(event)" ondragover"allowDrop(event)"></div> <br /> <img id"drag1" src"/i/eg_dragdrop_w3school.gif&quo…

Groovy创始人James Strachan博客称:Java面临终结Scala将来可能替代javac

Groovy创始人James Strachan前日在其博客上发表了一篇文章&#xff0c;题目为《Scala将取代Java /javac&#xff1f;》。以下是正文部分的翻译&#xff1a;不要误解我的意思——我在过去的这十来年里写了无数的Java代码&#xff0c;并且坚信它相对C和Smalltalk来说是一个巨大的…

Android发送信息模拟系统

Android系统中已经有了我们熟悉并常用的发送信息功能&#xff0c;在程序中叫做已经有了此Activity&#xff0c;那么有时候我们需要在编写Android程序时调用此应用程序以实现通过我们的程序发送信息。具体实现方式如下&#xff1a; 1. 建立xml布局文件&#xff0c;最终效果如下&…