1
0

s23-custom-methods.md 3.3 KB


title: "S23. カスタムHTTPメソッドを扱う" order: 42

status: "draft"

サーバーは知らないHTTPメソッドを400 Bad Requestで弾きます。RFC 4918のWebDAVメソッド(PROPFINDPROPPATCHMKCOLなど)やUPnPのSUBSCRIBEのような拡張メソッドを受け付けたいときは、CustomRoute()でハンドラを登録してください。登録したことがそのまま「このメソッドを受け付ける」という意味になります。

基本の使い方

svr.CustomRoute("PROPFIND", "/dav/:id",
                [](const httplib::Request &req, httplib::Response &res) {
                  // リクエストボディも通常どおり読める
                  auto id = req.path_params.at("id");
                  res.status = httplib::StatusCode::MultiStatus_207;
                  res.set_content(build_multistatus(req.body), "application/xml");
                });

パターンの書き方はGet()などと同じです。正規表現もパスパラメーターもそのまま使えます。

OPTIONSで対応メソッドを知らせる

WebDAVクライアントは接続すると、まずOPTIONSでサーバーの能力を問い合わせます。cpp-httplibはDAV:ヘッダーもAllowヘッダーも自動生成しないので、自分で返してください。ここを忘れると、PROPFINDが正しく動いてもクライアントに拒否されます。

svr.Options("/dav/.*", [](const httplib::Request &req, httplib::Response &res) {
  res.set_header("DAV", "1");
  res.set_header("Allow", "OPTIONS, GET, HEAD, PROPFIND, PROPPATCH, MKCOL");
});

ボディをストリーミングで受け取る

Post()などと同じく、Content Reader版のオーバーロードがあります。大きなXMLを一度にメモリへ載せたくないときに使ってください。

svr.CustomRoute("REPORT", "/dav/.*",
                [](const httplib::Request &req, httplib::Response &res,
                   const httplib::ContentReader &content_reader) {
                  content_reader([&](const char *data, size_t data_length) {
                    // 少しずつ処理する
                    return true;
                  });
                  res.status = httplib::StatusCode::MultiStatus_207;
                });

覚えておくこと

  • メソッド名はHTTPのトークン(RFC 9110)である必要があります。listen()より前に登録してください
  • GETHEADPOSTPUTDELETECONNECTOPTIONSTRACEPATCHPRIは登録できません。これらには専用のメソッドを使ってください
  • 登録が拒否されるとis_valid()falseになり、listen()が失敗します。呼ばれないハンドラを抱えたままサーバーが起動することはありません
  • 静的ファイルの配信とWebSocketのアップグレードはGET/HEADのままです

Note: cpp-httplibが用意するのはメソッドのルーティングまでです。WebDAVを名乗るなら、207 Multi-StatusのXML生成、Depthヘッダーの解釈、ロックの管理は自分で実装することになります。プロトコルの本体はライブラリの外側です。

ハンドラ登録の基本はS01. GET / POST / PUT / DELETEハンドラを登録するを参照してください。