【Crow】Crow学习笔记(1)

作者:wallace-lai
发布:2024-01-07
更新:2024-01-07

一、Crow是什么

Crow

Crow是一个用于创建HTTP或者Websocket服务的C++框架,类似于Python的Flask路由。它的特点是易于使用和高性能,在运行速度方面打败了很多现有框架。

以当前(01/2024)的最新版本v1.0+5为例,Crow的所有实现都放在了include目录下的32个头文件中,总共代码量不超过13K。Crow的首个正式发布版本v0.2是2020年11月发布的,距今不超过4年。因此,Crow是非常值得学习的。

二、使用Crow开发Web应用

2.1 hello world

第一个hello world程序如下所示。

#include "crow.h"

int main(int argc, char **argv)
{
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")([]() {
        return "hello world!";
    });

    app.port(18080).multithreaded().run();
}

对于第一个程序,可以做更详细的讲解。

  • 包含crow头文件

#include "crow.h"`

所有使用crow库的程序都应该包含crow.h头文件

  • 实例化一个SimpleApp对象

crow::SimpleApp app

SimpleApp类是crow库自带的一个App类实现。SimpleApp类内部包含了crow大部分组件,用户可以通过app和crow的其余组件进行交互。说白了就是关于Web编程的大部分需求都可以通过app来实现。关于App的更详细介绍将放在后面的笔记中。

  • 定义路由

CROW_ROUTE(app, "/")([]() {
    return "hello world!";
});

Crow-Helloworld

使用CROW_ROUTE宏定义一条根路由。所谓定义路由就是定义当客户端访问一个确定的URL时会发生什么事情。具体到上述例子就是:当用户访问网站首页(/),比如http://0.0.0.0:18080时,服务器将会向用户的浏览器页面返回一个”hello world!”的字符串。

  • 启动app

app.port(18080).multithreaded().run();

启动app,指定服务运行端口(port())为18080并使用多线程(multithreaded())的方式(默认启用4个线程)。注意port()multithreaded()并不是必须的,如果不使用port()指定端口则使用默认的80端口。

  • 编译

使用以下命令编译上面的代码,注意需要加上-lpthread选项才能成功编译。

 g++ 00-helloworld.cpp -lpthread -o hello

2.2 使用模板

简单模板

为了让页面更加美观,我们不能再像上节中的例子一样,简单地在浏览器页面上显示个字符串。corw作为Web开发框架,支持模板功能,利用模板功能,我们可以向浏览器返回一个HTML页面。

首先准备好HTML页面,比如index.html,放在templates目录下。放在templates目录下的模板可以直接被crow识别。

<!DOCTYPE html>
<html>
    <body>
        <p>Hellow World!</p>
    </body>
</html>

随后在上节例子的基础上稍加改动即可。使用mustacheload_text方法将index.html的内容返回给浏览器。

CROW_ROUTE(app, "/")([]() {
    auto index = crow::mustache::load_text("index.html");
    return index;
});

webpage

向模板传参

假设我们需要向模板传入用户名字这么一个参数,我们首先需要在模板中定义好相应的变量,用于接收crow传递过来的值。如下所示,我在模板中定义了一个name变量用于存放crow传递过来的用户名。

<!DOCTYPE html>
<html>
    <body>
        <p>Hellow {{name}}!</p>
    </body>
</html>

随后将上节中的路由改写成下面的样子

CROW_ROUTE(app, "/<string>")([](std::string name) {
    auto page = crow::mustache::load("index.html");
    crow::mustache::context ctx ({{"name", name}});
    return page.render(ctx);
});

稍作解释:

  • "/<string>" : 将/后面的内容当做string来解析

  • load("index.html") : 因为模板中定义了变量,所以不能再用load_text

  • ctx ({{"name", name}}) : 定义一个渲染模板所需的上下文,将用户名name传入

  • page.render(ctx) : 根据上下文ctx去渲染模板

webpage

三、总结

上面章节属于是crow框架快速上手的介绍性内容,共涉及了三个简单场景总结如下。

  • (1)简单路由场景

#include "crow.h"

int main(int argc, char **argv)
{
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")([]() {
        return "hello world!";
    });

    app.port(18080).multithreaded().run();
}
  • (2)使用模板

模板代码:

<!DOCTYPE html>
<html>
    <body>
        <p>Hellow World!</p>
    </body>
</html>

C++代码:

#include "crow.h"

int main(int argc, char **argv)
{
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")([]() {
        auto index = crow::mustache::load_text("index.html");
        return index;
    });

    app.port(8080).multithreaded().run();
}
  • (3)向模板传参

模板代码:

<!DOCTYPE html>
<html>
    <body>
        <p>Hellow {{name}}!</p>
    </body>
</html>

C++代码:

#include "crow.h"

int main(int argc, char **argv)
{
    crow::SimpleApp app;

    CROW_ROUTE(app, "/<string>")([](std::string name) {
        auto page = crow::mustache::load("index.html");
        crow::mustache::context ctx ({{"name", name}});
        return page.render(ctx);
    });

    app.port(8080).multithreaded().run();
}

以上三个场景中涉及到的crow框架中的“元素”有:

  • crow::SimpleApp : App类

  • CROW_ROUTE : 路由

  • crow::mustache : 模板

crow中的更多“元素”将在后续的笔记中介绍