C++のWebフレームワーク「Drogon」を触ってみた

# はじめに
こんにちは、tuq376sです。
この記事は「[ラクス Advent Calendar 2022](https://qiita.com/advent-calendar/2022/rakus)」の21日目の記事になります。

先日、久しぶりに学生時代に使ってたC++をまたやりたいなぁと思ってなんとなく調べていたら、**Drogon**というWebフレームワークに行き当たりました。
フレームワークと言えば、学生のころは学習のために全部自力でプログラムを書いていたのもあり、初めて使ったときは一言一句把握せず使うことになんとなく不安になったのを覚えています。（今ではむしろ頼りきりですが……。）
とにもかくにも、C++でのWebアプリケーションはまさに学生の頃にも課題で作ったことがあり気になったので、触ってみた内容を紹介したいと思います。

# Drogonとは
[Drogon](https://github.com/drogonframework/drogon)は、C++14以降で利用できるWebフレームワークです。
C++が実際にWebアプリケーションで使われているイメージはあんまりなかったのですが、どうやら処理が速いところが良い様子。
クロスプラットフォームでいろいろなOSに対応している他、DBもPostgreSQL, MySQL, Sqlite3, Redisが使えるようです。

# 環境構築
[Wikiのインスト](https://github.com/drogonframework/drogon/wiki/ENG-02-Installation#drogon-installation)がけっこう読みやすいので、ここを読みながら実施していきます。
今回は、`WSL`にインストールしたてのまっさらな`Ubuntu 22.04.1 LTS`で実施しました。

## 事前にインストールが必要なもの
Drogonの前に、ビルドに必要な以下を全てインストールします。
- git (今回はデフォルトで入っていたのでインストールしていませんが)
- gcc
- g++
- cmake
- jsoncpp (aptでインストールできなかったので[Github](https://github.com/open-source-parsers/jsoncpp)からクローンして自前でビルドしました)
- uuid-dev
- openssl
- zlib1g-dev

## Drogonのインストール
必要なものが揃ったら、wikiの内容に従ってDrogonをインストールします。
事前に必要なものがインストールされていれば特に失敗することもないと思います。
(自分はg++だけ何故かインストールしていなくてハマりました)

```
$ git clone https://github.com/drogonframework/drogon
$ cd drogon
$ git submodule update --init
$ mkdir build
$ cd build
$ cmake ..
$ sodo make && sudo make install
```
## drogon_ctlコマンドの確認
無事にビルドが終わっていると`drogon_ctl`というコマンドが使えるようになっています。
試しにバージョンを見てみると、ロゴとバージョン、各ライブラリが有効かどうかが表示されました。
```
$ drogon_ctl -v
     _
  __| |_ __ ___   __ _  ___  _ __
 / _` | '__/ _ \ / _` |/ _ \| '_ \
| (_| | | | (_) | (_| | (_) | | | |
 \__,_|_|  \___/ \__, |\___/|_| |_|
                 |___/

A utility for drogon
Version: 1.8.2
Git commit: 19f08786f0490de8e560d7f761b3166005a2d16d
Compilation:
  Compiler: /usr/bin/c++
  Compiler ID: GNU
  Compilation flags: -std=c++17 -I/usr/local/include
Libraries:
  postgresql: no  (pipeline mode: no)
  mariadb: no
  sqlite3: no
  openssl: no
  brotli: no
  boost: no
  hiredis: no
  c-ares: no
```

# Hello,world! してみる
これでDrogonのインストールは完了です。
さっそく新しいプロジェクトを作って「Hello,world!」を表示してみます。
お約束だとしても、新しい技術に触れたときにこれはいつもわくわくするものなんですよね。

## プロジェクト作成
プロジェクトの作成には先ほどの`drogon_ctl`を使用します。
```
$ drogon_ctl create project my_first_project
create a project named my_first_project
$ ls
CMakeLists.txt  build  config.json  controllers  filters  main.cc  models  plugins  test  views
```

プロジェクトが作成されたら、`build`ディレクトリ内でビルドします。
```
$ cd my_first_project
$ cd build/
$ cmake ..
$ make
```
これだけで最低限の設定は完了です。
サーバーをこの状態で立ち上げてみます。
```
$ sudo ./my_first_project
```
`http://localhost`にアクセスして、404画面が表示されれば無事成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959854/5482b01d-6fbc-6f1a-32c7-5ad860098119.png)

## コントローラ作成
「Hello,world!」を表示するだけならこのまま`index.html`を作って終わりなのですが、せっかくなのでコントローラを作ってルーティングをしてみます。
作成コマンドは以下です。実施すると「TestController.h」「TestController.cc」が作成されていることがわかります。
```
$ drogon_ctl create controller TestController　　　　//作成したプロジェクト直下で実施
Create a http simple controller: TestController
$ ls
CMakeLists.txt     TestController.h  config.json  filters  models   test
TestController.cc  build             controllers  main.cc  plugins  views
```

### TestController.h
「TestController.h」はルーティングに使われます。
ファイル内を見ると`PATH_ADD()`でパスを指定できるようです。
``` c++:TestController.h
#pragma once
#include <drogon/HttpSimpleController.h>
using namespace drogon;
class TestController : public drogon::HttpSimpleController<TestController>
{
  public:
    void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
    PATH_LIST_BEGIN
    // list path definitions here;
    // PATH_ADD("/path", "filter1", "filter2", HttpMethod1, HttpMethod2...);

    PATH_ADD("/", Get);       //追加

    PATH_LIST_END
};   
```

### TestController.cc
「TestController.cc」は実際の内部処理を記述していきます。今回は公式のwikiをそのまま拝借して、単純なHTTPレスポンスを返します。
```c++:TestController
#include "TestController.h"

void TestController::asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback)
{
    // write your application logic here
    auto resp=HttpResponse::newHttpResponse();
    resp->setStatusCode(k200OK);
    resp->setContentTypeCode(CT_TEXT_HTML);
    resp->setBody("Hello, world!");
    callback(resp);
}
~            
```
### ビルドして表示
これでコントローラの作成も完了ですので、先ほどと同じようにビルドして`http://localhost`にアクセスしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959854/4e9704ee-2fa3-2ac9-a73c-82ea58240f8d.png)
きちんと表示されました！



# おわりに
ということで、今回はWebフレームワークのDrogonを触ってみました。
ほとんど環境構築と導入だけだったのでC++のコードを書いたわけではないですが、久しぶりに`cmake`使ったり`using namespace`の文字列を見られて楽しかったです。
Drogon自体もいろいろできそうな気がするので、年末年始にもう少し触ってみたいですね。

ここまで読んでいただきありがとうございました。