如何使用QtHttpServer创建REST API

How to create a REST API with QtHttpServer

如何使用QtHttpServer创建REST API

September 27, 2022 by Konrad Kujawa | Comments

​Konrad Kujawa,2022年9月27日|评论

Current status of QtHttpServer

QtHttpServer的当前状态

Back in 2019 we announced QtHttpServer to the public, now we are extremely happy to introduce a technical preview,

早在2019年,我们就向公众发布了QtHttpServer,现在我们非常高兴地推出技术预览版,

starting in Qt 6.4. for this project.

从Qt 6.4开始。

What is QtHttpServer

什么是QtHttpServer

Qt Http Server is a high-level API that provides easy support for implementing an HTTP server in your application.

Qt Http Server是一个高级API,它为在应用程序中实现Http服务器提供了简单的支持。

It is designed to be embedded in applications to expose things on a trusted network and does not have robustness/security as a goal, it is not suitable for use on the public internet.

它被设计为嵌入到应用程序中,以在可信网络上公开内容,并且没有健壮性/安全性作为目标,不适合在公共互联网上使用。

How does the REST API work

REST API是如何工作的

The REST API communicates with the server using HTTP. The REST API is used to perform CRUD - create, read, update, delete - operations on a given resource. This uses a variety of HTTP methods (e.g. GET for reading operations, POST for creating operations, PUT and PATCH for updating resources, and DELETE for deleting data). Data is usually transmitted via HTTP request/response bodies in the form of JSON objects.

REST API使用HTTP与服务器通信。RESTAPI用于对给定资源执行CRUD-创建、读取、更新、删除操作。这使用了多种HTTP方法(例如,GET用于读取操作,POST用于创建操作,PUT和PATCH用于更新资源,DELETE用于删除数据)。数据通常以JSON对象的形式通过HTTP请求/响应体传输。

Implementing a REST API

实现REST API

For the sake of simplicity, we will discuss only a few of the most important parts like routing, handling requests, creating responses and basic authorization. Fully functional examples can be found in the documentation.

​为了简单起见,我们将只讨论几个最重要的部分,如路由、处理请求、创建响应和基本授权。完整的功能示例可以在文档中找到。

Hello world

#include <QtCore>
#include <QtHttpServer>

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);
    QHttpServer httpServer;

    const auto port = httpServer.listen(QHostAddress::Any);

    if (!port)
        return 0;

    qDebug() << QCoreApplication::translate("QHttpServerExample",
            "Running on http://127.0.0.1:%1/ (Press CTRL+C to quit)").arg(port);
    return app.exec(); 
} 

Let's start with the backbone of our server. We create a QCoreApplication with QHttpServer running on our local address. We leave QHttpServer to choose a port. Next, we need to make the server route specific requests to suitable handlers.

让我们从服务器的主干开始。我们创建了一个QCoreApplication,其中QHttpServer在本地地址上运行。我们让QHttpServer来选择端口。接下来,我们需要将服务器路由特定请求发送给合适的处理程序。

Define routes

定义路由

GET route

GET路由

httpServer.route("/myApi", QHttpServerRequest::Method::Get,
    [&myData](const QHttpServerRequest &request) {
        QJsonArray array = myData;
        return QHttpServerResponse(array);
    }
);

Starting with the GET method, our API in this case returns a list of results as a JSON array. To achieve that, we need to call QHttpServer::route() with a path that will match a request, the method (or methods) that are supported for that resource (if not specified, then all HTTP methods will be matched) and the last argument is a handler which shall be called. In this example, we route GET requests for /myApi to a handler that produces a response. The handler returns QJsonArray as a QHttpServerResponse with (default) HTTP status code 200 - OK.

​从GET方法开始,本例中的API以JSON数组的形式返回结果列表。为了实现这一点,我们需要调用QHttpServer::route(),其中的路径将匹配请求、该资源支持的方法(如果未指定,则将匹配所有HTTP方法),最后一个参数是应调用的处理程序。在本例中,我们将/myApi的GET请求路由到生成响应的处理程序。处理程序将QJsonArray作为QHttpServerResponse返回,(默认)HTTP状态代码为200-OK。

GET route with dynamic parameters

具有动态参数的GET路由

