cpp-d03-drogon-web开发入门


排行来源:https://www.techempower.com/benchmarks/

今天来学习一下由国人开发的疯狂刷棒的api 框架:drogon

0x00 准备C++WEB开发环境

从源码安装,生成项目配置工具。

git clone [https://github.com/an-tao/drogon](https://github.com/an-tao/drogon)
cd drogon
git submodule update --init
mkdir build
# gcc 12以上,开启协程支持
cmake .. -DCMAKE_CXX_FLAGS="-std=c++20"
make && sudo make install

中途缺啥,直接brew install,大概率可直接解决

安装完成后,可以使用命令行工具drogon_ctl快捷命令创建和维护代码。
也可以使用别名:dg_ctl

查看基础用法:

$ drogon_ctl help create
Use create command to create some source files of drogon webapp

Usage:drogon_ctl create <view|controller|filter|project|model> [-options] <object name>

drogon_ctl create view <csp file name> [-o <output path>] [-n <namespace>] [--path-to-namespace] //create HttpView source files from csp files, namespace is prefixed of path-to-namespace

drogon_ctl create controller [-s] <[namespace::]class_name> //create HttpSimpleController source files

drogon_ctl create controller -h <[namespace::]class_name> //create HttpController source files

drogon_ctl create controller -w <[namespace::]class_name> //create WebSocketController source files

drogon_ctl create controller -r <[namespace::]class_name> [--resource=...]//create restful controller source files

drogon_ctl create filter <[namespace::]class_name> //create a filter named class_name

drogon_ctl create plugin <[namespace::]class_name> //create a plugin named class_name

drogon_ctl create project <project_name> //create a project named project_name

drogon_ctl create model <model_path> [--table=<table_name>] [-f]//create model classes in model_path

0x01 创建第一个项目

  • 创建项目
drogon_ctl create project dc_hello

使用CLion打开此项目是可以直接运行的,访问本机 80 服务,返回404.

  • 添加一个 index响应
    调整main.cpp, 增加一个handler响应处理。
#include <drogon/drogon.h>
using namespace drogon;
int main() {
  drogon::app().addListener("0.0.0.0", 80);
  drogon::app().registerHandler("/",
                                [](const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
                                  auto resp = HttpResponse::newHttpResponse();
                                  resp->setBody("hello world");
                                  callback(resp);
                                });
  drogon::app().run();
  return 0;
}

  • 新增一个Controller,用于处理复杂rest api处理

开始之前,先看一个url例子:

http://localhost/api/v1/user/get

分解一下:

  • api/v1 : 在drogon中, 是以namespace的形式存在
  • user : Controller 处理类,也符合Rest中实体的名称定义
  • get : 在Controller上的某个具体行为

接下来,开始操作

cd controllers
drogon_ctl create controller -h api::v1::User

生成文件后,手动在CMakeFiles.txt 中加上 .cc 文件。

# 启动 协程,在project 前添加
set(CMAKE_CXX_STANDARD 20)

# 添加文件
add_executable(${PROJECT_NAME} main.cc controllers/api_v1_User.cc)

接下来,修改两个文件:

  • .h
#pragma once
#include <drogon/HttpController.h>
using namespace drogon;
namespace api::v1 {
class User : public drogon::HttpController<User> {
 public:
  METHOD_LIST_BEGIN
    METHOD_ADD(User::get, "/get", Get);
  METHOD_LIST_END
  void get(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback);
};
}
  • .cc
#include "api_v1_User.h"
using namespace api::v1;
void User::get(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
  Json::Value rst;
  rst["code"] = 0;
  rst["message"] = "ok";
  auto resp = HttpResponse::newHttpJsonResponse(rst);
  callback(resp);
}

编译运行测试接口:

$ curl localhost/api/v1/user/get 
{"code":0,"message":"ok"}

0x02 多种参数获取方式

一、URL参数

直接上代码:

  // 增加URI配置, {1}对应方法后面的第一个参数
  METHOD_ADD(User::get_info, "/info/{1}", Get);
  void get_info(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, std::string name);
  void User::get_info(const HttpRequestPtr &req,
                    std::function<void(const HttpResponsePtr &)> &&callback,
                    std::string name) {
  Json::Value rst;
  rst["code"] = 0;
  rst["message"] = "hello: " + name;
  auto resp = HttpResponse::newHttpJsonResponse(rst);
  callback(resp);
}

效果 :

$ curl localhost/api/v1/user/info/demo 
{"code":0,"message":"hello: demo"}

二、query参数

  METHOD_ADD(User::get_detail, "/detail?name={1}", Get);
  void get_detail(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, std::string name);

  void User::get_detail(const HttpRequestPtr &req,
                      std::function<void(const HttpResponsePtr &)> &&callback,
                      std::string name) {
  Json::Value rst;
  rst["code"] = 0;
  rst["message"] = "detail: " + name;
  auto resp = HttpResponse::newHttpJsonResponse(rst);
  callback(resp);
}

上面两种,感觉是同一类处理方法,通过类似正则的方式去获取相应的参数。

三、json Body参数

编写一个POST方式,提交json的接口例:

  METHOD_ADD(User::add, "/add", Post);
  void add(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback);
  void User::add(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) {
  auto param = req->getJsonObject();

  Json::Value rst;
  rst["code"] = 0;

  if (param) {
    auto name = (*param)["name"].asString();
    rst["message"] = "user added :" + name;
  }
  auto resp = HttpResponse::newHttpJsonResponse(rst);
  callback(resp);
}

验证:

$ curl -XPOST localhost/api/v1/user/add -d '{"name":"Cook"}' -H"content-type:application/json"
{"code":0,"message":"user added :Cook"}

四、json请求参数,自动转为Bean

在.h文件中, 需要预定义一个转换方法:

namespace api::v1 {
struct UserParam {
  std::string name;
  std::string email;
};
}

namespace drogon {
template<>
inline api::v1::UserParam fromRequest(const HttpRequest &req) {
  auto json = req.getJsonObject();
  api::v1::UserParam param;
  if (json) {
    param.name = (*json)["name"].asString();
    param.email = (*json)["email"].asString();
  }
  return param;
}
}

然后编写路由匹配和方法定义:

  METHOD_ADD(User::add_user, "/add/user", Post);
  // 注意: 这里第一个参数是转换后的结构体对象,可以自动提取转换
  void add_user(UserParam &&pUserParam, std::function<void(const HttpResponsePtr &)> &&callback) const;
  void User::add_user(UserParam &&pUserParam, std::function<void(const HttpResponsePtr &)> &&callback) const {
  Json::Value rst;
  rst["code"] = 0;
  rst["message"] = pUserParam.name + ":" + pUserParam.email;
  auto resp = HttpResponse::newHttpJsonResponse(rst);
  callback(resp);
}

0x03 小结

至此,已经具体API开发的基本能力了, 后续增加其他体验:

  • redis
  • mysql
  • 日志
  • 切面

最后,也是最重要的官方学习文档:
https://github.com/drogonframework/drogon-docs/blob/master/CHN-03-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B.md

0x04 Mac下协程编译支持

brew install gcc@12

修改cmake文件中的编译器

SET(CMAKE_C_COMPILER /opt/homebrew/bin/gcc-12)
SET(CMAKE_CXX_COMPILER /opt/homebrew/bin/g++-12)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章