Update pages-data.json with new content and structure for cpp-httplib documentation

This commit is contained in:
yhirose
2026-03-02 17:22:52 -05:00
parent 2e124cde02
commit 74807d24a7
30 changed files with 1894 additions and 1814 deletions

View File

@@ -105,13 +105,13 @@
<p>cpp-httplibを始めるのに必要なのは、<code>httplib.h</code>とC++コンパイラーだけです。ファイルをダウンロードして、Hello Worldサーバーを動かすところまでやってみましょう。</p>
<h2>httplib.h の入手</h2>
<p>GitHubから直接ダウンロードできます。常に最新版を使ってください。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -LO</span><span style="color:#d3d0c8;"> https://github.com/yhirose/cpp-httplib/raw/refs/tags/latest/httplib.h
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -LO</span><span style="color:#4f5b66;"> https://github.com/yhirose/cpp-httplib/raw/refs/tags/latest/httplib.h
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -LO https://github.com/yhirose/cpp-httplib/raw/refs/tags/latest/httplib.h
</span></pre>
</div>
</div></div>
<p>ダウンロードした <code>httplib.h</code> をプロジェクトのディレクトリに置けば、準備完了です。</p>
<h2>コンパイラーの準備</h2>
<table><thead><tr><th>OS</th><th>開発環境</th><th>セットアップ</th></tr></thead><tbody>
@@ -121,7 +121,7 @@
</tbody></table>
<h2>Hello World サーバー</h2>
<p>次のコードを <code>server.cpp</code> として保存しましょう。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#d3d0c8;">
</span><span style="color:#cc99cc;">int </span><span style="color:#6699cc;">main</span><span style="color:#d3d0c8;">() {
@@ -134,24 +134,24 @@
</span><span style="color:#d3d0c8;"> svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8080</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Server svr;
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::Request&amp;, httplib::Response&amp; res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello, World!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8080</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Server svr;
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::Request</span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">, httplib::Response</span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;"> res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello, World!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8080</span><span style="color:#323232;">);
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>たった数行で、HTTPリクエストに応答するサーバーが書けます。</p>
<h2>コンパイルと実行</h2>
<p>このチュートリアルのサンプルコードは、コードを簡潔に書けるC++17で書いています。cpp-httplib自体はC++11でもコンパイルできます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#747369;"># macOS
</span><span style="color:#6699cc;">clang++</span><span style="color:#f2777a;"> -std</span><span style="color:#d3d0c8;">=c++17</span><span style="color:#f2777a;"> -o</span><span style="color:#d3d0c8;"> server server.cpp
</span><span style="color:#d3d0c8;">
@@ -163,46 +163,46 @@
</span><span style="color:#747369;"># `/EHsc`: C++例外処理を有効化
</span><span style="color:#6699cc;">cl</span><span style="color:#d3d0c8;"> /EHsc /std:c++17 server.cpp
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#a7adba;"># macOS
</span><span style="color:#8fa1b3;">clang++</span><span style="color:#bf616a;"> -std</span><span style="color:#4f5b66;">=c++17</span><span style="color:#bf616a;"> -o</span><span style="color:#4f5b66;"> server server.cpp
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;"># Linux
</span><span style="color:#a7adba;"># `-pthread`: cpp-httplibは内部でスレッドを使用
</span><span style="color:#8fa1b3;">clang++</span><span style="color:#bf616a;"> -std</span><span style="color:#4f5b66;">=c++17</span><span style="color:#bf616a;"> -pthread -o</span><span style="color:#4f5b66;"> server server.cpp
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;"># Windows (Developer Command Prompt)
</span><span style="color:#a7adba;"># `/EHsc`: C++例外処理を有効化
</span><span style="color:#8fa1b3;">cl</span><span style="color:#4f5b66;"> /EHsc /std:c++17 server.cpp
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-style:italic;color:#969896;"># macOS
</span><span style="color:#323232;">clang++ -std</span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;">c++17 -o server server.cpp
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Linux
</span><span style="font-style:italic;color:#969896;"># `-pthread`: cpp-httplibは内部でスレッドを使用
</span><span style="color:#323232;">clang++ -std</span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;">c++17 -pthread -o server server.cpp
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Windows (Developer Command Prompt)
</span><span style="font-style:italic;color:#969896;"># `/EHsc`: C++例外処理を有効化
</span><span style="color:#323232;">cl /EHsc /std:c++17 server.cpp
</span></pre>
</div>
</div></div>
<p>コンパイルできたら実行します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#747369;"># macOS / Linux
</span><span style="color:#6699cc;">./server
</span><span style="color:#d3d0c8;">
</span><span style="color:#747369;"># Windows
</span><span style="color:#6699cc;">server.exe
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#a7adba;"># macOS / Linux
</span><span style="color:#8fa1b3;">./server
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;"># Windows
</span><span style="color:#8fa1b3;">server.exe
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-style:italic;color:#969896;"># macOS / Linux
</span><span style="color:#323232;">./server
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Windows
</span><span style="color:#323232;">server.exe
</span></pre>
</div>
</div></div>
<p>ブラウザで <code>http://localhost:8080</code> を開いてください。"Hello, World!" と表示されれば成功です。</p>
<p><code>curl</code> でも確認できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#d3d0c8;"> http://localhost:8080/
</span><span style="color:#747369;"># Hello, World!
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#4f5b66;"> http://localhost:8080/
</span><span style="color:#a7adba;"># Hello, World!
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl http://localhost:8080/
</span><span style="font-style:italic;color:#969896;"># Hello, World!
</span></pre>
</div>
</div></div>
<p>サーバーを停止するには、ターミナルで <code>Ctrl+C</code> を押します。</p>
<h2>次のステップ</h2>
<p>サーバーの基本がわかりましたね。次は、クライアント側を見てみましょう。cpp-httplibはHTTPクライアント機能も備えています。</p>

View File