httpServer.route("/myApi/<arg>", QHttpServerRequest::Method::Get,
    [&myData](int id, const QHttpServerRequest &request) {
        QJsonObject myApiObject = myData.find(id);
        return QHttpServerResponse(myApiObject);
    }
);

Now, let's add a route to return only one item instead of the whole list. To make it possible, we define a dynamic route that matches an int argument after the /myApi/ path. We define that by including a placeholder, <arg>, in the path. Because our handler takes an int parameter, this route is used when the relevant part of the URL can be converted to an int, which will be passed to the handler.

现在,让我们添加一个路由,只返回一个项目,而不是整个列表。为了实现这一点,我们定义了一个动态路由,它匹配/myApi/路径后面的int参数。我们通过在路径中包含占位符<arg>来定义它。因为我们的处理程序采用int参数,所以当URL的相关部分可以转换为int时,将使用此路由,int将被传递给处理程序。

In this example, the <arg> placeholder could even be omitted because it appears at the end of the path expression.

在本例中,<arg>占位符甚至可以省略,因为它出现在路径表达式的末尾。

To know more about routing, check out this blog post.

​要了解有关路由的更多信息,请查看此博客帖子。

POST route with authorization

带授权的POST路由

bool authorize(const QHttpServerRequest &request)
{
    for (const auto &[key, value] : request.headers()) {
        if (key == “SECRET_KEY” && value == “SECRET_VALUE”)
            return true;
    }
    return false;
}

QJsonObject byteArrayToJsonObject(const QByteArray &arr)
{
    const auto json = QJsonDocument::fromJson(arr);
    return json.object();
}

httpServer.route("/myApi", QHttpServerRequest::Method::Post,
    [&myData](const QHttpServerRequest &request) {
        if (!authorize(request))
            return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized);

        const QJsonObject newObject = byteArrayToJsonObject(request.body());
        myData.insert(newObject);
        return QHttpServerResponse(newObject, QHttpServerResponder::StatusCode::Created);
    }
);

Let's take a look at the POST method snippet. First, we want to authorize the modification request. We scan the request headers to find the SECRET_KEY header and its value equal to the string SECRET_VALUE (obviously, you would do something more secure in reality). If that header is not found, we return QHttpServerResponse with HTTP status code 401 - Unauthorized. Then we extract the JSON object from the request body and store it in myData. Finally, we return an HTTP response containing the same JSON object along with HTTP status code 201 – Created.

让我们看看POST方法片段。首先,我们想授权修改请求。我们扫描请求头以找到SECRET_KEY头及其值等于字符串SECRET_VALUE(显然,在现实中您会做一些更安全的事情)。如果找不到该标头,则返回QHttpServerResponse,HTTP状态代码为401-Unauthorized。然后,我们从请求体中提取JSON对象,并将其存储在myData中。最后,我们返回一个包含相同JSON对象的HTTP响应,以及HTTP状态代码201–Created。

Hosting files

处理文件

httpServer.route("/myApi/img/<arg>-image.jpg", QHttpServerRequest::Method::Get,
    [](int imageId, const QHttpServerRequest &) {
        return QHttpServerResponse::fromFile(QString(":/assets/img/%1-image.jpg")
                .arg(imageId));
    }
);

The last thing that we wanted to show is the easy hosting of files for our API. To return a static file as an HTTP response, we can use the convenience method QHttpServerResponse::fromFile().

​我们想展示的最后一件事是为API轻松处理文件。要将静态文件作为HTTP响应返回,我们可以使用方便的方法QHttpServerResponse::fromFile()。

This shows how to do simple things - for more detailed and full examples, please check out our examples page or QtHttpServer documentation.

​这展示了如何做简单的事情-要获得更详细和完整的示例,请查看我们的示例页面或QtHttpServer文档。

Keep in mind that this project is in the technical preview phase, which means that we are still working on it,and some things are subject to change. Therefore, your feedback is extremely important.

请记住,这个项目正处于技术预览阶段,这意味着我们仍在努力,有些事情可能会发生变化。因此,您的反馈非常重要。

We hope that you will try our new project and share your opinions with us.

我们希望您能尝试我们的新项目,并与我们分享您的意见。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值