QHttpServer Class
QHttpServer 是QAbstractHttpServer 和QHttpServerRouter 的简化 API。更多内容...
| 标题: | #include <QHttpServer> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS HttpServer) target_link_libraries(mytarget PRIVATE Qt6::HttpServer) |
| qmake: | QT += httpserver |
| 自: | Qt 6.4 |
| 继承自: | QAbstractHttpServer |
公共函数
| QHttpServer(QObject *parent = nullptr) | |
| virtual | ~QHttpServer() override |
| void | addAfterRequestHandler(const QObject *context, Functor &&slot) |
| void | clearMissingHandler() |
| Rule * | route(const QString &pathPattern, QHttpServerRequest::Methods method, const QObject *context, Functor &&slot) |
| Rule * | route(const QString &pathPattern, Functor &&handler) |
| Rule * | route(const QString &pathPattern, QHttpServerRequest::Methods method, Functor &&handler) |
| Rule * | route(const QString &pathPattern, const QObject *context, Functor &&slot) |
| QHttpServerRouter * | router() |
| const QHttpServerRouter * | router() const |
| void | setMissingHandler(const QObject *context, Functor &&slot) |
详细说明
QHttpServer 用于通过注册一系列请求处理程序来创建一个简单的 HTTP 服务器。
可通过route 函数便捷地向服务器的QHttpServerRouter 添加规则。若要注册在每次请求后被调用以进一步处理响应的处理程序,请使用addAfterRequestHandler ,但此机制仅适用于返回QHttpServerResponse 或QFuture<QHttpServerResponse>的路由。若要为所有未处理的请求注册处理程序,请使用setMissingHandler 。
最简单的示例:
QHttpServer server;
server.route("/", []() {
return "hello world";
});
autotcpserver= newQTcpServer();
if(!tcpserver->listen()|| !server.bind(tcpserver)) {
deletetcpserver;
return-1;
}
qDebug() << "Listening on port" << tcpserver->serverPort();成员函数文档
[explicit] QHttpServer::QHttpServer(QObject *parent = nullptr)
创建一个 QHttpServer 实例,其父类为parent 。
[override virtual noexcept] QHttpServer::~QHttpServer()
销毁一个QHttpServer 。
template <typename Functor> void QHttpServer::addAfterRequestHandler(const QObject *context, Functor &&slot)
注册一个context 和slot ,以便在处理完每个请求后被调用。
slot 必须实现void (*)(const QHttpServerRequest &, QHttpServerResponse &) 的接口。
slot 也可以是函数指针、不可变的 lambda 表达式,或任何其他具有 const call 运算符的可复制可调用对象。在这种情况下,context 将是一个上下文对象,且该处理程序将在上下文对象被销毁之前保持有效。
示例:
server.addAfterRequestHandler(&server, [] (const QHttpServerRequest &req, QHttpServerResponse &resp) {
auto h = resp.headers();
h.append(QHttpHeaders::WellKnownHeader::Cookie, "PollyWants=Cracker");
resp.setHeaders(std::move(h));
}注意:这些 处理程序仅会在由返回QHttpServerResponse 或QFuture<QHttpServerResponse> 的路由处理程序处理的请求中被调用。
void QHttpServer::clearMissingHandler()
将处理程序重置为默认处理程序,该处理程序会返回状态码为404 Not Found 的响应。
另请参阅 setMissingHandler 。
template <typename Rule = QHttpServerRouterRule, typename Functor> Rule *QHttpServer::route(const QString &pathPattern, QHttpServerRequest::Methods method, const QObject *context, Functor &&slot)
此方法将一个新的路由Rule 添加到服务器的QHttpServerRouter 成员中。Rule 模板参数可以是任何从QHttpServerRouterRule 派生的类。参数将传递给Rule 。服务器会根据 URL 路径和 HTTP 方法,将传入的 HTTP 请求与已注册的规则进行匹配,并执行同时满足这两个条件的第一个匹配规则。
pathPattern 参数将与传入请求URL的path()进行比对。method 参数将与传入请求的HTTP方法进行比对。slot 参数即为请求处理程序。它可以是context 类的成员函数指针、函数指针、不可变lambda表达式,或任何带有const调用运算符的可复制可调用对象。若提供了context ,则只要context存在,该规则即保持有效。context 必须与QHttpServer 具有相同的线程亲和性。
该slot 接受任意数量的已解析参数作为参数,这些参数是从pathPattern 中通过匹配"<arg>" 占位符提取的,随后是可选的QHttpServerRequest 和可选的QHttpServerResponder 。这两个类被称为特殊参数。
slot 可以返回一个QHttpServerResponse 或可转换类型:
QHttpServer server;
server.route("/test/", this, [] () { return ""; });注意:此 函数 route() 不得在slot 中被调用,因此任何路由处理程序都无法注册其他路由处理程序。
此外,如果提供了可选的QHttpServerResponder 参数,则必须使用该参数写入响应,且该函数必须返回void 或QFuture<void>。QFuture<VOID> 支持功能是在 Qt 6.11 中添加的。QHttpServerResponder 不可复制,可以作为引用或右值引用传递,但返回QFuture<VOID> 时除外——此时必须将其作为右值引用传递,以防止其超出作用域。
server.route("/test2", this,
[] (QHttpServerResponder &&responder) {
responder.write(QHttpServerResponder::StatusCode::Forbidden);
});注意:如果 请求是由接受QHttpServerResponder 作为参数的slot 处理的,则不会调用任何请求后的处理程序(参见addAfterRequestHandler )。
此外,QHttpServerRequest 可用作最后一个参数,或者(如果存在QHttpServerResponder 参数)用作倒数第二个参数,以获取请求的详细信息。它可以作为 const 引用(仅适用于非并发回调)或按值传递,并可用于访问请求正文:
server.route("/test3", QHttpServerRequest::Method::Post, this,
[] (QHttpServerRequest request, QHttpServerResponder &&responder) {
responder.write(request.body(), "text/plain"_ba);
});pathPattern 中的任何占位符("<arg>" )都会自动转换为与处理程序参数类型匹配的格式。支持的类型包括整数、浮点数、QString 、QByteArray 和QUrl 。QUrl 类可作为最后一个参数,用于处理pathPattern 的结尾;通过将其拆分,可支持任意数量的参数。可使用QHttpServerRouter::addConverter() 添加自定义转换器。
每个已注册的类型都关联有一个正则表达式,用于匹配并转换pathPattern 中的占位符。这些正则表达式模式会被组合起来,以构建整个路径的解析器。 随后,生成的解析器将用于验证路径是否与模式匹配。如果解析成功,则使用转换后的参数调用相应的函数;如果解析失败,则尝试调用下一个已注册的回调函数;如果所有回调函数的解析均失败,则调用 missingHandler。
在下面的示例中,请求路径中替换"<arg>" 的值会被转换为int ,因为该 lambda 函数期望接收int 参数。当 HTTP 请求匹配该路由时,转换后的值会被传递给 lambda 函数的page 参数:
QHttpServer server;
server.route("/showpage/<arg>", this, [] (int page) { return getPage(page); });该函数若成功,则返回指向新创建的 Rule 的指针;否则返回nullptr 。该指针可用于设置任何自定义QHttpServerRouter 类的参数:
auto rule = server.route<MyRule>("/test4", this, [] () {return "";});
rule->setParameter("test");默认情况下,请求在QHttpServer 的线程内按顺序处理。如果需要并发处理,请求处理程序可以返回QFuture<QHttpServerResponse> :
server.route("/feature/<arg>", [] (int ms) {
return QtConcurrent::run(pool, [ms] () {
QThread::msleep(ms);
return QHttpServerResponse("the future is coming");
});
});QtConcurrent::run() 的 lambda 表达式会并行执行,但所有网络通信都在QHttpServer 所属的线程中进行。
返回 futures 的路由仅在 HTTP/2 连接上才完全并发执行。早期版本的 HTTP 不支持交错处理不同响应的各个部分:响应必须按请求到达的顺序完整返回。 因此,即使路由处理程序返回一个QFuture<void>,该 HTTP/1 连接上的下一个传入请求也必须等到当前请求处理完成后才会被处理。不过,不同连接上的路由处理程序可以并行执行。
让路由处理程序在并发线程中执行其工作,对所有版本的 HTTP 都有益处,因为QHttpServer 所属的线程将不再承担并发线程所执行的工作。
QHttpServerRequest slot 是可复制的,且在返回未来对象时必须按值捕获,因为传递给 的变量可能在未来对象完成之前就已超出作用域。
server.route("/test4", QHttpServerRequest::Method::Post, this,
[] (QHttpServerRequest request) {
return QtConcurrent::run(pool, [request]() {
return QHttpServerResponse("text/plain"_ba, request.body());
}
});如果在返回 Future 时,slot 通过引用捕获了QHttpServerRequest 或QHttpServerResponder ,则会引发断言,并附有说明解释为何此操作被禁止。
并非所有平台都支持将 `QHttpServerResponder ` 移动到传递给 `QConcurrent::run` 的可变 lambda 中,因此解决方法是将 `QHttpServerResponder ` 移动到 `std::shared_ptr` 中,然后复制该指针。
server.route("/concurrent-multipart-back/<arg>",
[](QString message, QHttpServerResponder &&responder) {
return QtConcurrent::run(pool,
[=, r = std::make_shared<QHttpServerResponder>(std::move(responder))] {
QByteArray ba = message.toUtf8();
r->writeBeginChunked("text/plain"_ba);
for (ushort i = 1; i < 8; ++i) {
r->writeChunk(ba);
}
r->writeEndChunked(ba);
});
});另请参阅 QHttpServerRouter::addRule 和addAfterRequestHandler 。
template <typename Rule = QHttpServerRouterRule, typename Functor> Rule *QHttpServer::route(const QString &pathPattern, Functor &&handler)
重载 `QHttpServer::route ` 函数,用于为 `pathPattern ` 和 `QHttpServerRequest::Method::AnyKnown` 创建规则。所有请求都会转发至 `handler`,该参数可以是函数指针、不可变的lambda表达式,或任何其他具有 `const call` 运算符的可复制可调用对象。该规则在 `QHttpServer ` 被销毁之前一直有效。
这是一个重载函数。
template <typename Rule = QHttpServerRouterRule, typename Functor> Rule *QHttpServer::route(const QString &pathPattern, QHttpServerRequest::Methods method, Functor &&handler)
重载 `QHttpServer::route ` 函数,用于为 `pathPattern ` 和 `method` 创建规则。所有请求都会转发至 `handler`,该参数可以是函数指针、不可变的 lambda 表达式,或任何其他具有 `const call` 运算符的可复制可调用对象。该规则在 `QHttpServer ` 被销毁之前始终有效。
这是一个重载函数。
template <typename Rule = QHttpServerRouterRule, typename Functor> Rule *QHttpServer::route(const QString &pathPattern, const QObject *context, Functor &&slot)
重载了QHttpServer::route ,用于为pathPattern 和方法QHttpServerRequest::Method::AnyKnown 创建规则。所有请求均被转发至context 和slot 。
这是一个重载函数。
QHttpServerRouter *QHttpServer::router()
返回指向路由器对象的指针。
const QHttpServerRouter *QHttpServer::router() const
返回指向常量路由器对象的指针。
template <typename Functor> void QHttpServer::setMissingHandler(const QObject *context, Functor &&slot)
为未处理的请求设置处理程序。
所有未处理的请求都将转发至context 的slot 。
slot 必须实现void (*)(const QHttpServerRequest &, QHttpServerResponder &) 接口。slot 也可以是函数指针、不可变的lambda表达式,或任何其他具有const call运算符且可复制的可调用对象。在这种情况下,context 将是一个上下文对象。该处理程序在上下文对象被销毁之前一直有效。
默认处理程序将返回状态码404 Not Found 。
另请参阅 clearMissingHandler 。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.