@@ -105,7 +105,7 @@
<p>cpp-httplibはサーバーだけでなく、HTTPクライアント機能も備えています。<code>httplib::Client</code> を使って、GETやPOSTリクエストを送ってみましょう。</p>
<h2>テスト用サーバーの準備</h2>
<p>クライアントの動作を確認するために、リクエストを受け付けるサーバーを用意します。次のコードを保存し、前章と同じ手順でコンパイル・実行してください。サーバーの詳しい解説は次章で行います。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
</span><span style="color:#d3d0c8;">
@@ -153,58 +153,58 @@
</span><span style="color:#d3d0c8;"> svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8080</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Server svr;
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/search</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> q = req.</span><span style="color:#8fa1b3;">get_param_value</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">q</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Query: </span><span style="color:#4f5b66;">&quot; + q, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/post</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(req.</span><span style="color:#bf616a;">body</span><span style="color:#4f5b66;">, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/submit</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> std::string result;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">for </span><span style="color:#4f5b66;">(</span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;[key, val] : req.</span><span style="color:#bf616a;">params</span><span style="color:#4f5b66;">) {
</span><span style="color:#4f5b66;"> result += key + &quot;</span><span style="color:#a3be8c;"> = </span><span style="color:#4f5b66;">&quot; + val + &quot;</span><span style="color:#96b5b4;">\n</span><span style="color:#4f5b66;">&quot;;
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(result, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/upload</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> f = req.</span><span style="color:#bf616a;">form</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">get_file</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">file</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> content = f.</span><span style="color:#bf616a;">filename </span><span style="color:#4f5b66;">+ &quot;</span><span style="color:#a3be8c;"> (</span><span style="color:#4f5b66;">&quot; + </span><span style="color:#8fa1b3;">std::to_string</span><span style="color:#4f5b66;">(f.</span><span style="color:#bf616a;">content</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">size</span><span style="color:#4f5b66;">()) + &quot;</span><span style="color:#a3be8c;"> bytes)</span><span style="color:#4f5b66;">&quot;;
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(content, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/users/:id</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> id = req.</span><span style="color:#bf616a;">path_params</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">at</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">id</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">User ID: </span><span style="color:#4f5b66;">&quot; + id, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(</span><span style="color:#b48ead;">R</span><span style="color:#4f5b66;">&quot;(</span><span style="color:#a3be8c;">/files/(\d+)</span><span style="color:#4f5b66;">)&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> id = req.</span><span style="color:#bf616a;">matches</span><span style="color:#4f5b66;">[</span><span style="color:#d08770;">1</span><span style="color:#4f5b66;">];
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">File ID: </span><span style="color:#4f5b66;">&quot; + </span><span style="color:#8fa1b3;">std::string</span><span style="color:#4f5b66;">(id), &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Listening on port 8080...</span><span style="color:#4f5b66;">&quot; &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8080</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Server svr;
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Get(</span><span style="color:#183691;">&quot;/search&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> q </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.get_param_value(</span><span style="color:#183691;">&quot;q&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Query: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> q, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Post(</span><span style="color:#183691;">&quot;/post&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(req.body, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Post(</span><span style="color:#183691;">&quot;/submit&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> std::string result;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">for </span><span style="color:#323232;">(</span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">[key, val] </span><span style="font-weight:bold;color:#a71d5d;">:</span><span style="color:#323232;"> req.params) {
</span><span style="color:#323232;"> result </span><span style="font-weight:bold;color:#a71d5d;">+=</span><span style="color:#323232;"> key </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; = &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> val </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot;</span><span style="color:#0086b3;">\n</span><span style="color:#183691;">&quot;</span><span style="color:#323232;">;
</span><span style="color:#323232;"> }
</span><span style="color:#323232;"> res.set_content(result, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Post(</span><span style="color:#183691;">&quot;/upload&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> f </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.form.get_file(</span><span style="color:#183691;">&quot;file&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> content </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> f.filename </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; (&quot; </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#323232;">std::to_string(f.content.size()) </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; bytes)&quot;</span><span style="color:#323232;">;
</span><span style="color:#323232;"> res.set_content(content, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Get(</span><span style="color:#183691;">&quot;/users/:id&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.path_params.at(</span><span style="color:#183691;">&quot;id&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;User ID: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> id, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Get(</span><span style="font-weight:bold;color:#a71d5d;">R</span><span style="color:#183691;">&quot;(/files/(\d+))&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.matches[</span><span style="color:#0086b3;">1</span><span style="color:#323232;">];
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;File ID: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#323232;">std::string(id), </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Listening on port 8080...&quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8080</span><span style="color:#323232;">);
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<h2>GETリクエスト</h2>
<p>サーバーが起動したら、別のターミナルを開いて試してみましょう。まず、最もシンプルなGETリクエストです。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
</span><span style="color:#d3d0c8;">
@@ -218,35 +218,35 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost:8080</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// 200
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// Hello!
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Client cli(</span><span style="color:#183691;">&quot;http://localhost:8080&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// 200
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// Hello!
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p><code>httplib::Client</code> のコンストラクターにサーバーのアドレスを渡し、<code>Get()</code> でリクエストを送ります。戻り値の <code>res</code> からステータスコードやボディを取得できます。</p>
<p>対応する <code>curl</code> コマンドはこうなります。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#d3d0c8;"> http://localhost:8080/hi
</span><span style="color:#747369;"># Hello!
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#4f5b66;"> http://localhost:8080/hi
</span><span style="color:#a7adba;"># Hello!
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl http://localhost:8080/hi
</span><span style="font-style:italic;color:#969896;"># Hello!
</span></pre>
</div>
</div></div>
<h2>レスポンスの確認</h2>
<p>レスポンスには、ステータスコードとボディ以外にもヘッダー情報が含まれています。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/hi</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#cc99cc;">if </span><span style="color:#d3d0c8;">(res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#747369;">// ステータスコード
@@ -259,141 +259,141 @@
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#6699cc;">get_header_value</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Content-Type</span><span style="color:#d3d0c8;">&quot;) &lt;&lt; std::endl; </span><span style="color:#747369;">// text/plain
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// ステータスコード
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// 200
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// ボディ
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// Hello!
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// ヘッダー
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#8fa1b3;">get_header_value</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Content-Type</span><span style="color:#4f5b66;">&quot;) &lt;&lt; std::endl; </span><span style="color:#a7adba;">// text/plain
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// ステータスコード
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// 200
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// ボディ
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// Hello!
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// ヘッダー
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;get_header_value(</span><span style="color:#183691;">&quot;Content-Type&quot;</span><span style="color:#323232;">) </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// text/plain
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p><code>res-&gt;body</code><code>std::string</code> なので、JSON レスポンスをパースしたい場合は <a href="https://github.com/nlohmann/json">nlohmann/json</a> などの JSON ライブラリにそのまま渡せます。</p>
<h2>クエリパラメーター</h2>
<p>GETリクエストにクエリパラメーターを付けるには、URLに直接書くか、<code>httplib::Params</code> を使います。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/search</span><span style="color:#d3d0c8;">&quot;, httplib::Params{{&quot;</span><span style="color:#99cc99;">q</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">cpp-httplib</span><span style="color:#d3d0c8;">&quot;}});
</span><span style="color:#cc99cc;">if </span><span style="color:#d3d0c8;">(res) {
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">body </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// Query: cpp-httplib
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/search</span><span style="color:#4f5b66;">&quot;, httplib::Params{{&quot;</span><span style="color:#a3be8c;">q</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">cpp-httplib</span><span style="color:#4f5b66;">&quot;}});
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// Query: cpp-httplib
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/search&quot;</span><span style="color:#323232;">, httplib::Params{{</span><span style="color:#183691;">&quot;q&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;cpp-httplib&quot;</span><span style="color:#323232;">}});
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// Query: cpp-httplib
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p><code>httplib::Params</code> を使うと、特殊文字のURLエンコードを自動で行ってくれます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">http://localhost:8080/search?q=cpp-httplib</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#747369;"># Query: cpp-httplib
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">http://localhost:8080/search?q=cpp-httplib</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#a7adba;"># Query: cpp-httplib
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl </span><span style="color:#183691;">&quot;http://localhost:8080/search?q=cpp-httplib&quot;
</span><span style="font-style:italic;color:#969896;"># Query: cpp-httplib
</span></pre>
</div>
</div></div>
<h2>パスパラメーター</h2>
<p>URLのパスに値を直接埋め込む場合も、クライアント側は特別なAPIは不要です。パスをそのまま <code>Get()</code> に渡すだけです。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/users/42</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#cc99cc;">if </span><span style="color:#d3d0c8;">(res) {
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">body </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// User ID: 42
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/users/42</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// User ID: 42
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/users/42&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// User ID: 42
</span><span style="color:#323232;">}
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#d3d0c8;"> http://localhost:8080/users/42
</span><span style="color:#747369;"># User ID: 42
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#4f5b66;"> http://localhost:8080/users/42
</span><span style="color:#a7adba;"># User ID: 42
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl http://localhost:8080/users/42
</span><span style="font-style:italic;color:#969896;"># User ID: 42
</span></pre>
</div>
</div></div>
<p>テスト用サーバーには、正規表現でIDを数字のみに絞った <code>/files/(\d+)</code> もあります。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/files/42</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#cc99cc;">if </span><span style="color:#d3d0c8;">(res) {
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">body </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// File ID: 42
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/files/42</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// File ID: 42
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/files/42&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// File ID: 42
</span><span style="color:#323232;">}
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#d3d0c8;"> http://localhost:8080/files/42
</span><span style="color:#747369;"># File ID: 42
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#4f5b66;"> http://localhost:8080/files/42
</span><span style="color:#a7adba;"># File ID: 42
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl http://localhost:8080/files/42
</span><span style="font-style:italic;color:#969896;"># File ID: 42
</span></pre>
</div>
</div></div>
<p><code>/files/abc</code> のように数字以外を渡すと404が返ります。仕組みは次章で解説します。</p>
<h2>リクエストヘッダー</h2>
<p>カスタムHTTPヘッダーを付けるには、<code>httplib::Headers</code> を渡します。<code>Get()</code><code>Post()</code> のどちらでも使えます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/hi</span><span style="color:#d3d0c8;">&quot;, httplib::Headers{
</span><span style="color:#d3d0c8;"> {&quot;</span><span style="color:#99cc99;">Authorization</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">Bearer my-token</span><span style="color:#d3d0c8;">&quot;}
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;, httplib::Headers{
</span><span style="color:#4f5b66;"> {&quot;</span><span style="color:#a3be8c;">Authorization</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">Bearer my-token</span><span style="color:#4f5b66;">&quot;}
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">, httplib::Headers{
</span><span style="color:#323232;"> {</span><span style="color:#183691;">&quot;Authorization&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;Bearer my-token&quot;</span><span style="color:#323232;">}
</span><span style="color:#323232;">});
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -H </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">Authorization: Bearer my-token</span><span style="color:#d3d0c8;">&quot; http://localhost:8080/hi
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -H </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">Authorization: Bearer my-token</span><span style="color:#4f5b66;">&quot; http://localhost:8080/hi
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -H </span><span style="color:#183691;">&quot;Authorization: Bearer my-token&quot;</span><span style="color:#323232;"> http://localhost:8080/hi
</span></pre>
</div>
</div></div>
<h2>POSTリクエスト</h2>
<p>テキストデータをPOSTしてみましょう。<code>Post()</code> の第2引数にボディ、第3引数にContent-Typeを指定します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/post</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">Hello, Server!</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#cc99cc;">if </span><span style="color:#d3d0c8;">(res) {
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">status </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// 200
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">body </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// Hello, Server!
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/post</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">Hello, Server!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// 200
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// Hello, Server!
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Post(</span><span style="color:#183691;">&quot;/post&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;Hello, Server!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// 200
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// Hello, Server!
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>テスト用サーバーの <code>/post</code> はボディをそのまま返すので、送った文字列がそのまま返ってきます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -X</span><span style="color:#d3d0c8;"> POST</span><span style="color:#f2777a;"> -H </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">Content-Type: text/plain</span><span style="color:#d3d0c8;">&quot;</span><span style="color:#f2777a;"> -d </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">Hello, Server!</span><span style="color:#d3d0c8;">&quot; http://localhost:8080/post
</span><span style="color:#747369;"># Hello, Server!
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -X</span><span style="color:#4f5b66;"> POST</span><span style="color:#bf616a;"> -H </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">Content-Type: text/plain</span><span style="color:#4f5b66;">&quot;</span><span style="color:#bf616a;"> -d </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">Hello, Server!</span><span style="color:#4f5b66;">&quot; http://localhost:8080/post
</span><span style="color:#a7adba;"># Hello, Server!
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -X POST -H </span><span style="color:#183691;">&quot;Content-Type: text/plain&quot;</span><span style="color:#323232;"> -d </span><span style="color:#183691;">&quot;Hello, Server!&quot;</span><span style="color:#323232;"> http://localhost:8080/post
</span><span style="font-style:italic;color:#969896;"># Hello, Server!
</span></pre>
</div>
</div></div>
<h2>フォームデータの送信</h2>
<p>HTMLフォームのように、キーと値のペアを送ることもできます。<code>httplib::Params</code> を使います。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/submit</span><span style="color:#d3d0c8;">&quot;, httplib::Params{
</span><span style="color:#d3d0c8;"> {&quot;</span><span style="color:#99cc99;">name</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">Alice</span><span style="color:#d3d0c8;">&quot;},
</span><span style="color:#d3d0c8;"> {&quot;</span><span style="color:#99cc99;">age</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">30</span><span style="color:#d3d0c8;">&quot;}
@@ -404,29 +404,29 @@
</span><span style="color:#d3d0c8;"> </span><span style="color:#747369;">// name = Alice
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/submit</span><span style="color:#4f5b66;">&quot;, httplib::Params{
</span><span style="color:#4f5b66;"> {&quot;</span><span style="color:#a3be8c;">name</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">Alice</span><span style="color:#4f5b66;">&quot;},
</span><span style="color:#4f5b66;"> {&quot;</span><span style="color:#a3be8c;">age</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">30</span><span style="color:#4f5b66;">&quot;}
</span><span style="color:#4f5b66;">});
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// age = 30
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// name = Alice
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Post(</span><span style="color:#183691;">&quot;/submit&quot;</span><span style="color:#323232;">, httplib::Params{
</span><span style="color:#323232;"> {</span><span style="color:#183691;">&quot;name&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;Alice&quot;</span><span style="color:#323232;">},
</span><span style="color:#323232;"> {</span><span style="color:#183691;">&quot;age&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;30&quot;</span><span style="color:#323232;">}
</span><span style="color:#323232;">});
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// age = 30
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// name = Alice
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>これは <code>application/x-www-form-urlencoded</code> 形式で送信されます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -X</span><span style="color:#d3d0c8;"> POST</span><span style="color:#f2777a;"> -d </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">name=Alice&amp;age=30</span><span style="color:#d3d0c8;">&quot; http://localhost:8080/submit
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -X</span><span style="color:#4f5b66;"> POST</span><span style="color:#bf616a;"> -d </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">name=Alice&amp;age=30</span><span style="color:#4f5b66;">&quot; http://localhost:8080/submit
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -X POST -d </span><span style="color:#183691;">&quot;name=Alice&amp;age=30&quot;</span><span style="color:#323232;"> http://localhost:8080/submit
</span></pre>
</div>
</div></div>
<h2>ファイルのPOST</h2>
<p>ファイルをアップロードするには、<code>httplib::UploadFormDataItems</code> を使ってマルチパートフォームデータとして送信します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/upload</span><span style="color:#d3d0c8;">&quot;, httplib::UploadFormDataItems{
</span><span style="color:#d3d0c8;"> {&quot;</span><span style="color:#99cc99;">file</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">Hello, File!</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">hello.txt</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;}
</span><span style="color:#d3d0c8;">});
@@ -434,26 +434,26 @@
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">body </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// hello.txt (12 bytes)
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/upload</span><span style="color:#4f5b66;">&quot;, httplib::UploadFormDataItems{
</span><span style="color:#4f5b66;"> {&quot;</span><span style="color:#a3be8c;">file</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">Hello, File!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">hello.txt</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;}
</span><span style="color:#4f5b66;">});
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// hello.txt (12 bytes)
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Post(</span><span style="color:#183691;">&quot;/upload&quot;</span><span style="color:#323232;">, httplib::UploadFormDataItems{
</span><span style="color:#323232;"> {</span><span style="color:#183691;">&quot;file&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;Hello, File!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;hello.txt&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">}
</span><span style="color:#323232;">});
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// hello.txt (12 bytes)
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p><code>UploadFormDataItems</code> の各要素は <code>{name, content, filename, content_type}</code> の4つのフィールドで構成されます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -F </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">file=Hello, File!;filename=hello.txt;type=text/plain</span><span style="color:#d3d0c8;">&quot; http://localhost:8080/upload
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -F </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">file=Hello, File!;filename=hello.txt;type=text/plain</span><span style="color:#4f5b66;">&quot; http://localhost:8080/upload
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -F </span><span style="color:#183691;">&quot;file=Hello, File!;filename=hello.txt;type=text/plain&quot;</span><span style="color:#323232;"> http://localhost:8080/upload
</span></pre>
</div>
</div></div>
<h2>エラーハンドリング</h2>
<p>ネットワーク通信では、サーバーに接続できない場合があります。<code>res</code> が有効かどうかを必ず確認しましょう。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">http://localhost:9999</span><span style="color:#d3d0c8;">&quot;); </span><span style="color:#747369;">// 存在しないポート
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/hi</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
@@ -472,26 +472,26 @@
</span><span style="color:#d3d0c8;">
</span><span style="color:#d3d0c8;">std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">body </span><span style="color:#d3d0c8;">&lt;&lt; std::endl;
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost:9999</span><span style="color:#4f5b66;">&quot;); </span><span style="color:#a7adba;">// 存在しないポート
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(!res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// 接続エラー
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Error: </span><span style="color:#4f5b66;">&quot; &lt;&lt; </span><span style="color:#8fa1b3;">httplib::to_string</span><span style="color:#4f5b66;">(res.</span><span style="color:#8fa1b3;">error</span><span style="color:#4f5b66;">()) &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// Error: Connection
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return </span><span style="color:#d08770;">1</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;">}
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;">// ここに到達すればレスポンスを受信できている
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">!= </span><span style="color:#d08770;">200</span><span style="color:#4f5b66;">) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">HTTP Error: </span><span style="color:#4f5b66;">&quot; &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return </span><span style="color:#d08770;">1</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;">}
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl;
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;http://localhost:9999&quot;</span><span style="color:#323232;">); </span><span style="font-style:italic;color:#969896;">// 存在しないポート
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(</span><span style="font-weight:bold;color:#a71d5d;">!</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// 接続エラー
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Error: &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#323232;">httplib::to_string(res.error()) </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// Error: Connection
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return </span><span style="color:#0086b3;">1</span><span style="color:#323232;">;
</span><span style="color:#323232;">}
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;">// ここに到達すればレスポンスを受信できている
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">!= </span><span style="color:#0086b3;">200</span><span style="color:#323232;">) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;HTTP Error: &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return </span><span style="color:#0086b3;">1</span><span style="color:#323232;">;
</span><span style="color:#323232;">}
</span><span style="color:#323232;">
</span><span style="color:#323232;">std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span></pre>
</div>
</div></div>
<p>エラーには2つのレベルがあります。</p>
<ul>
<li><strong>接続エラー</strong>: サーバーに到達できなかった場合。<code>res</code> が偽になり、<code>res.error()</code> でエラーの種類を取得できます</li>

View File

@@ -105,110 +105,110 @@
<p>前章ではクライアントからリクエストを送りました。そのとき、テスト用サーバーを用意しましたね。この章では、あのサーバーの仕組みをひとつずつ紐解いていきます。</p>
<h2>サーバーの起動</h2>
<p>ルーティングを登録したら、最後に <code>svr.listen()</code> を呼んでサーバーを起動します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8080</span><span style="color:#d3d0c8;">);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8080</span><span style="color:#4f5b66;">);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8080</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<p>第1引数はホスト、第2引数はポート番号です。<code>"0.0.0.0"</code> を指定すると、すべてのネットワークインターフェースでリクエストを受け付けます。自分のマシンからのアクセスだけに限定したいときは <code>"127.0.0.1"</code> を使います。</p>
<p><code>listen()</code> はブロッキング呼び出しです。サーバーが停止するまで、この行から先には進みません。ターミナルで <code>Ctrl+C</code> を押すか、別スレッドから <code>svr.stop()</code> を呼ぶまでサーバーは動き続けます。</p>
<h2>ルーティング</h2>
<p>サーバーの核になるのは「ルーティング」です。どのURLに、どのHTTPメソッドでアクセスされたら、何をするか。それを登録する仕組みです。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Server svr;
</span><span style="color:#d3d0c8;">
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/hi</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const</span><span style="color:#d3d0c8;"> httplib::Request &amp;req, httplib::Response &amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Hello!</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Server svr;
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::Request &amp;req, httplib::Response &amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Server svr;
</span><span style="color:#323232;">
</span><span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::Request </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">req, httplib::Response </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>svr.Get()</code> は、GETリクエストに対するハンドラーを登録します。第1引数がパス、第2引数がハンドラー関数です。<code>/hi</code> にGETリクエストが来たら、このラムダが呼ばれます。</p>
<p>HTTPメソッドごとにメソッドが用意されています。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/path</span><span style="color:#d3d0c8;">&quot;, handler); </span><span style="color:#747369;">// GET
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/path</span><span style="color:#d3d0c8;">&quot;, handler); </span><span style="color:#747369;">// POST
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Put</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/path</span><span style="color:#d3d0c8;">&quot;, handler); </span><span style="color:#747369;">// PUT
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Delete</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/path</span><span style="color:#d3d0c8;">&quot;, handler); </span><span style="color:#747369;">// DELETE
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/path</span><span style="color:#4f5b66;">&quot;, handler); </span><span style="color:#a7adba;">// GET
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/path</span><span style="color:#4f5b66;">&quot;, handler); </span><span style="color:#a7adba;">// POST
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Put</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/path</span><span style="color:#4f5b66;">&quot;, handler); </span><span style="color:#a7adba;">// PUT
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Delete</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/path</span><span style="color:#4f5b66;">&quot;, handler); </span><span style="color:#a7adba;">// DELETE
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/path&quot;</span><span style="color:#323232;">, handler); </span><span style="font-style:italic;color:#969896;">// GET
</span><span style="color:#323232;">svr.Post(</span><span style="color:#183691;">&quot;/path&quot;</span><span style="color:#323232;">, handler); </span><span style="font-style:italic;color:#969896;">// POST
</span><span style="color:#323232;">svr.Put(</span><span style="color:#183691;">&quot;/path&quot;</span><span style="color:#323232;">, handler); </span><span style="font-style:italic;color:#969896;">// PUT
</span><span style="color:#323232;">svr.Delete(</span><span style="color:#183691;">&quot;/path&quot;</span><span style="color:#323232;">, handler); </span><span style="font-style:italic;color:#969896;">// DELETE
</span></pre>
</div>
</div></div>
<p>ハンドラーのシグネチャは <code>(const httplib::Request &amp;req, httplib::Response &amp;res)</code> です。<code>auto</code> を使って短く書くこともできます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/hi</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Hello!</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>パスが一致したときだけハンドラーが呼ばれます。登録されていないパスにアクセスすると、自動的に404が返ります。</p>
<h2>リクエストオブジェクト</h2>
<p>ハンドラーの第1引数 <code>req</code> から、クライアントが送ってきた情報を読み取れます。</p>
<h3>ボディ</h3>
<p><code>req.body</code> でリクエストボディを取得できます。型は <code>std::string</code> です。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/post</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#747369;">// クライアントが送ったボディをそのまま返す
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(req.</span><span style="color:#f2777a;">body</span><span style="color:#d3d0c8;">, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/post</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// クライアントが送ったボディをそのまま返す
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(req.</span><span style="color:#bf616a;">body</span><span style="color:#4f5b66;">, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Post(</span><span style="color:#183691;">&quot;/post&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// クライアントが送ったボディをそのまま返す
</span><span style="color:#323232;"> res.set_content(req.body, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h3>ヘッダー</h3>
<p><code>req.get_header_value()</code> でリクエストヘッダーの値を取得できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/check</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> auth = req.</span><span style="color:#6699cc;">get_header_value</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Authorization</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Auth: </span><span style="color:#d3d0c8;">&quot; + auth, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/check</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> auth = req.</span><span style="color:#8fa1b3;">get_header_value</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Authorization</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Auth: </span><span style="color:#4f5b66;">&quot; + auth, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/check&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> auth </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.get_header_value(</span><span style="color:#183691;">&quot;Authorization&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Auth: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> auth, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h3>クエリパラメーターとフォームデータ</h3>
<p><code>req.get_param_value()</code> でパラメーターを取得できます。GETのクエリパラメーターと、POSTのフォームデータの両方に使えます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/search</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> q = req.</span><span style="color:#6699cc;">get_param_value</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">q</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Query: </span><span style="color:#d3d0c8;">&quot; + q, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/search</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> q = req.</span><span style="color:#8fa1b3;">get_param_value</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">q</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Query: </span><span style="color:#4f5b66;">&quot; + q, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/search&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> q </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.get_param_value(</span><span style="color:#183691;">&quot;q&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Query: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> q, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>/search?q=cpp-httplib</code> にアクセスすると、<code>q</code> の値は <code>"cpp-httplib"</code> になります。</p>
<p>すべてのパラメーターをループで処理したいときは、<code>req.params</code> を使います。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/submit</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> std::string result;
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">for </span><span style="color:#d3d0c8;">(</span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;[key, val] : req.</span><span style="color:#f2777a;">params</span><span style="color:#d3d0c8;">) {
@@ -217,174 +217,174 @@
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(result, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/submit</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> std::string result;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">for </span><span style="color:#4f5b66;">(</span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;[key, val] : req.</span><span style="color:#bf616a;">params</span><span style="color:#4f5b66;">) {
</span><span style="color:#4f5b66;"> result += key + &quot;</span><span style="color:#a3be8c;"> = </span><span style="color:#4f5b66;">&quot; + val + &quot;</span><span style="color:#96b5b4;">\n</span><span style="color:#4f5b66;">&quot;;
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(result, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Post(</span><span style="color:#183691;">&quot;/submit&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> std::string result;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">for </span><span style="color:#323232;">(</span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">[key, val] </span><span style="font-weight:bold;color:#a71d5d;">:</span><span style="color:#323232;"> req.params) {
</span><span style="color:#323232;"> result </span><span style="font-weight:bold;color:#a71d5d;">+=</span><span style="color:#323232;"> key </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; = &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> val </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot;</span><span style="color:#0086b3;">\n</span><span style="color:#183691;">&quot;</span><span style="color:#323232;">;
</span><span style="color:#323232;"> }
</span><span style="color:#323232;"> res.set_content(result, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h3>ファイルアップロード</h3>
<p>マルチパートフォームでアップロードされたファイルは、<code>req.form.get_file()</code> で取得します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/upload</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> f = req.</span><span style="color:#f2777a;">form</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">get_file</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">file</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> content = f.</span><span style="color:#f2777a;">filename </span><span style="color:#d3d0c8;">+ &quot;</span><span style="color:#99cc99;"> (</span><span style="color:#d3d0c8;">&quot; + </span><span style="color:#6699cc;">std::to_string</span><span style="color:#d3d0c8;">(f.</span><span style="color:#f2777a;">content</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">size</span><span style="color:#d3d0c8;">()) + &quot;</span><span style="color:#99cc99;"> bytes)</span><span style="color:#d3d0c8;">&quot;;
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(content, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/upload</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> f = req.</span><span style="color:#bf616a;">form</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">get_file</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">file</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> content = f.</span><span style="color:#bf616a;">filename </span><span style="color:#4f5b66;">+ &quot;</span><span style="color:#a3be8c;"> (</span><span style="color:#4f5b66;">&quot; + </span><span style="color:#8fa1b3;">std::to_string</span><span style="color:#4f5b66;">(f.</span><span style="color:#bf616a;">content</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">size</span><span style="color:#4f5b66;">()) + &quot;</span><span style="color:#a3be8c;"> bytes)</span><span style="color:#4f5b66;">&quot;;
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(content, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Post(</span><span style="color:#183691;">&quot;/upload&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> f </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.form.get_file(</span><span style="color:#183691;">&quot;file&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> content </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> f.filename </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; (&quot; </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#323232;">std::to_string(f.content.size()) </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; bytes)&quot;</span><span style="color:#323232;">;
</span><span style="color:#323232;"> res.set_content(content, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>f.filename</code> でファイル名、<code>f.content</code> でファイルの中身にアクセスできます。</p>
<h2>パスパラメーター</h2>
<p>URLの一部を変数として受け取りたいことがあります。たとえば <code>/users/42</code><code>42</code> を取得したい場合です。<code>:param</code> 記法を使うと、URLの一部をキャプチャできます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/users/:id</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> id = req.</span><span style="color:#f2777a;">path_params</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">at</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">id</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">User ID: </span><span style="color:#d3d0c8;">&quot; + id, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/users/:id</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> id = req.</span><span style="color:#bf616a;">path_params</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">at</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">id</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">User ID: </span><span style="color:#4f5b66;">&quot; + id, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/users/:id&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.path_params.at(</span><span style="color:#183691;">&quot;id&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;User ID: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> id, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>/users/42</code> にアクセスすると、<code>req.path_params.at("id")</code><code>"42"</code> を返します。<code>/users/100</code> なら <code>"100"</code> です。</p>
<p>複数のパスパラメーターも使えます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/users/:user_id/posts/:post_id</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> user_id = req.</span><span style="color:#f2777a;">path_params</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">at</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">user_id</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> post_id = req.</span><span style="color:#f2777a;">path_params</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">at</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">post_id</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">User: </span><span style="color:#d3d0c8;">&quot; + user_id + &quot;</span><span style="color:#99cc99;">, Post: </span><span style="color:#d3d0c8;">&quot; + post_id, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/users/:user_id/posts/:post_id</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> user_id = req.</span><span style="color:#bf616a;">path_params</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">at</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">user_id</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> post_id = req.</span><span style="color:#bf616a;">path_params</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">at</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">post_id</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">User: </span><span style="color:#4f5b66;">&quot; + user_id + &quot;</span><span style="color:#a3be8c;">, Post: </span><span style="color:#4f5b66;">&quot; + post_id, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/users/:user_id/posts/:post_id&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> user_id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.path_params.at(</span><span style="color:#183691;">&quot;user_id&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> post_id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.path_params.at(</span><span style="color:#183691;">&quot;post_id&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;User: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> user_id </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot;, Post: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> post_id, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h3>正規表現パターン</h3>
<p><code>:param</code> の代わりに正規表現をパスに書くこともできます。キャプチャグループの値は <code>req.matches</code> で取得します。型は <code>std::smatch</code> です。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#747369;">// 数字のみのIDを受け付ける
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(</span><span style="color:#cc99cc;">R</span><span style="color:#d3d0c8;">&quot;(</span><span style="color:#99cc99;">/files/(\d+)</span><span style="color:#d3d0c8;">)&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> id = req.</span><span style="color:#f2777a;">matches</span><span style="color:#d3d0c8;">[</span><span style="color:#f99157;">1</span><span style="color:#d3d0c8;">]; </span><span style="color:#747369;">// 最初のキャプチャグループ
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">File ID: </span><span style="color:#d3d0c8;">&quot; + </span><span style="color:#6699cc;">std::string</span><span style="color:#d3d0c8;">(id), &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#a7adba;">// 数字のみのIDを受け付ける
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(</span><span style="color:#b48ead;">R</span><span style="color:#4f5b66;">&quot;(</span><span style="color:#a3be8c;">/files/(\d+)</span><span style="color:#4f5b66;">)&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> id = req.</span><span style="color:#bf616a;">matches</span><span style="color:#4f5b66;">[</span><span style="color:#d08770;">1</span><span style="color:#4f5b66;">]; </span><span style="color:#a7adba;">// 最初のキャプチャグループ
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">File ID: </span><span style="color:#4f5b66;">&quot; + </span><span style="color:#8fa1b3;">std::string</span><span style="color:#4f5b66;">(id), &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-style:italic;color:#969896;">// 数字のみのIDを受け付ける
</span><span style="color:#323232;">svr.Get(</span><span style="font-weight:bold;color:#a71d5d;">R</span><span style="color:#183691;">&quot;(/files/(\d+))&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.matches[</span><span style="color:#0086b3;">1</span><span style="color:#323232;">]; </span><span style="font-style:italic;color:#969896;">// 最初のキャプチャグループ
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;File ID: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#323232;">std::string(id), </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>/files/42</code> にはマッチしますが、<code>/files/abc</code> にはマッチしません。入力値を絞り込みたいときに便利です。</p>
<h2>レスポンスの組み立て</h2>
<p>ハンドラーの第2引数 <code>res</code> を使って、クライアントに返すレスポンスを組み立てます。</p>
<h3>ボディとContent-Type</h3>
<p><code>res.set_content()</code> でボディとContent-Typeを設定します。これだけでステータスコード200のレスポンスが返ります。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/hi</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Hello!</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h3>ステータスコード</h3>
<p>ステータスコードを変えたいときは、<code>res.status</code> に代入します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/not-found</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#f2777a;">status </span><span style="color:#d3d0c8;">= </span><span style="color:#f99157;">404</span><span style="color:#d3d0c8;">;
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Not found</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/not-found</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">= </span><span style="color:#d08770;">404</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Not found</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/not-found&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.status </span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#0086b3;">404</span><span style="color:#323232;">;
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Not found&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h3>レスポンスヘッダー</h3>
<p><code>res.set_header()</code> でレスポンスヘッダーを追加できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/with-header</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_header</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">X-Custom</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">my-value</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Hello!</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/with-header</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_header</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">X-Custom</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">my-value</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/with-header&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_header(</span><span style="color:#183691;">&quot;X-Custom&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;my-value&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h2>前章のサーバーを読み解く</h2>
<p>ここまでの知識を使って、前章で用意したテスト用サーバーを改めて見てみましょう。</p>
<h3>GET /hi</h3>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/hi</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Hello!</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/hi</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/hi&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>最もシンプルなハンドラーです。リクエストの情報は使わないので、<code>req</code> の変数名を省略しています。<code>"Hello!"</code> というテキストをそのまま返します。</p>
<h3>GET /search</h3>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/search</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> q = req.</span><span style="color:#6699cc;">get_param_value</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">q</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Query: </span><span style="color:#d3d0c8;">&quot; + q, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/search</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> q = req.</span><span style="color:#8fa1b3;">get_param_value</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">q</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Query: </span><span style="color:#4f5b66;">&quot; + q, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/search&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> q </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.get_param_value(</span><span style="color:#183691;">&quot;q&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Query: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> q, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>req.get_param_value("q")</code> でクエリパラメーター <code>q</code> の値を取り出します。<code>/search?q=cpp-httplib</code> なら、レスポンスは <code>"Query: cpp-httplib"</code> になります。</p>
<h3>POST /post</h3>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/post</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(req.</span><span style="color:#f2777a;">body</span><span style="color:#d3d0c8;">, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/post</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(req.</span><span style="color:#bf616a;">body</span><span style="color:#4f5b66;">, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Post(</span><span style="color:#183691;">&quot;/post&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(req.body, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>クライアントが送ったリクエストボディを、そのままレスポンスとして返すエコーサーバーです。<code>req.body</code> にボディが丸ごと入っています。</p>
<h3>POST /submit</h3>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/submit</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> std::string result;
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">for </span><span style="color:#d3d0c8;">(</span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;[key, val] : req.</span><span style="color:#f2777a;">params</span><span style="color:#d3d0c8;">) {
@@ -393,63 +393,63 @@
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(result, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/submit</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> std::string result;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">for </span><span style="color:#4f5b66;">(</span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;[key, val] : req.</span><span style="color:#bf616a;">params</span><span style="color:#4f5b66;">) {
</span><span style="color:#4f5b66;"> result += key + &quot;</span><span style="color:#a3be8c;"> = </span><span style="color:#4f5b66;">&quot; + val + &quot;</span><span style="color:#96b5b4;">\n</span><span style="color:#4f5b66;">&quot;;
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(result, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Post(</span><span style="color:#183691;">&quot;/submit&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> std::string result;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">for </span><span style="color:#323232;">(</span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">[key, val] </span><span style="font-weight:bold;color:#a71d5d;">:</span><span style="color:#323232;"> req.params) {
</span><span style="color:#323232;"> result </span><span style="font-weight:bold;color:#a71d5d;">+=</span><span style="color:#323232;"> key </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; = &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> val </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot;</span><span style="color:#0086b3;">\n</span><span style="color:#183691;">&quot;</span><span style="color:#323232;">;
</span><span style="color:#323232;"> }
</span><span style="color:#323232;"> res.set_content(result, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>フォームデータとして送られたキーと値のペアを、<code>req.params</code> でループ処理しています。構造化束縛 <code>auto &amp;[key, val]</code> を使って、各ペアを取り出しています。</p>
<h3>POST /upload</h3>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/upload</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> f = req.</span><span style="color:#f2777a;">form</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">get_file</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">file</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> content = f.</span><span style="color:#f2777a;">filename </span><span style="color:#d3d0c8;">+ &quot;</span><span style="color:#99cc99;"> (</span><span style="color:#d3d0c8;">&quot; + </span><span style="color:#6699cc;">std::to_string</span><span style="color:#d3d0c8;">(f.</span><span style="color:#f2777a;">content</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">size</span><span style="color:#d3d0c8;">()) + &quot;</span><span style="color:#99cc99;"> bytes)</span><span style="color:#d3d0c8;">&quot;;
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(content, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/upload</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> f = req.</span><span style="color:#bf616a;">form</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">get_file</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">file</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> content = f.</span><span style="color:#bf616a;">filename </span><span style="color:#4f5b66;">+ &quot;</span><span style="color:#a3be8c;"> (</span><span style="color:#4f5b66;">&quot; + </span><span style="color:#8fa1b3;">std::to_string</span><span style="color:#4f5b66;">(f.</span><span style="color:#bf616a;">content</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">size</span><span style="color:#4f5b66;">()) + &quot;</span><span style="color:#a3be8c;"> bytes)</span><span style="color:#4f5b66;">&quot;;
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(content, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Post(</span><span style="color:#183691;">&quot;/upload&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> f </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.form.get_file(</span><span style="color:#183691;">&quot;file&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> content </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> f.filename </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; (&quot; </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#323232;">std::to_string(f.content.size()) </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#183691;">&quot; bytes)&quot;</span><span style="color:#323232;">;
</span><span style="color:#323232;"> res.set_content(content, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>マルチパートフォームで送られたファイルを受け取ります。<code>req.form.get_file("file")</code><code>"file"</code> という名前のフィールドを取得し、<code>f.filename</code><code>f.content.size()</code> でファイル名とサイズを返しています。</p>
<h3>GET /users/:id</h3>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/users/:id</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> id = req.</span><span style="color:#f2777a;">path_params</span><span style="color:#d3d0c8;">.</span><span style="color:#6699cc;">at</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">id</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">User ID: </span><span style="color:#d3d0c8;">&quot; + id, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/users/:id</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> id = req.</span><span style="color:#bf616a;">path_params</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">at</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">id</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">User ID: </span><span style="color:#4f5b66;">&quot; + id, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/users/:id&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.path_params.at(</span><span style="color:#183691;">&quot;id&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;User ID: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> id, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>:id</code> の部分がパスパラメーターです。<code>req.path_params.at("id")</code> で値を取り出しています。<code>/users/42</code> なら <code>"42"</code><code>/users/alice</code> なら <code>"alice"</code> が得られます。</p>
<h3>GET /files/(\d+)</h3>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(</span><span style="color:#cc99cc;">R</span><span style="color:#d3d0c8;">&quot;(</span><span style="color:#99cc99;">/files/(\d+)</span><span style="color:#d3d0c8;">)&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> id = req.</span><span style="color:#f2777a;">matches</span><span style="color:#d3d0c8;">[</span><span style="color:#f99157;">1</span><span style="color:#d3d0c8;">];
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">File ID: </span><span style="color:#d3d0c8;">&quot; + </span><span style="color:#6699cc;">std::string</span><span style="color:#d3d0c8;">(id), &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(</span><span style="color:#b48ead;">R</span><span style="color:#4f5b66;">&quot;(</span><span style="color:#a3be8c;">/files/(\d+)</span><span style="color:#4f5b66;">)&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> id = req.</span><span style="color:#bf616a;">matches</span><span style="color:#4f5b66;">[</span><span style="color:#d08770;">1</span><span style="color:#4f5b66;">];
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">File ID: </span><span style="color:#4f5b66;">&quot; + </span><span style="color:#8fa1b3;">std::string</span><span style="color:#4f5b66;">(id), &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.Get(</span><span style="font-weight:bold;color:#a71d5d;">R</span><span style="color:#183691;">&quot;(/files/(\d+))&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> id </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.matches[</span><span style="color:#0086b3;">1</span><span style="color:#323232;">];
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;File ID: &quot; </span><span style="font-weight:bold;color:#a71d5d;">+ </span><span style="color:#323232;">std::string(id), </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>正規表現 <code>(\d+)</code> で数字だけのIDにマッチします。<code>/files/42</code> にはマッチしますが、<code>/files/abc</code> は404になります。<code>req.matches[1]</code> で最初のキャプチャグループの値を取得しています。</p>
<h2>次のステップ</h2>
<p>サーバーの基本がわかりましたね。ルーティング、リクエストの読み取り、レスポンスの組み立て。これだけで、十分に実用的なAPIサーバーが作れます。</p>

View File

@@ -105,7 +105,7 @@
<p>cpp-httplibは、HTMLやCSS、画像ファイルなどの静的ファイルも配信できます。面倒な設定は要りません。<code>set_mount_point()</code> を1行呼ぶだけです。</p>
<h2>set_mount_point の基本</h2>
<p>さっそくやってみましょう。<code>set_mount_point()</code> は、URLのパスとローカルディレクトリを紐づけます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
</span><span style="color:#d3d0c8;">
@@ -118,29 +118,29 @@
</span><span style="color:#d3d0c8;"> svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8080</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Server svr;
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">set_mount_point</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">./html</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Listening on port 8080...</span><span style="color:#4f5b66;">&quot; &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8080</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Server svr;
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.set_mount_point(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;./html&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Listening on port 8080...&quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8080</span><span style="color:#323232;">);
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>第1引数がURLのマウントポイント、第2引数がローカルのディレクトリパスです。この例だと、<code>/</code> へのリクエストを <code>./html</code> ディレクトリから配信します。</p>
<p>試してみましょう。まず <code>html</code> ディレクトリを作って、<code>index.html</code> を置きます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">mkdir</span><span style="color:#d3d0c8;"> html
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">mkdir</span><span style="color:#4f5b66;"> html
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">mkdir html
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">&lt;!</span><span style="color:#f2777a;">DOCTYPE</span><span style="color:#d3d0c8;"> html&gt;
</span><span style="color:#d3d0c8;">&lt;</span><span style="color:#f2777a;">html</span><span style="color:#d3d0c8;">&gt;
</span><span style="color:#d3d0c8;">&lt;</span><span style="color:#f2777a;">head</span><span style="color:#d3d0c8;">&gt;&lt;</span><span style="color:#f2777a;">title</span><span style="color:#d3d0c8;">&gt;My Page&lt;/</span><span style="color:#f2777a;">title</span><span style="color:#d3d0c8;">&gt;&lt;/</span><span style="color:#f2777a;">head</span><span style="color:#d3d0c8;">&gt;
@@ -150,67 +150,67 @@
</span><span style="color:#d3d0c8;">&lt;/</span><span style="color:#f2777a;">body</span><span style="color:#d3d0c8;">&gt;
</span><span style="color:#d3d0c8;">&lt;/</span><span style="color:#f2777a;">html</span><span style="color:#d3d0c8;">&gt;
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">&lt;!</span><span style="color:#bf616a;">DOCTYPE</span><span style="color:#4f5b66;"> html&gt;
</span><span style="color:#4f5b66;">&lt;</span><span style="color:#bf616a;">html</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">&lt;</span><span style="color:#bf616a;">head</span><span style="color:#4f5b66;">&gt;&lt;</span><span style="color:#bf616a;">title</span><span style="color:#4f5b66;">&gt;My Page&lt;/</span><span style="color:#bf616a;">title</span><span style="color:#4f5b66;">&gt;&lt;/</span><span style="color:#bf616a;">head</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">&lt;</span><span style="color:#bf616a;">body</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;"> &lt;</span><span style="color:#bf616a;">h1</span><span style="color:#4f5b66;">&gt;Hello from cpp-httplib!&lt;/</span><span style="color:#bf616a;">h1</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;"> &lt;</span><span style="color:#bf616a;">p</span><span style="color:#4f5b66;">&gt;This is a static file.&lt;/</span><span style="color:#bf616a;">p</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">&lt;/</span><span style="color:#bf616a;">body</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">&lt;/</span><span style="color:#bf616a;">html</span><span style="color:#4f5b66;">&gt;
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">&lt;!</span><span style="color:#63a35c;">DOCTYPE</span><span style="color:#323232;"> html&gt;
</span><span style="color:#323232;">&lt;</span><span style="color:#63a35c;">html</span><span style="color:#323232;">&gt;
</span><span style="color:#323232;">&lt;</span><span style="color:#63a35c;">head</span><span style="color:#323232;">&gt;&lt;</span><span style="color:#63a35c;">title</span><span style="color:#323232;">&gt;My Page&lt;/</span><span style="color:#63a35c;">title</span><span style="color:#323232;">&gt;&lt;/</span><span style="color:#63a35c;">head</span><span style="color:#323232;">&gt;
</span><span style="color:#323232;">&lt;</span><span style="color:#63a35c;">body</span><span style="color:#323232;">&gt;
</span><span style="color:#323232;"> &lt;</span><span style="color:#63a35c;">h1</span><span style="color:#323232;">&gt;Hello from cpp-httplib!&lt;/</span><span style="color:#63a35c;">h1</span><span style="color:#323232;">&gt;
</span><span style="color:#323232;"> &lt;</span><span style="color:#63a35c;">p</span><span style="color:#323232;">&gt;This is a static file.&lt;/</span><span style="color:#63a35c;">p</span><span style="color:#323232;">&gt;
</span><span style="color:#323232;">&lt;/</span><span style="color:#63a35c;">body</span><span style="color:#323232;">&gt;
</span><span style="color:#323232;">&lt;/</span><span style="color:#63a35c;">html</span><span style="color:#323232;">&gt;
</span></pre>
</div>
</div></div>
<p>コンパイルして起動します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">g++</span><span style="color:#f2777a;"> -std</span><span style="color:#d3d0c8;">=c++17</span><span style="color:#f2777a;"> -o</span><span style="color:#d3d0c8;"> server server.cpp</span><span style="color:#f2777a;"> -pthread
</span><span style="color:#6699cc;">./server
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">g++</span><span style="color:#bf616a;"> -std</span><span style="color:#4f5b66;">=c++17</span><span style="color:#bf616a;"> -o</span><span style="color:#4f5b66;"> server server.cpp</span><span style="color:#bf616a;"> -pthread
</span><span style="color:#8fa1b3;">./server
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">g++ -std</span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;">c++17 -o server server.cpp -pthread
</span><span style="color:#323232;">./server
</span></pre>
</div>
</div></div>
<p>ブラウザで <code>http://localhost:8080</code> を開いてみてください。<code>html/index.html</code> の内容が表示されるはずです。<code>http://localhost:8080/index.html</code> でも同じページが返ります。</p>
<p>もちろん、前章のクライアントコードや <code>curl</code> でもアクセスできますよ。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">http://localhost:8080</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#cc99cc;">if </span><span style="color:#d3d0c8;">(res) {
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">body </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// HTMLが表示される
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost:8080</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// HTMLが表示される
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;http://localhost:8080&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// HTMLが表示される
</span><span style="color:#323232;">}
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#d3d0c8;"> http://localhost:8080
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#4f5b66;"> http://localhost:8080
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl http://localhost:8080
</span></pre>
</div>
</div></div>
<h2>複数のマウントポイント</h2>
<p><code>set_mount_point()</code> は何回でも呼べます。URLのパスごとに、別々のディレクトリを割り当てられます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_mount_point</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">./public</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_mount_point</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/assets</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">./static/assets</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_mount_point</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/docs</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">./documentation</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_mount_point</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">./public</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_mount_point</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/assets</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">./static/assets</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_mount_point</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/docs</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">./documentation</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.set_mount_point(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;./public&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">svr.set_mount_point(</span><span style="color:#183691;">&quot;/assets&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;./static/assets&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">svr.set_mount_point(</span><span style="color:#183691;">&quot;/docs&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;./documentation&quot;</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<p><code>/assets/style.css</code> なら <code>./static/assets/style.css</code> を、<code>/docs/guide.html</code> なら <code>./documentation/guide.html</code> を配信します。</p>
<h2>ハンドラーとの組み合わせ</h2>
<p>静的ファイルの配信と、前章で学んだルーティングハンドラーは共存できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Server svr;
</span><span style="color:#d3d0c8;">
</span><span style="color:#747369;">// APIエンドポイント
@@ -223,38 +223,38 @@
</span><span style="color:#d3d0c8;">
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8080</span><span style="color:#d3d0c8;">);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Server svr;
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;">// APIエンドポイント
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/api/hello</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(</span><span style="color:#b48ead;">R</span><span style="color:#4f5b66;">&quot;(</span><span style="color:#a3be8c;">{&quot;message&quot;:&quot;Hello!&quot;}</span><span style="color:#4f5b66;">)&quot;, &quot;</span><span style="color:#a3be8c;">application/json</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;">// 静的ファイル配信
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_mount_point</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">./public</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8080</span><span style="color:#4f5b66;">);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Server svr;
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;">// APIエンドポイント
</span><span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/api/hello&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="font-weight:bold;color:#a71d5d;">R</span><span style="color:#183691;">&quot;({&quot;message&quot;:&quot;Hello!&quot;})&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;application/json&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;">// 静的ファイル配信
</span><span style="color:#323232;">svr.set_mount_point(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;./public&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;">svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8080</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<p>ハンドラーが先に評価されます。<code>/api/hello</code> にはハンドラーが応答し、それ以外のパスは <code>./public</code> ディレクトリからファイルを探します。</p>
<h2>レスポンスヘッダーの追加</h2>
<p><code>set_mount_point()</code> の第3引数にヘッダーを渡すと、静的ファイルのレスポンスにカスタムヘッダーを付けられます。キャッシュ制御に便利です。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_mount_point</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">./public</span><span style="color:#d3d0c8;">&quot;, {
</span><span style="color:#d3d0c8;"> {&quot;</span><span style="color:#99cc99;">Cache-Control</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">max-age=3600</span><span style="color:#d3d0c8;">&quot;}
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_mount_point</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">./public</span><span style="color:#4f5b66;">&quot;, {
</span><span style="color:#4f5b66;"> {&quot;</span><span style="color:#a3be8c;">Cache-Control</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">max-age=3600</span><span style="color:#4f5b66;">&quot;}
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.set_mount_point(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;./public&quot;</span><span style="color:#323232;">, {
</span><span style="color:#323232;"> {</span><span style="color:#183691;">&quot;Cache-Control&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;max-age=3600&quot;</span><span style="color:#323232;">}
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>こうすると、ブラウザは配信されたファイルを1時間キャッシュします。</p>
<h2>静的ファイルサーバー用のDockerファイル</h2>
<p>cpp-httplibのリポジトリには、静的ファイルサーバー用の <code>Dockerfile</code> が含まれています。Docker Hubにビルド済みイメージも公開しているので、1コマンドで起動できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">&gt; docker run</span><span style="color:#f2777a;"> -p</span><span style="color:#d3d0c8;"> 8080:80</span><span style="color:#f2777a;"> -v</span><span style="color:#d3d0c8;"> ./my-site:/html yhirose4dockerhub/cpp-httplib-server
</span><span style="color:#6699cc;">Serving</span><span style="color:#d3d0c8;"> HTTP on 0.0.0.0:80
</span><span style="color:#6699cc;">Mount</span><span style="color:#d3d0c8;"> point: / -&gt; ./html
@@ -263,16 +263,16 @@
</span><span style="color:#6699cc;">192.168.65.1</span><span style="color:#d3d0c8;"> - - </span><span style="color:#cc99cc;">[</span><span style="color:#d3d0c8;">22/Feb/2026:12:00:00 +0000</span><span style="color:#cc99cc;">] </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">GET /style.css HTTP/1.1</span><span style="color:#d3d0c8;">&quot; 200 1024 &quot;</span><span style="color:#99cc99;">-</span><span style="color:#d3d0c8;">&quot; &quot;</span><span style="color:#99cc99;">Mozilla/5.0 ...</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#6699cc;">192.168.65.1</span><span style="color:#d3d0c8;"> - - </span><span style="color:#cc99cc;">[</span><span style="color:#d3d0c8;">22/Feb/2026:12:00:01 +0000</span><span style="color:#cc99cc;">] </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">GET /favicon.ico HTTP/1.1</span><span style="color:#d3d0c8;">&quot; 404 152 &quot;</span><span style="color:#99cc99;">-</span><span style="color:#d3d0c8;">&quot; &quot;</span><span style="color:#99cc99;">Mozilla/5.0 ...</span><span style="color:#d3d0c8;">&quot;
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">&gt; docker run</span><span style="color:#bf616a;"> -p</span><span style="color:#4f5b66;"> 8080:80</span><span style="color:#bf616a;"> -v</span><span style="color:#4f5b66;"> ./my-site:/html yhirose4dockerhub/cpp-httplib-server
</span><span style="color:#8fa1b3;">Serving</span><span style="color:#4f5b66;"> HTTP on 0.0.0.0:80
</span><span style="color:#8fa1b3;">Mount</span><span style="color:#4f5b66;"> point: / -&gt; ./html
</span><span style="color:#8fa1b3;">Press</span><span style="color:#4f5b66;"> Ctrl+C to shutdown gracefully...
</span><span style="color:#8fa1b3;">192.168.65.1</span><span style="color:#4f5b66;"> - - </span><span style="color:#b48ead;">[</span><span style="color:#4f5b66;">22/Feb/2026:12:00:00 +0000</span><span style="color:#b48ead;">] </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">GET / HTTP/1.1</span><span style="color:#4f5b66;">&quot; 200 256 &quot;</span><span style="color:#a3be8c;">-</span><span style="color:#4f5b66;">&quot; &quot;</span><span style="color:#a3be8c;">Mozilla/5.0 ...</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#8fa1b3;">192.168.65.1</span><span style="color:#4f5b66;"> - - </span><span style="color:#b48ead;">[</span><span style="color:#4f5b66;">22/Feb/2026:12:00:00 +0000</span><span style="color:#b48ead;">] </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">GET /style.css HTTP/1.1</span><span style="color:#4f5b66;">&quot; 200 1024 &quot;</span><span style="color:#a3be8c;">-</span><span style="color:#4f5b66;">&quot; &quot;</span><span style="color:#a3be8c;">Mozilla/5.0 ...</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#8fa1b3;">192.168.65.1</span><span style="color:#4f5b66;"> - - </span><span style="color:#b48ead;">[</span><span style="color:#4f5b66;">22/Feb/2026:12:00:01 +0000</span><span style="color:#b48ead;">] </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">GET /favicon.ico HTTP/1.1</span><span style="color:#4f5b66;">&quot; 404 152 &quot;</span><span style="color:#a3be8c;">-</span><span style="color:#4f5b66;">&quot; &quot;</span><span style="color:#a3be8c;">Mozilla/5.0 ...</span><span style="color:#4f5b66;">&quot;
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">&gt;</span><span style="color:#323232;"> docker run -p 8080:80 -v ./my-site:/html yhirose4dockerhub/cpp-httplib-server
</span><span style="color:#323232;">Serving HTTP on 0.0.0.0:80
</span><span style="color:#323232;">Mount point: / -</span><span style="font-weight:bold;color:#a71d5d;">&gt;</span><span style="color:#323232;"> ./html
</span><span style="color:#323232;">Press Ctrl+C to shutdown gracefully...
</span><span style="color:#323232;">192.168.65.1 - - </span><span style="font-weight:bold;color:#a71d5d;">[</span><span style="color:#323232;">22/Feb/2026:12:00:00 +0000</span><span style="font-weight:bold;color:#a71d5d;">] </span><span style="color:#183691;">&quot;GET / HTTP/1.1&quot;</span><span style="color:#323232;"> 200 256 </span><span style="color:#183691;">&quot;-&quot; &quot;Mozilla/5.0 ...&quot;
</span><span style="color:#323232;">192.168.65.1 - - </span><span style="font-weight:bold;color:#a71d5d;">[</span><span style="color:#323232;">22/Feb/2026:12:00:00 +0000</span><span style="font-weight:bold;color:#a71d5d;">] </span><span style="color:#183691;">&quot;GET /style.css HTTP/1.1&quot;</span><span style="color:#323232;"> 200 1024 </span><span style="color:#183691;">&quot;-&quot; &quot;Mozilla/5.0 ...&quot;
</span><span style="color:#323232;">192.168.65.1 - - </span><span style="font-weight:bold;color:#a71d5d;">[</span><span style="color:#323232;">22/Feb/2026:12:00:01 +0000</span><span style="font-weight:bold;color:#a71d5d;">] </span><span style="color:#183691;">&quot;GET /favicon.ico HTTP/1.1&quot;</span><span style="color:#323232;"> 404 152 </span><span style="color:#183691;">&quot;-&quot; &quot;Mozilla/5.0 ...&quot;
</span></pre>
</div>
</div></div>
<p><code>./my-site</code> ディレクトリの中身が、そのままポート8080で配信されます。NGINXと同じログ形式で、アクセスの様子を確認できますよ。</p>
<h2>次のステップ</h2>
<p>静的ファイルの配信ができるようになりましたね。HTMLやCSS、JavaScriptを配信するWebサーバーが、これだけのコードで作れます。</p>

View File

@@ -113,7 +113,7 @@
</tbody></table>
<h2>コンパイルオプション</h2>
<p>TLS機能を有効にするには、<code>CPPHTTPLIB_OPENSSL_SUPPORT</code> マクロを定義してコンパイルします。前章までのコンパイルコマンドに、いくつかオプションが増えます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#747369;"># macOS (Homebrew)
</span><span style="color:#6699cc;">clang++</span><span style="color:#f2777a;"> -std</span><span style="color:#d3d0c8;">=c++17</span><span style="color:#f2777a;"> -DCPPHTTPLIB_OPENSSL_SUPPORT </span><span style="color:#d3d0c8;">\
</span><span style="color:#f2777a;"> -I</span><span style="color:#d3d0c8;">$</span><span style="color:#f2777a;">(</span><span style="color:#6699cc;">brew</span><span style="color:#f2777a;"> --prefix openssl)</span><span style="color:#d3d0c8;">/include \
@@ -130,24 +130,24 @@
</span><span style="color:#747369;"># Windows (Developer Command Prompt)
</span><span style="color:#6699cc;">cl</span><span style="color:#d3d0c8;"> /EHsc /std:c++17 /DCPPHTTPLIB_OPENSSL_SUPPORT server.cpp libssl.lib libcrypto.lib
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#a7adba;"># macOS (Homebrew)
</span><span style="color:#8fa1b3;">clang++</span><span style="color:#bf616a;"> -std</span><span style="color:#4f5b66;">=c++17</span><span style="color:#bf616a;"> -DCPPHTTPLIB_OPENSSL_SUPPORT </span><span style="color:#4f5b66;">\
</span><span style="color:#bf616a;"> -I</span><span style="color:#4f5b66;">$</span><span style="color:#bf616a;">(</span><span style="color:#8fa1b3;">brew</span><span style="color:#bf616a;"> --prefix openssl)</span><span style="color:#4f5b66;">/include \
</span><span style="color:#bf616a;"> -L</span><span style="color:#4f5b66;">$</span><span style="color:#bf616a;">(</span><span style="color:#8fa1b3;">brew</span><span style="color:#bf616a;"> --prefix openssl)</span><span style="color:#4f5b66;">/lib \
</span><span style="color:#bf616a;"> -lssl -lcrypto </span><span style="color:#4f5b66;">\
</span><span style="color:#bf616a;"> -framework</span><span style="color:#4f5b66;"> CoreFoundation</span><span style="color:#bf616a;"> -framework</span><span style="color:#4f5b66;"> Security \
</span><span style="color:#bf616a;"> -o</span><span style="color:#4f5b66;"> server server.cpp
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;"># Linux
</span><span style="color:#8fa1b3;">clang++</span><span style="color:#bf616a;"> -std</span><span style="color:#4f5b66;">=c++17</span><span style="color:#bf616a;"> -pthread -DCPPHTTPLIB_OPENSSL_SUPPORT </span><span style="color:#4f5b66;">\
</span><span style="color:#bf616a;"> -lssl -lcrypto </span><span style="color:#4f5b66;">\
</span><span style="color:#bf616a;"> -o</span><span style="color:#4f5b66;"> server server.cpp
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;"># Windows (Developer Command Prompt)
</span><span style="color:#8fa1b3;">cl</span><span style="color:#4f5b66;"> /EHsc /std:c++17 /DCPPHTTPLIB_OPENSSL_SUPPORT server.cpp libssl.lib libcrypto.lib
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-style:italic;color:#969896;"># macOS (Homebrew)
</span><span style="color:#323232;">clang++ -std</span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;">c++17 -DCPPHTTPLIB_OPENSSL_SUPPORT \
</span><span style="color:#323232;"> -I$(brew --prefix openssl)/include \
</span><span style="color:#323232;"> -L$(brew --prefix openssl)/lib \
</span><span style="color:#323232;"> -lssl -lcrypto \
</span><span style="color:#323232;"> -framework CoreFoundation -framework Security \
</span><span style="color:#323232;"> -o server server.cpp
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Linux
</span><span style="color:#323232;">clang++ -std</span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;">c++17 -pthread -DCPPHTTPLIB_OPENSSL_SUPPORT \
</span><span style="color:#323232;"> -lssl -lcrypto \
</span><span style="color:#323232;"> -o server server.cpp
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;"># Windows (Developer Command Prompt)
</span><span style="color:#323232;">cl /EHsc /std:c++17 /DCPPHTTPLIB_OPENSSL_SUPPORT server.cpp libssl.lib libcrypto.lib
</span></pre>
</div>
</div></div>
<p>それぞれのオプションの役割を見てみましょう。</p>
<ul>
<li><strong><code>-DCPPHTTPLIB_OPENSSL_SUPPORT</code></strong> — TLS機能を有効にするマクロ定義</li>
@@ -157,7 +157,7 @@
</ul>
<h2>動作確認</h2>
<p>ちゃんと動くか確認してみましょう。<code>httplib::Client</code> にHTTPSのURLを渡してアクセスするだけのプログラムです。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#define </span><span style="color:#d3d0c8;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
@@ -173,23 +173,23 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#define </span><span style="color:#4f5b66;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://www.google.com</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Status: </span><span style="color:#4f5b66;">&quot; &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> } </span><span style="color:#b48ead;">else </span><span style="color:#4f5b66;">{
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Error: </span><span style="color:#4f5b66;">&quot; &lt;&lt; </span><span style="color:#8fa1b3;">httplib::to_string</span><span style="color:#4f5b66;">(res.</span><span style="color:#8fa1b3;">error</span><span style="color:#4f5b66;">()) &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#define </span><span style="color:#323232;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Client cli(</span><span style="color:#183691;">&quot;https://www.google.com&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Status: &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> } </span><span style="font-weight:bold;color:#a71d5d;">else </span><span style="color:#323232;">{
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Error: &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#323232;">httplib::to_string(res.error()) </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>コンパイルして実行してみてください。<code>Status: 200</code> と表示されれば、セットアップ完了です。</p>
<h2>他のTLSバックエンド</h2>
<p>cpp-httplibはOpenSSL以外にも、Mbed TLSとwolfSSLに対応しています。マクロ定義とリンクするライブラリを変えるだけで切り替えられます。</p>

View File

@@ -105,7 +105,7 @@
<p>前章でOpenSSLのセットアップが済んだので、さっそくHTTPSクライアントを使ってみましょう。2章で使った <code>httplib::Client</code> がそのまま使えます。コンストラクタに <code>https://</code> 付きのURLを渡すだけです。</p>
<h2>GETリクエスト</h2>
<p>実在するHTTPSサイトにアクセスしてみましょう。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#define </span><span style="color:#d3d0c8;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
@@ -122,91 +122,91 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#define </span><span style="color:#4f5b66;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://nghttp2.org</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// 200
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">substr</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">0</span><span style="color:#4f5b66;">, </span><span style="color:#d08770;">100</span><span style="color:#4f5b66;">) &lt;&lt; std::endl; </span><span style="color:#a7adba;">// HTMLの先頭部分
</span><span style="color:#4f5b66;"> } </span><span style="color:#b48ead;">else </span><span style="color:#4f5b66;">{
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Error: </span><span style="color:#4f5b66;">&quot; &lt;&lt; </span><span style="color:#8fa1b3;">httplib::to_string</span><span style="color:#4f5b66;">(res.</span><span style="color:#8fa1b3;">error</span><span style="color:#4f5b66;">()) &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#define </span><span style="color:#323232;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Client cli(</span><span style="color:#183691;">&quot;https://nghttp2.org&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// 200
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body.substr(</span><span style="color:#0086b3;">0</span><span style="color:#323232;">, </span><span style="color:#0086b3;">100</span><span style="color:#323232;">) </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// HTMLの先頭部分
</span><span style="color:#323232;"> } </span><span style="font-weight:bold;color:#a71d5d;">else </span><span style="color:#323232;">{
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Error: &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#323232;">httplib::to_string(res.error()) </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>2章では <code>httplib::Client cli("http://localhost:8080")</code> と書きましたよね。スキームを <code>https://</code> に変えるだけです。<code>Get()</code><code>Post()</code> など、2章で学んだAPIはすべてそのまま使えます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#d3d0c8;"> https://nghttp2.org/
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#4f5b66;"> https://nghttp2.org/
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl https://nghttp2.org/
</span></pre>
</div>
</div></div>
<h2>ポートの指定</h2>
<p>HTTPSのデフォルトポートは443です。別のポートを使いたい場合は、URLにポートを含めます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://localhost:8443</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://localhost:8443</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://localhost:8443&quot;</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<h2>CA証明書の検証</h2>
<p><code>httplib::Client</code> はHTTPS接続時、デフォルトでサーバー証明書を検証します。信頼できるCA認証局が発行した証明書を持つサーバーにしか接続しません。</p>
<p>CA証明書は、macOSならKeychain、LinuxならシステムのCA証明書ストア、WindowsならWindowsの証明書ストアから自動で読み込みます。ほとんどの場合、追加の設定は要りません。</p>
<h3>CA証明書ファイルの指定</h3>
<p>環境によってはシステムのCA証明書が見つからないこともあります。そのときは <code>set_ca_cert_path()</code> でパスを直接指定してください。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://nghttp2.org</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_ca_cert_path</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/etc/ssl/certs/ca-certificates.crt</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://nghttp2.org</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_ca_cert_path</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/etc/ssl/certs/ca-certificates.crt</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://nghttp2.org&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_ca_cert_path(</span><span style="color:#183691;">&quot;/etc/ssl/certs/ca-certificates.crt&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> --cacert</span><span style="color:#d3d0c8;"> /etc/ssl/certs/ca-certificates.crt https://nghttp2.org/
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> --cacert</span><span style="color:#4f5b66;"> /etc/ssl/certs/ca-certificates.crt https://nghttp2.org/
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl --cacert /etc/ssl/certs/ca-certificates.crt https://nghttp2.org/
</span></pre>
</div>
</div></div>
<h3>証明書検証の無効化</h3>
<p>開発中、自己署名証明書のサーバーに接続したいときは、検証を無効にできます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://localhost:8443</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">enable_server_certificate_verification</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">false</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://localhost:8443</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">enable_server_certificate_verification</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">false</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://localhost:8443&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.enable_server_certificate_verification(</span><span style="color:#0086b3;">false</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -k</span><span style="color:#d3d0c8;"> https://localhost:8443/
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -k</span><span style="color:#4f5b66;"> https://localhost:8443/
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -k https://localhost:8443/
</span></pre>
</div>
</div></div>
<p>本番では絶対に無効にしないでください。中間者攻撃のリスクがあります。</p>
<h2>リダイレクトの追跡</h2>
<p>HTTPSサイトへのアクセスでは、リダイレクトに遭遇することがよくあります。たとえば <code>http://</code> から <code>https://</code> へ、あるいは <code>www</code> なしから <code>www</code> ありへ転送されるケースです。</p>
<p>デフォルトではリダイレクトを追跡しません。リダイレクト先は <code>Location</code> ヘッダーで確認できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://nghttp2.org</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/httpbin/redirect/3</span><span style="color:#d3d0c8;">&quot;);
@@ -215,24 +215,24 @@
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#6699cc;">get_header_value</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Location</span><span style="color:#d3d0c8;">&quot;) &lt;&lt; std::endl;
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://nghttp2.org</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/httpbin/redirect/3</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// 302
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#8fa1b3;">get_header_value</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Location</span><span style="color:#4f5b66;">&quot;) &lt;&lt; std::endl;
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://nghttp2.org&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/httpbin/redirect/3&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// 302
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;get_header_value(</span><span style="color:#183691;">&quot;Location&quot;</span><span style="color:#323232;">) </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;">}
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#d3d0c8;"> https://nghttp2.org/httpbin/redirect/3
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#4f5b66;"> https://nghttp2.org/httpbin/redirect/3
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl https://nghttp2.org/httpbin/redirect/3
</span></pre>
</div>
</div></div>
<p><code>set_follow_location(true)</code> を設定すると、リダイレクトを自動で追跡して、最終的なレスポンスを返してくれます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://nghttp2.org</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_follow_location</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">true</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">
@@ -241,22 +241,22 @@
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#f2777a;">status </span><span style="color:#d3d0c8;">&lt;&lt; std::endl; </span><span style="color:#747369;">// 200最終的なレスポンス
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://nghttp2.org</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_follow_location</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">true</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/httpbin/redirect/3</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// 200最終的なレスポンス
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://nghttp2.org&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_follow_location(</span><span style="color:#0086b3;">true</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/httpbin/redirect/3&quot;</span><span style="color:#323232;">);
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// 200最終的なレスポンス
</span><span style="color:#323232;">}
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -L</span><span style="color:#d3d0c8;"> https://nghttp2.org/httpbin/redirect/3
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -L</span><span style="color:#4f5b66;"> https://nghttp2.org/httpbin/redirect/3
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -L https://nghttp2.org/httpbin/redirect/3
</span></pre>
</div>
</div></div>
<h2>次のステップ</h2>
<p>HTTPSクライアントの使い方がわかりましたね。次は自分でHTTPSサーバーを立ててみましょう。自己署名証明書の作り方から始めます。</p>
<p><strong>次:</strong> <a href="../07-https-server">HTTPS Server</a></p>

View File

@@ -106,13 +106,13 @@
<p>ただし、TLSサーバーにはサーバー証明書と秘密鍵が必要です。まずはそこから準備しましょう。</p>
<h2>自己署名証明書の作成</h2>
<p>開発やテスト用なら、自己署名証明書いわゆるオレオレ証明書で十分です。OpenSSLのコマンドでサクッと作れます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">openssl</span><span style="color:#d3d0c8;"> req</span><span style="color:#f2777a;"> -x509 -noenc -keyout</span><span style="color:#d3d0c8;"> key.pem</span><span style="color:#f2777a;"> -out</span><span style="color:#d3d0c8;"> cert.pem</span><span style="color:#f2777a;"> -subj</span><span style="color:#d3d0c8;"> /CN=localhost
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">openssl</span><span style="color:#4f5b66;"> req</span><span style="color:#bf616a;"> -x509 -noenc -keyout</span><span style="color:#4f5b66;"> key.pem</span><span style="color:#bf616a;"> -out</span><span style="color:#4f5b66;"> cert.pem</span><span style="color:#bf616a;"> -subj</span><span style="color:#4f5b66;"> /CN=localhost
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">openssl req -x509 -noenc -keyout key.pem -out cert.pem -subj /CN=localhost
</span></pre>
</div>
</div></div>
<p>これで2つのファイルができます。</p>
<ul>
<li><strong><code>cert.pem</code></strong> — サーバー証明書</li>
@@ -120,7 +120,7 @@
</ul>
<h2>最小のHTTPSサーバー</h2>
<p>証明書ができたら、さっそくサーバーを書いてみましょう。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#define </span><span style="color:#d3d0c8;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
@@ -136,42 +136,42 @@
</span><span style="color:#d3d0c8;"> svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8443</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#define </span><span style="color:#4f5b66;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::SSLServer </span><span style="color:#8fa1b3;">svr</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">cert.pem</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">key.pem</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello, HTTPS!</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Listening on https://localhost:8443</span><span style="color:#4f5b66;">&quot; &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8443</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#define </span><span style="color:#323232;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::SSLServer svr(</span><span style="color:#183691;">&quot;cert.pem&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;key.pem&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello, HTTPS!&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Listening on https://localhost:8443&quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8443</span><span style="color:#323232;">);
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p><code>httplib::SSLServer</code> のコンストラクタに証明書と秘密鍵のパスを渡すだけです。ルーティングの書き方は3章の <code>httplib::Server</code> とまったく同じですよ。</p>
<p>コンパイルして起動しましょう。</p>
<h2>動作確認</h2>
<p>サーバーが起動したら、<code>curl</code> でアクセスしてみましょう。自己署名証明書なので、<code>-k</code> オプションで証明書検証をスキップします。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#6699cc;">curl</span><span style="color:#f2777a;"> -k</span><span style="color:#d3d0c8;"> https://localhost:8443/
</span><span style="color:#747369;"># Hello, HTTPS!
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#8fa1b3;">curl</span><span style="color:#bf616a;"> -k</span><span style="color:#4f5b66;"> https://localhost:8443/
</span><span style="color:#a7adba;"># Hello, HTTPS!
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">curl -k https://localhost:8443/
</span><span style="font-style:italic;color:#969896;"># Hello, HTTPS!
</span></pre>
</div>
</div></div>
<p>ブラウザで <code>https://localhost:8443</code> を開くと、「この接続は安全ではありません」と警告が出ます。自己署名証明書なので正常です。気にせず進めてください。</p>
<h2>クライアントからの接続</h2>
<p>前章の <code>httplib::Client</code> で接続してみましょう。自己署名証明書のサーバーに接続するには、2つの方法があります。</p>
<h3>方法1: 証明書検証を無効にする</h3>
<p>開発時の手軽な方法です。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#define </span><span style="color:#d3d0c8;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
@@ -186,25 +186,25 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#define </span><span style="color:#4f5b66;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://localhost:8443</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> cli.</span><span style="color:#8fa1b3;">enable_server_certificate_verification</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">false</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// Hello, HTTPS!
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#define </span><span style="color:#323232;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Client cli(</span><span style="color:#183691;">&quot;https://localhost:8443&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> cli.enable_server_certificate_verification(</span><span style="color:#0086b3;">false</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// Hello, HTTPS!
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<h3>方法2: 自己署名証明書をCA証明書として指定する</h3>
<p>こちらのほうが安全です。<code>cert.pem</code> をCA証明書として信頼するよう指定します。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#define </span><span style="color:#d3d0c8;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
@@ -219,22 +219,22 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#define </span><span style="color:#4f5b66;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://localhost:8443</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> cli.</span><span style="color:#8fa1b3;">set_ca_cert_path</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">cert.pem</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; res-&gt;</span><span style="color:#bf616a;">body </span><span style="color:#4f5b66;">&lt;&lt; std::endl; </span><span style="color:#a7adba;">// Hello, HTTPS!
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#define </span><span style="color:#323232;">CPPHTTPLIB_OPENSSL_SUPPORT
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Client cli(</span><span style="color:#183691;">&quot;https://localhost:8443&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> cli.set_ca_cert_path(</span><span style="color:#183691;">&quot;cert.pem&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res-&gt;body </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// Hello, HTTPS!
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>この方法なら、指定した証明書のサーバーにだけ接続を許可して、なりすましを防げます。テスト環境でもなるべくこちらを使いましょう。</p>
<h2>Server と SSLServer の比較</h2>
<p>3章で学んだ <code>httplib::Server</code> のAPIは、<code>httplib::SSLServer</code> でもそのまま使えます。違いはコンストラクタだけです。</p>

View File

@@ -106,7 +106,7 @@
<p>さっそく、エコーサーバーとクライアントを作ってみましょう。</p>
<h2>エコーサーバー</h2>
<p>受け取ったメッセージをそのまま返すエコーサーバーです。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
</span><span style="color:#d3d0c8;">
@@ -124,30 +124,30 @@
</span><span style="color:#d3d0c8;"> svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8080</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::Server svr;
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">WebSocket</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/ws</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::Request &amp;, httplib::ws::WebSocket &amp;ws) {
</span><span style="color:#4f5b66;"> std::string msg;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">while </span><span style="color:#4f5b66;">(ws.</span><span style="color:#8fa1b3;">read</span><span style="color:#4f5b66;">(msg)) {
</span><span style="color:#4f5b66;"> ws.</span><span style="color:#8fa1b3;">send</span><span style="color:#4f5b66;">(msg); </span><span style="color:#a7adba;">// 受け取ったメッセージをそのまま返す
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Listening on port 8080...</span><span style="color:#4f5b66;">&quot; &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8080</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::Server svr;
</span><span style="color:#323232;">
</span><span style="color:#323232;"> svr.WebSocket(</span><span style="color:#183691;">&quot;/ws&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::Request </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">, httplib::ws::WebSocket </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">ws) {
</span><span style="color:#323232;"> std::string msg;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">while </span><span style="color:#323232;">(ws.read(msg)) {
</span><span style="color:#323232;"> ws.send(msg); </span><span style="font-style:italic;color:#969896;">// 受け取ったメッセージをそのまま返す
</span><span style="color:#323232;"> }
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Listening on port 8080...&quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8080</span><span style="color:#323232;">);
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p><code>svr.WebSocket()</code> でWebSocketハンドラーを登録します。3章の <code>svr.Get()</code><code>svr.Post()</code> と同じ感覚ですね。</p>
<p>ハンドラーの中では、<code>ws.read(msg)</code> でメッセージを待ちます。接続が閉じられると <code>read()</code><code>false</code> を返すので、ループを抜けます。<code>ws.send(msg)</code> でメッセージを送り返します。</p>
<h2>クライアントからの接続</h2>
<p><code>httplib::ws::WebSocketClient</code> を使ってサーバーに接続してみましょう。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&quot;</span><span style="color:#99cc99;">httplib.h</span><span style="color:#d3d0c8;">&quot;
</span><span style="color:#cc99cc;">#include </span><span style="color:#d3d0c8;">&lt;</span><span style="color:#99cc99;">iostream</span><span style="color:#d3d0c8;">&gt;
</span><span style="color:#d3d0c8;">
@@ -171,35 +171,35 @@
</span><span style="color:#d3d0c8;"> client.</span><span style="color:#6699cc;">close</span><span style="color:#d3d0c8;">();
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&quot;</span><span style="color:#a3be8c;">httplib.h</span><span style="color:#4f5b66;">&quot;
</span><span style="color:#b48ead;">#include </span><span style="color:#4f5b66;">&lt;</span><span style="color:#a3be8c;">iostream</span><span style="color:#4f5b66;">&gt;
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">int </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> httplib::ws::WebSocketClient </span><span style="color:#8fa1b3;">client</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">ws://localhost:8080/ws</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(!client.</span><span style="color:#8fa1b3;">connect</span><span style="color:#4f5b66;">()) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; &quot;</span><span style="color:#a3be8c;">Connection failed</span><span style="color:#4f5b66;">&quot; &lt;&lt; std::endl;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return </span><span style="color:#d08770;">1</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// メッセージを送信
</span><span style="color:#4f5b66;"> client.</span><span style="color:#8fa1b3;">send</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello, WebSocket!</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// サーバーからの応答を受信
</span><span style="color:#4f5b66;"> std::string msg;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(client.</span><span style="color:#8fa1b3;">read</span><span style="color:#4f5b66;">(msg)) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; msg &lt;&lt; std::endl; </span><span style="color:#a7adba;">// Hello, WebSocket!
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> client.</span><span style="color:#8fa1b3;">close</span><span style="color:#4f5b66;">();
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&quot;httplib.h&quot;
</span><span style="font-weight:bold;color:#a71d5d;">#include </span><span style="color:#183691;">&lt;iostream&gt;
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">int </span><span style="font-weight:bold;color:#795da3;">main</span><span style="color:#323232;">() {
</span><span style="color:#323232;"> httplib::ws::WebSocketClient client(</span><span style="color:#183691;">&quot;ws://localhost:8080/ws&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(</span><span style="font-weight:bold;color:#a71d5d;">!</span><span style="color:#323232;">client.connect()) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;Connection failed&quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return </span><span style="color:#0086b3;">1</span><span style="color:#323232;">;
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// メッセージを送信
</span><span style="color:#323232;"> client.send(</span><span style="color:#183691;">&quot;Hello, WebSocket!&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// サーバーからの応答を受信
</span><span style="color:#323232;"> std::string msg;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(client.read(msg)) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> msg </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl; </span><span style="font-style:italic;color:#969896;">// Hello, WebSocket!
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">
</span><span style="color:#323232;"> client.close();
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p>コンストラクタには <code>ws://host:port/path</code> 形式のURLを渡します。<code>connect()</code> で接続を開始し、<code>send()</code><code>read()</code> でメッセージをやり取りします。</p>
<h2>テキストとバイナリ</h2>
<p>WebSocketにはテキストとバイナリの2種類のメッセージがあります。<code>read()</code> の戻り値で区別できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">WebSocket</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/ws</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const</span><span style="color:#d3d0c8;"> httplib::Request &amp;, httplib::ws::WebSocket &amp;ws) {
</span><span style="color:#d3d0c8;"> std::string msg;
</span><span style="color:#d3d0c8;"> httplib::ws::ReadResult ret;
@@ -212,20 +212,20 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">WebSocket</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/ws</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::Request &amp;, httplib::ws::WebSocket &amp;ws) {
</span><span style="color:#4f5b66;"> std::string msg;
</span><span style="color:#4f5b66;"> httplib::ws::ReadResult ret;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">while </span><span style="color:#4f5b66;">((ret = ws.</span><span style="color:#8fa1b3;">read</span><span style="color:#4f5b66;">(msg))) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(ret == httplib::ws::Binary) {
</span><span style="color:#4f5b66;"> ws.</span><span style="color:#8fa1b3;">send</span><span style="color:#4f5b66;">(msg.</span><span style="color:#8fa1b3;">data</span><span style="color:#4f5b66;">(), msg.</span><span style="color:#8fa1b3;">size</span><span style="color:#4f5b66;">()); </span><span style="color:#a7adba;">// バイナリとして送信
</span><span style="color:#4f5b66;"> } </span><span style="color:#b48ead;">else </span><span style="color:#4f5b66;">{
</span><span style="color:#4f5b66;"> ws.</span><span style="color:#8fa1b3;">send</span><span style="color:#4f5b66;">(msg); </span><span style="color:#a7adba;">// テキストとして送信
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.WebSocket(</span><span style="color:#183691;">&quot;/ws&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::Request </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">, httplib::ws::WebSocket </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">ws) {
</span><span style="color:#323232;"> std::string msg;
</span><span style="color:#323232;"> httplib::ws::ReadResult ret;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">while </span><span style="color:#323232;">((ret </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> ws.read(msg))) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(ret </span><span style="font-weight:bold;color:#a71d5d;">==</span><span style="color:#323232;"> httplib::ws::Binary) {
</span><span style="color:#323232;"> ws.send(msg.data(), msg.size()); </span><span style="font-style:italic;color:#969896;">// バイナリとして送信
</span><span style="color:#323232;"> } </span><span style="font-weight:bold;color:#a71d5d;">else </span><span style="color:#323232;">{
</span><span style="color:#323232;"> ws.send(msg); </span><span style="font-style:italic;color:#969896;">// テキストとして送信
</span><span style="color:#323232;"> }
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<ul>
<li><code>ws.send(const std::string &amp;)</code> — テキストメッセージとして送信</li>
<li><code>ws.send(const char *, size_t)</code> — バイナリメッセージとして送信</li>
@@ -233,7 +233,7 @@
<p>クライアント側も同じAPIです。</p>
<h2>リクエスト情報へのアクセス</h2>
<p>ハンドラーの第1引数 <code>req</code> から、ハンドシェイク時のHTTPリクエスト情報を読み取れます。認証トークンの確認などに便利です。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">WebSocket</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/ws</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const</span><span style="color:#d3d0c8;"> httplib::Request &amp;req, httplib::ws::WebSocket &amp;ws) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> token = req.</span><span style="color:#6699cc;">get_header_value</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Authorization</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">if </span><span style="color:#d3d0c8;">(token.</span><span style="color:#6699cc;">empty</span><span style="color:#d3d0c8;">()) {
@@ -247,24 +247,24 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">WebSocket</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/ws</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::Request &amp;req, httplib::ws::WebSocket &amp;ws) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> token = req.</span><span style="color:#8fa1b3;">get_header_value</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Authorization</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(token.</span><span style="color:#8fa1b3;">empty</span><span style="color:#4f5b66;">()) {
</span><span style="color:#4f5b66;"> ws.</span><span style="color:#8fa1b3;">close</span><span style="color:#4f5b66;">(httplib::ws::CloseStatus::PolicyViolation, &quot;</span><span style="color:#a3be8c;">unauthorized</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;"> std::string msg;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">while </span><span style="color:#4f5b66;">(ws.</span><span style="color:#8fa1b3;">read</span><span style="color:#4f5b66;">(msg)) {
</span><span style="color:#4f5b66;"> ws.</span><span style="color:#8fa1b3;">send</span><span style="color:#4f5b66;">(msg);
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.WebSocket(</span><span style="color:#183691;">&quot;/ws&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::Request </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">req, httplib::ws::WebSocket </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">ws) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> token </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> req.get_header_value(</span><span style="color:#183691;">&quot;Authorization&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(token.empty()) {
</span><span style="color:#323232;"> ws.close(httplib::ws::CloseStatus::PolicyViolation, </span><span style="color:#183691;">&quot;unauthorized&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return</span><span style="color:#323232;">;
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">
</span><span style="color:#323232;"> std::string msg;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">while </span><span style="color:#323232;">(ws.read(msg)) {
</span><span style="color:#323232;"> ws.send(msg);
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h2>WSSで使う</h2>
<p>HTTPS上のWebSocketWSSにも対応しています。サーバー側は <code>httplib::SSLServer</code> にWebSocketハンドラーを登録するだけです。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::SSLServer </span><span style="color:#6699cc;">svr</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">cert.pem</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">key.pem</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">WebSocket</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/ws</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const</span><span style="color:#d3d0c8;"> httplib::Request &amp;, httplib::ws::WebSocket &amp;ws) {
@@ -276,27 +276,27 @@
</span><span style="color:#d3d0c8;">
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">0.0.0.0</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8443</span><span style="color:#d3d0c8;">);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::SSLServer </span><span style="color:#8fa1b3;">svr</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">cert.pem</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">key.pem</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">WebSocket</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/ws</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::Request &amp;, httplib::ws::WebSocket &amp;ws) {
</span><span style="color:#4f5b66;"> std::string msg;
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">while </span><span style="color:#4f5b66;">(ws.</span><span style="color:#8fa1b3;">read</span><span style="color:#4f5b66;">(msg)) {
</span><span style="color:#4f5b66;"> ws.</span><span style="color:#8fa1b3;">send</span><span style="color:#4f5b66;">(msg);
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">});
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">0.0.0.0</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8443</span><span style="color:#4f5b66;">);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::SSLServer </span><span style="font-weight:bold;color:#795da3;">svr</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;cert.pem&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;key.pem&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;">svr.WebSocket(</span><span style="color:#183691;">&quot;/ws&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::Request </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">, httplib::ws::WebSocket </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">ws) {
</span><span style="color:#323232;"> std::string msg;
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">while </span><span style="color:#323232;">(ws.read(msg)) {
</span><span style="color:#323232;"> ws.send(msg);
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">});
</span><span style="color:#323232;">
</span><span style="color:#323232;">svr.listen(</span><span style="color:#183691;">&quot;0.0.0.0&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8443</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<p>クライアント側は <code>wss://</code> スキームを使います。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::ws::WebSocketClient </span><span style="color:#6699cc;">client</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">wss://localhost:8443/ws</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::ws::WebSocketClient </span><span style="color:#8fa1b3;">client</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">wss://localhost:8443/ws</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::ws::WebSocketClient </span><span style="font-weight:bold;color:#795da3;">client</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;wss://localhost:8443/ws&quot;</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<h2>次のステップ</h2>
<p>WebSocketの基本がわかりましたね。ここまでで Tourは終わりです。</p>
<p>次のページでは、Tourで取り上げなかった機能をまとめて紹介します。</p>

View File

@@ -105,7 +105,7 @@
<p>Tourお疲れさまでした cpp-httplibの基本はひと通り押さえましたね。でも、まだまだ便利な機能があります。Tourで取り上げなかった機能をカテゴリー別に紹介します。</p>
<h2>Streaming API</h2>
<p>LLMのストリーミング応答や大きなファイルのダウンロードでは、レスポンス全体をメモリに載せたくないですよね。<code>stream::Get()</code> を使えば、データをチャンクごとに処理できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">http://localhost:11434</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> result = </span><span style="color:#6699cc;">httplib::stream::Get</span><span style="color:#d3d0c8;">(cli, &quot;</span><span style="color:#99cc99;">/api/generate</span><span style="color:#d3d0c8;">&quot;);
@@ -116,20 +116,20 @@
</span><span style="color:#d3d0c8;"> }
</span><span style="color:#d3d0c8;">}
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost:11434</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> result = </span><span style="color:#8fa1b3;">httplib::stream::Get</span><span style="color:#4f5b66;">(cli, &quot;</span><span style="color:#a3be8c;">/api/generate</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">if </span><span style="color:#4f5b66;">(result) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">while </span><span style="color:#4f5b66;">(result.</span><span style="color:#8fa1b3;">next</span><span style="color:#4f5b66;">()) {
</span><span style="color:#4f5b66;"> std::cout.</span><span style="color:#8fa1b3;">write</span><span style="color:#4f5b66;">(result.</span><span style="color:#8fa1b3;">data</span><span style="color:#4f5b66;">(), result.</span><span style="color:#8fa1b3;">size</span><span style="color:#4f5b66;">());
</span><span style="color:#4f5b66;"> }
</span><span style="color:#4f5b66;">}
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;http://localhost:11434&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> result </span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#323232;">httplib::stream::Get(cli, </span><span style="color:#183691;">&quot;/api/generate&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">if </span><span style="color:#323232;">(result) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">while </span><span style="color:#323232;">(result.next()) {
</span><span style="color:#323232;"> std::cout.write(result.data(), result.size());
</span><span style="color:#323232;"> }
</span><span style="color:#323232;">}
</span></pre>
</div>
</div></div>
<p><code>Get()</code><code>content_receiver</code> コールバックを渡す方法もあります。こちらはKeep-Aliveと併用できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">http://localhost:8080</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/stream</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const char </span><span style="color:#d3d0c8;">*data, size_t len) {
@@ -137,17 +137,17 @@
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">return </span><span style="color:#f99157;">true</span><span style="color:#d3d0c8;">;
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost:8080</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/stream</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const char </span><span style="color:#4f5b66;">*data, size_t len) {
</span><span style="color:#4f5b66;"> std::cout.</span><span style="color:#8fa1b3;">write</span><span style="color:#4f5b66;">(data, len);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return </span><span style="color:#d08770;">true</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;http://localhost:8080&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;">cli.Get(</span><span style="color:#183691;">&quot;/stream&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const char *</span><span style="color:#323232;">data, </span><span style="color:#0086b3;">size_t</span><span style="color:#323232;"> len) {
</span><span style="color:#323232;"> std::cout.write(data, len);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return </span><span style="color:#0086b3;">true</span><span style="color:#323232;">;
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>サーバー側には <code>set_content_provider()</code><code>set_chunked_content_provider()</code> があります。サイズがわかっているなら前者、不明なら後者を使ってください。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#747369;">// サイズ指定ありContent-Length が設定される)
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/file</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> size = </span><span style="color:#6699cc;">get_file_size</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">large.bin</span><span style="color:#d3d0c8;">&quot;);
@@ -167,46 +167,46 @@
</span><span style="color:#d3d0c8;"> });
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#a7adba;">// サイズ指定ありContent-Length が設定される)
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/file</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> size = </span><span style="color:#8fa1b3;">get_file_size</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">large.bin</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content_provider</span><span style="color:#4f5b66;">(size, &quot;</span><span style="color:#a3be8c;">application/octet-stream</span><span style="color:#4f5b66;">&quot;,
</span><span style="color:#4f5b66;"> [](size_t offset, size_t length, httplib::DataSink &amp;sink) {
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// offset から length バイト分を送る
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return </span><span style="color:#d08770;">true</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">});
</span><span style="color:#4f5b66;">
</span><span style="color:#a7adba;">// サイズ不明Chunked Transfer Encoding
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/stream</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_chunked_content_provider</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;,
</span><span style="color:#4f5b66;"> [](size_t offset, httplib::DataSink &amp;sink) {
</span><span style="color:#4f5b66;"> sink.</span><span style="color:#8fa1b3;">write</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">chunk</span><span style="color:#96b5b4;">\n</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">6</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return </span><span style="color:#d08770;">true</span><span style="color:#4f5b66;">; </span><span style="color:#a7adba;">// falseを返すと終了
</span><span style="color:#4f5b66;"> });
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-style:italic;color:#969896;">// サイズ指定ありContent-Length が設定される)
</span><span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/file&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> size </span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#323232;">get_file_size(</span><span style="color:#183691;">&quot;large.bin&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> res.set_content_provider(size, </span><span style="color:#183691;">&quot;application/octet-stream&quot;</span><span style="color:#323232;">,
</span><span style="color:#323232;"> [](</span><span style="color:#0086b3;">size_t</span><span style="color:#323232;"> offset, </span><span style="color:#0086b3;">size_t</span><span style="color:#323232;"> length, httplib::DataSink </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">sink) {
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// offset から length バイト分を送る
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return </span><span style="color:#0086b3;">true</span><span style="color:#323232;">;
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">});
</span><span style="color:#323232;">
</span><span style="font-style:italic;color:#969896;">// サイズ不明Chunked Transfer Encoding
</span><span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/stream&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_chunked_content_provider(</span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">,
</span><span style="color:#323232;"> [](</span><span style="color:#0086b3;">size_t</span><span style="color:#323232;"> offset, httplib::DataSink </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">sink) {
</span><span style="color:#323232;"> sink.write(</span><span style="color:#183691;">&quot;chunk</span><span style="color:#0086b3;">\n</span><span style="color:#183691;">&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">6</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return </span><span style="color:#0086b3;">true</span><span style="color:#323232;">; </span><span style="font-style:italic;color:#969896;">// falseを返すと終了
</span><span style="color:#323232;"> });
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>大きなファイルのアップロードには <code>make_file_provider()</code> が便利です。ファイルを全部メモリに読み込まず、ストリーミングで送れます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">http://localhost:8080</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Post</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/upload</span><span style="color:#d3d0c8;">&quot;, {}, {
</span><span style="color:#d3d0c8;"> </span><span style="color:#6699cc;">httplib::make_file_provider</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">file</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">/path/to/large-file.zip</span><span style="color:#d3d0c8;">&quot;)
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost:8080</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Post</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/upload</span><span style="color:#4f5b66;">&quot;, {}, {
</span><span style="color:#4f5b66;"> </span><span style="color:#8fa1b3;">httplib::make_file_provider</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">file</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">/path/to/large-file.zip</span><span style="color:#4f5b66;">&quot;)
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;http://localhost:8080&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Post(</span><span style="color:#183691;">&quot;/upload&quot;</span><span style="color:#323232;">, {}, {
</span><span style="color:#323232;"> httplib::make_file_provider(</span><span style="color:#183691;">&quot;file&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;/path/to/large-file.zip&quot;</span><span style="color:#323232;">)
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h2>Server-Sent Events (SSE)</h2>
<p>SSEクライアントも用意しています。自動再接続や <code>Last-Event-ID</code> による再開にも対応しています。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">http://localhost:8080</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">httplib::sse::SSEClient </span><span style="color:#6699cc;">sse</span><span style="color:#d3d0c8;">(</span><span style="color:#f2777a;">cli</span><span style="color:#d3d0c8;">, &quot;</span><span style="color:#99cc99;">/events</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">
@@ -216,42 +216,42 @@
</span><span style="color:#d3d0c8;">
</span><span style="color:#d3d0c8;">sse.</span><span style="color:#6699cc;">start</span><span style="color:#d3d0c8;">(); </span><span style="color:#747369;">// ブロッキング、自動再接続あり
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost:8080</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">httplib::sse::SSEClient </span><span style="color:#8fa1b3;">sse</span><span style="color:#4f5b66;">(</span><span style="color:#bf616a;">cli</span><span style="color:#4f5b66;">, &quot;</span><span style="color:#a3be8c;">/events</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">sse.</span><span style="color:#8fa1b3;">on_message</span><span style="color:#4f5b66;">([](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::sse::SSEMessage &amp;msg) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; msg.</span><span style="color:#bf616a;">event </span><span style="color:#4f5b66;">&lt;&lt; &quot;</span><span style="color:#a3be8c;">: </span><span style="color:#4f5b66;">&quot; &lt;&lt; msg.</span><span style="color:#bf616a;">data </span><span style="color:#4f5b66;">&lt;&lt; std::endl;
</span><span style="color:#4f5b66;">});
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">sse.</span><span style="color:#8fa1b3;">start</span><span style="color:#4f5b66;">(); </span><span style="color:#a7adba;">// ブロッキング、自動再接続あり
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;http://localhost:8080&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">httplib::sse::SSEClient </span><span style="font-weight:bold;color:#795da3;">sse</span><span style="color:#323232;">(cli, </span><span style="color:#183691;">&quot;/events&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">
</span><span style="color:#323232;">sse.on_message([](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::sse::SSEMessage </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">msg) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> msg.event </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot;: &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> msg.data </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;">});
</span><span style="color:#323232;">
</span><span style="color:#323232;">sse.start(); </span><span style="font-style:italic;color:#969896;">// ブロッキング、自動再接続あり
</span></pre>
</div>
</div></div>
<p>イベントタイプごとにハンドラーを分けることもできますよ。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">sse.</span><span style="color:#6699cc;">on_event</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">update</span><span style="color:#d3d0c8;">&quot;, [](</span><span style="color:#cc99cc;">const</span><span style="color:#d3d0c8;"> httplib::sse::SSEMessage &amp;msg) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#747369;">// &quot;update&quot; イベントだけ処理
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">sse.</span><span style="color:#8fa1b3;">on_event</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">update</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const</span><span style="color:#4f5b66;"> httplib::sse::SSEMessage &amp;msg) {
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// &quot;update&quot; イベントだけ処理
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">sse.on_event(</span><span style="color:#183691;">&quot;update&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const</span><span style="color:#323232;"> httplib::sse::SSEMessage </span><span style="font-weight:bold;color:#a71d5d;">&amp;</span><span style="color:#323232;">msg) {
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// &quot;update&quot; イベントだけ処理
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h2>認証</h2>
<p>クライアントにはBasic認証、Bearer Token認証、Digest認証のヘルパーを用意しています。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://api.example.com</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_basic_auth</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">user</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">password</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_bearer_token_auth</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">my-token</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://api.example.com</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_basic_auth</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">user</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">password</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_bearer_token_auth</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">my-token</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://api.example.com&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_basic_auth(</span><span style="color:#183691;">&quot;user&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;password&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_bearer_token_auth(</span><span style="color:#183691;">&quot;my-token&quot;</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<h2>圧縮</h2>
<p>gzip、Brotli、Zstandardによる圧縮・展開に対応しています。使いたい方式のマクロを定義してコンパイルしましょう。</p>
<table><thead><tr><th>圧縮方式</th><th>マクロ定義</th></tr></thead><tbody>
@@ -259,59 +259,59 @@
<tr><td>Brotli</td><td><code>CPPHTTPLIB_BROTLI_SUPPORT</code></td></tr>
<tr><td>Zstandard</td><td><code>CPPHTTPLIB_ZSTD_SUPPORT</code></td></tr>
</tbody></table>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://example.com</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_compress</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">true</span><span style="color:#d3d0c8;">); </span><span style="color:#747369;">// リクエストボディを圧縮
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_decompress</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">true</span><span style="color:#d3d0c8;">); </span><span style="color:#747369;">// レスポンスボディを展開
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://example.com</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_compress</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">true</span><span style="color:#4f5b66;">); </span><span style="color:#a7adba;">// リクエストボディを圧縮
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_decompress</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">true</span><span style="color:#4f5b66;">); </span><span style="color:#a7adba;">// レスポンスボディを展開
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://example.com&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_compress(</span><span style="color:#0086b3;">true</span><span style="color:#323232;">); </span><span style="font-style:italic;color:#969896;">// リクエストボディを圧縮
</span><span style="color:#323232;">cli.set_decompress(</span><span style="color:#0086b3;">true</span><span style="color:#323232;">); </span><span style="font-style:italic;color:#969896;">// レスポンスボディを展開
</span></pre>
</div>
</div></div>
<h2>プロキシ</h2>
<p>HTTPプロキシ経由で接続できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://example.com</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_proxy</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">proxy.example.com</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">8080</span><span style="color:#d3d0c8;">);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_proxy_basic_auth</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">user</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">password</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://example.com</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_proxy</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">proxy.example.com</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">8080</span><span style="color:#4f5b66;">);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_proxy_basic_auth</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">user</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">password</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://example.com&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_proxy(</span><span style="color:#183691;">&quot;proxy.example.com&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">8080</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_proxy_basic_auth(</span><span style="color:#183691;">&quot;user&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;password&quot;</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<h2>タイムアウト</h2>
<p>接続・読み取り・書き込みのタイムアウトを個別に設定できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://example.com</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_connection_timeout</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">5</span><span style="color:#d3d0c8;">, </span><span style="color:#f99157;">0</span><span style="color:#d3d0c8;">); </span><span style="color:#747369;">// 5秒
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_read_timeout</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">10</span><span style="color:#d3d0c8;">, </span><span style="color:#f99157;">0</span><span style="color:#d3d0c8;">); </span><span style="color:#747369;">// 10秒
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_write_timeout</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">10</span><span style="color:#d3d0c8;">, </span><span style="color:#f99157;">0</span><span style="color:#d3d0c8;">); </span><span style="color:#747369;">// 10秒
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://example.com</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_connection_timeout</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">5</span><span style="color:#4f5b66;">, </span><span style="color:#d08770;">0</span><span style="color:#4f5b66;">); </span><span style="color:#a7adba;">// 5秒
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_read_timeout</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">10</span><span style="color:#4f5b66;">, </span><span style="color:#d08770;">0</span><span style="color:#4f5b66;">); </span><span style="color:#a7adba;">// 10秒
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_write_timeout</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">10</span><span style="color:#4f5b66;">, </span><span style="color:#d08770;">0</span><span style="color:#4f5b66;">); </span><span style="color:#a7adba;">// 10秒
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://example.com&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_connection_timeout(</span><span style="color:#0086b3;">5</span><span style="color:#323232;">, </span><span style="color:#0086b3;">0</span><span style="color:#323232;">); </span><span style="font-style:italic;color:#969896;">// 5秒
</span><span style="color:#323232;">cli.set_read_timeout(</span><span style="color:#0086b3;">10</span><span style="color:#323232;">, </span><span style="color:#0086b3;">0</span><span style="color:#323232;">); </span><span style="font-style:italic;color:#969896;">// 10秒
</span><span style="color:#323232;">cli.set_write_timeout(</span><span style="color:#0086b3;">10</span><span style="color:#323232;">, </span><span style="color:#0086b3;">0</span><span style="color:#323232;">); </span><span style="font-style:italic;color:#969896;">// 10秒
</span></pre>
</div>
</div></div>
<h2>Keep-Alive</h2>
<p>同じサーバーに何度もリクエストするなら、Keep-Aliveを有効にしましょう。TCP接続を再利用するので効率的です。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">https://example.com</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_keep_alive</span><span style="color:#d3d0c8;">(</span><span style="color:#f99157;">true</span><span style="color:#d3d0c8;">);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">https://example.com</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_keep_alive</span><span style="color:#4f5b66;">(</span><span style="color:#d08770;">true</span><span style="color:#4f5b66;">);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;https://example.com&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_keep_alive(</span><span style="color:#0086b3;">true</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<h2>サーバーのミドルウェア</h2>
<p>リクエスト処理の前後にフックを挟めます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_pre_routing_handler</span><span style="color:#d3d0c8;">([](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> </span><span style="color:#747369;">// すべてのリクエストの前に実行される
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">return</span><span style="color:#d3d0c8;"> httplib::Server::HandlerResponse::Unhandled; </span><span style="color:#747369;">// 通常のルーティングに進む
@@ -322,20 +322,20 @@
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_header</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">X-Server</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">cpp-httplib</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_pre_routing_handler</span><span style="color:#4f5b66;">([](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// すべてのリクエストの前に実行される
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return</span><span style="color:#4f5b66;"> httplib::Server::HandlerResponse::Unhandled; </span><span style="color:#a7adba;">// 通常のルーティングに進む
</span><span style="color:#4f5b66;">});
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_post_routing_handler</span><span style="color:#4f5b66;">([](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#a7adba;">// レスポンスが返された後に実行される
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_header</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">X-Server</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">cpp-httplib</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.set_pre_routing_handler([](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// すべてのリクエストの前に実行される
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return</span><span style="color:#323232;"> httplib::Server::HandlerResponse::Unhandled; </span><span style="font-style:italic;color:#969896;">// 通常のルーティングに進む
</span><span style="color:#323232;">});
</span><span style="color:#323232;">
</span><span style="color:#323232;">svr.set_post_routing_handler([](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-style:italic;color:#969896;">// レスポンスが返された後に実行される
</span><span style="color:#323232;"> res.set_header(</span><span style="color:#183691;">&quot;X-Server&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;cpp-httplib&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p><code>req.user_data</code> を使うと、ミドルウェアからハンドラーにデータを渡せます。認証トークンのデコード結果を共有するときに便利です。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_pre_routing_handler</span><span style="color:#d3d0c8;">([](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> req.</span><span style="color:#f2777a;">user_data</span><span style="color:#d3d0c8;">[&quot;</span><span style="color:#99cc99;">auth_user</span><span style="color:#d3d0c8;">&quot;] = </span><span style="color:#6699cc;">std::string</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">alice</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;"> </span><span style="color:#cc99cc;">return</span><span style="color:#d3d0c8;"> httplib::Server::HandlerResponse::Unhandled;
@@ -346,20 +346,20 @@
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Hello, </span><span style="color:#d3d0c8;">&quot; + user, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_pre_routing_handler</span><span style="color:#4f5b66;">([](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> req.</span><span style="color:#bf616a;">user_data</span><span style="color:#4f5b66;">[&quot;</span><span style="color:#a3be8c;">auth_user</span><span style="color:#4f5b66;">&quot;] = </span><span style="color:#8fa1b3;">std::string</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">alice</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">return</span><span style="color:#4f5b66;"> httplib::Server::HandlerResponse::Unhandled;
</span><span style="color:#4f5b66;">});
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/me</span><span style="color:#4f5b66;">&quot;, [](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> </span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> user = std::</span><span style="color:#8fa1b3;">any_cast</span><span style="color:#4f5b66;">&lt;std::string&gt;(req.</span><span style="color:#bf616a;">user_data</span><span style="color:#4f5b66;">.</span><span style="color:#8fa1b3;">at</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">auth_user</span><span style="color:#4f5b66;">&quot;));
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Hello, </span><span style="color:#4f5b66;">&quot; + user, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.set_pre_routing_handler([](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> req.user_data[</span><span style="color:#183691;">&quot;auth_user&quot;</span><span style="color:#323232;">] </span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#323232;">std::string(</span><span style="color:#183691;">&quot;alice&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">return</span><span style="color:#323232;"> httplib::Server::HandlerResponse::Unhandled;
</span><span style="color:#323232;">});
</span><span style="color:#323232;">
</span><span style="color:#323232;">svr.Get(</span><span style="color:#183691;">&quot;/me&quot;</span><span style="color:#323232;">, [](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> </span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> user </span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#323232;">std::any_cast&lt;std::string&gt;(req.user_data.at(</span><span style="color:#183691;">&quot;auth_user&quot;</span><span style="color:#323232;">));
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Hello, &quot; </span><span style="font-weight:bold;color:#a71d5d;">+</span><span style="color:#323232;"> user, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<p>エラーや例外のハンドラーもカスタマイズできますよ。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_error_handler</span><span style="color:#d3d0c8;">([](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Custom Error Page</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/html</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
@@ -369,45 +369,45 @@
</span><span style="color:#d3d0c8;"> res.</span><span style="color:#6699cc;">set_content</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">Internal Server Error</span><span style="color:#d3d0c8;">&quot;, &quot;</span><span style="color:#99cc99;">text/plain</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_error_handler</span><span style="color:#4f5b66;">([](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Custom Error Page</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/html</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</span><span style="color:#4f5b66;">
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_exception_handler</span><span style="color:#4f5b66;">([](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">auto </span><span style="color:#4f5b66;">&amp;res, std::exception_ptr ep) {
</span><span style="color:#4f5b66;"> res.</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">= </span><span style="color:#d08770;">500</span><span style="color:#4f5b66;">;
</span><span style="color:#4f5b66;"> res.</span><span style="color:#8fa1b3;">set_content</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">Internal Server Error</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">text/plain</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.set_error_handler([](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Custom Error Page&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/html&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span><span style="color:#323232;">
</span><span style="color:#323232;">svr.set_exception_handler([](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">auto &amp;</span><span style="color:#323232;">res, std::exception_ptr ep) {
</span><span style="color:#323232;"> res.status </span><span style="font-weight:bold;color:#a71d5d;">= </span><span style="color:#0086b3;">500</span><span style="color:#323232;">;
</span><span style="color:#323232;"> res.set_content(</span><span style="color:#183691;">&quot;Internal Server Error&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;text/plain&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h2>ロギング</h2>
<p>サーバーでもクライアントでもロガーを設定できます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_logger</span><span style="color:#d3d0c8;">([](</span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;req, </span><span style="color:#cc99cc;">const auto </span><span style="color:#d3d0c8;">&amp;res) {
</span><span style="color:#d3d0c8;"> std::cout &lt;&lt; req.</span><span style="color:#f2777a;">method </span><span style="color:#d3d0c8;">&lt;&lt; &quot; &quot; &lt;&lt; req.</span><span style="color:#f2777a;">path </span><span style="color:#d3d0c8;">&lt;&lt; &quot; &quot; &lt;&lt; res.</span><span style="color:#f2777a;">status </span><span style="color:#d3d0c8;">&lt;&lt; std::endl;
</span><span style="color:#d3d0c8;">});
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_logger</span><span style="color:#4f5b66;">([](</span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;req, </span><span style="color:#b48ead;">const auto </span><span style="color:#4f5b66;">&amp;res) {
</span><span style="color:#4f5b66;"> std::cout &lt;&lt; req.</span><span style="color:#bf616a;">method </span><span style="color:#4f5b66;">&lt;&lt; &quot; &quot; &lt;&lt; req.</span><span style="color:#bf616a;">path </span><span style="color:#4f5b66;">&lt;&lt; &quot; &quot; &lt;&lt; res.</span><span style="color:#bf616a;">status </span><span style="color:#4f5b66;">&lt;&lt; std::endl;
</span><span style="color:#4f5b66;">});
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="color:#323232;">svr.set_logger([](</span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">req, </span><span style="font-weight:bold;color:#a71d5d;">const auto &amp;</span><span style="color:#323232;">res) {
</span><span style="color:#323232;"> std::cout </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> req.method </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot; &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> req.path </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt; </span><span style="color:#183691;">&quot; &quot; </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> res.status </span><span style="font-weight:bold;color:#a71d5d;">&lt;&lt;</span><span style="color:#323232;"> std::endl;
</span><span style="color:#323232;">});
</span></pre>
</div>
</div></div>
<h2>Unix Domain Socket</h2>
<p>TCP以外に、Unix Domain Socketでの通信にも対応しています。同じマシン上のプロセス間通信に使えます。</p>
<div class="code-dark"><pre style="background-color:#2d2d2d;">
<div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#747369;">// サーバー
</span><span style="color:#d3d0c8;">httplib::Server svr;
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">set_address_family</span><span style="color:#d3d0c8;">(AF_UNIX);
</span><span style="color:#d3d0c8;">svr.</span><span style="color:#6699cc;">listen</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/tmp/httplib.sock</span><span style="color:#d3d0c8;">&quot;, </span><span style="color:#f99157;">0</span><span style="color:#d3d0c8;">);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#a7adba;">// サーバー
</span><span style="color:#4f5b66;">httplib::Server svr;
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">set_address_family</span><span style="color:#4f5b66;">(AF_UNIX);
</span><span style="color:#4f5b66;">svr.</span><span style="color:#8fa1b3;">listen</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/tmp/httplib.sock</span><span style="color:#4f5b66;">&quot;, </span><span style="color:#d08770;">0</span><span style="color:#4f5b66;">);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-style:italic;color:#969896;">// サーバー
</span><span style="color:#323232;">httplib::Server svr;
</span><span style="color:#323232;">svr.set_address_family(AF_UNIX);
</span><span style="color:#323232;">svr.listen(</span><span style="color:#183691;">&quot;/tmp/httplib.sock&quot;</span><span style="color:#323232;">, </span><span style="color:#0086b3;">0</span><span style="color:#323232;">);
</span></pre>
</div><div class="code-dark"><pre style="background-color:#2d2d2d;">
</div></div><div class="code-block-wrapper"><div data-code-theme="dark"><pre style="background-color:#2d2d2d;">
<span style="color:#747369;">// クライアント
</span><span style="color:#d3d0c8;">httplib::Client </span><span style="color:#6699cc;">cli</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">http://localhost</span><span style="color:#d3d0c8;">&quot;);
</span><span style="color:#d3d0c8;">cli.</span><span style="color:#6699cc;">set_address_family</span><span style="color:#d3d0c8;">(AF_UNIX);
@@ -415,15 +415,15 @@
</span><span style="color:#d3d0c8;">
</span><span style="color:#cc99cc;">auto</span><span style="color:#d3d0c8;"> res = cli.</span><span style="color:#6699cc;">Get</span><span style="color:#d3d0c8;">(&quot;</span><span style="color:#99cc99;">/</span><span style="color:#d3d0c8;">&quot;);
</span></pre>
</div><div class="code-light"><pre style="background-color:#eff1f5;">
<span style="color:#a7adba;">// クライアント
</span><span style="color:#4f5b66;">httplib::Client </span><span style="color:#8fa1b3;">cli</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">http://localhost</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_address_family</span><span style="color:#4f5b66;">(AF_UNIX);
</span><span style="color:#4f5b66;">cli.</span><span style="color:#8fa1b3;">set_hostname_addr_map</span><span style="color:#4f5b66;">({{&quot;</span><span style="color:#a3be8c;">localhost</span><span style="color:#4f5b66;">&quot;, &quot;</span><span style="color:#a3be8c;">/tmp/httplib.sock</span><span style="color:#4f5b66;">&quot;}});
</span><span style="color:#4f5b66;">
</span><span style="color:#b48ead;">auto</span><span style="color:#4f5b66;"> res = cli.</span><span style="color:#8fa1b3;">Get</span><span style="color:#4f5b66;">(&quot;</span><span style="color:#a3be8c;">/</span><span style="color:#4f5b66;">&quot;);
</div><div data-code-theme="light"><pre style="background-color:#ffffff;">
<span style="font-style:italic;color:#969896;">// クライアント
</span><span style="color:#323232;">httplib::Client </span><span style="font-weight:bold;color:#795da3;">cli</span><span style="color:#323232;">(</span><span style="color:#183691;">&quot;http://localhost&quot;</span><span style="color:#323232;">);
</span><span style="color:#323232;">cli.set_address_family(AF_UNIX);
</span><span style="color:#323232;">cli.set_hostname_addr_map({{</span><span style="color:#183691;">&quot;localhost&quot;</span><span style="color:#323232;">, </span><span style="color:#183691;">&quot;/tmp/httplib.sock&quot;</span><span style="color:#323232;">}});
</span><span style="color:#323232;">
</span><span style="font-weight:bold;color:#a71d5d;">auto</span><span style="color:#323232;"> res </span><span style="font-weight:bold;color:#a71d5d;">=</span><span style="color:#323232;"> cli.Get(</span><span style="color:#183691;">&quot;/&quot;</span><span style="color:#323232;">);
</span></pre>
</div>
</div></div>
<h2>さらに詳しく</h2>
<p>もっと詳しく知りたいときは、以下を参照してください。</p>
<ul>