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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章