<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Reinhardt Press</title>
      <link>https://press.reinhardt-web.dev</link>
      <description>ReinhardtとRustでWeb APIを作るための、実行確認済みのガイドとサンプル。</description>
      <generator>Zola</generator>
      <language>ja</language>
      <atom:link href="https://press.reinhardt-web.dev/ja/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sat, 05 Sep 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Reinhardt 0.3.15のRESTサンプルでCRUD APIを試す</title>
          <pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate>
          <author>Reinhardt Press</author>
          <link>https://press.reinhardt-web.dev/ja/rest-0-3-15/</link>
          <guid>https://press.reinhardt-web.dev/ja/rest-0-3-15/</guid>
          <description xml:base="https://press.reinhardt-web.dev/ja/rest-0-3-15/">&lt;p&gt;Rustで小さなWeb APIを試したい方に向けて、ReinhardtのRESTサンプルを動かす手順を紹介します。題材は、タイトル・コード・言語を登録できるスニペット（短いコード片）の管理APIです。&lt;&#x2F;p&gt;
&lt;p&gt;サンプルを起動してCRUDと不正入力を試し、HTTPリクエストの受信からデータベースへの書き込みまで、処理の流れをコードで追います。対象は &lt;strong&gt;Reinhardt 0.3.15&lt;&#x2F;strong&gt;。このバージョンで必要なローカル設定ファイルと、管理コマンドのサーバー機能を有効にする指定も含めて説明します。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rokaruhuan-jing-woyong-yi-suru&quot;&gt;ローカル環境を用意する&lt;&#x2F;h2&gt;
&lt;p&gt;Git、Cargoを含む &lt;strong&gt;Rust 1.96.0以上&lt;&#x2F;strong&gt;、Docker Engine、&lt;strong&gt;Python 3.11以上&lt;&#x2F;strong&gt;、Bash、curlが必要です。Docker Engineはあらかじめ起動しておいてください。Pythonはインフラ用のスクリプトで使います。付属スクリプトを直接実行するため、cargo-makeは必須ではありません。環境変数 &lt;code&gt;CI&lt;&#x2F;code&gt; や &lt;code&gt;REINHARDT_ENV&lt;&#x2F;code&gt; で別の設定プロファイルが選ばれていない、通常のローカルシェルで実行します。&lt;&#x2F;p&gt;
&lt;p&gt;ポート &lt;strong&gt;5432・6379・8000&lt;&#x2F;strong&gt; を空けておきます。付属スクリプトは、&lt;code&gt;examples-tutorial-rest-postgres&lt;&#x2F;code&gt; と &lt;code&gt;examples-tutorial-rest-redis&lt;&#x2F;code&gt; という名前のコンテナを作成します。同名のコンテナがすでにある場合は作り直すため、保存されていたデータは消えます。データを残す必要がない、ローカルの検証環境で試してください。&lt;&#x2F;p&gt;
&lt;p&gt;タグを指定し、新しいディレクトリにリポジトリをクローンします。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --depth 1 --branch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;#39;reinhardt-web@v0.3.15&amp;#39; https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web.git reinhardt-rest-demo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reinhardt-rest-demo&#x2F;examples&#x2F;examples-tutorial-rest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rev-parse HEAD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;表示されたコミットが &lt;code&gt;c64a11e2dd945eab35ce3d56d812b0b78ff1b327&lt;&#x2F;code&gt; と一致することを確認します。このターミナルでは、以後のコマンドも &lt;code&gt;examples&#x2F;examples-tutorial-rest&lt;&#x2F;code&gt; ディレクトリで実行します。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rokarushe-ding-wobu-tuteapiwoqi-dong-suru&quot;&gt;ローカル設定を補ってAPIを起動する&lt;&#x2F;h2&gt;
&lt;p&gt;このタグには &lt;code&gt;settings&#x2F;local.toml&lt;&#x2F;code&gt; も、そのひな形も含まれていません。インフラ用スクリプトが参照するローカル設定を作成します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; settings&#x2F;local.toml&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;TOML&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;[core]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;debug = true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;allowed_hosts = [&amp;quot;localhost&amp;quot;, &amp;quot;127.0.0.1&amp;quot;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;TOML&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;これはローカルでサンプルを試すための開発設定です。データベースの接続設定は、既存の&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;blob&#x2F;reinhardt-web%40v0.3.15&#x2F;examples&#x2F;examples-tutorial-rest&#x2F;settings&#x2F;base.toml&quot;&gt;ベース設定&lt;&#x2F;a&gt;から引き継ぎます。付属スクリプトでコンテナを起動します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; scripts&#x2F;infra_up.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;このスクリプトでPostgreSQLとRedisが起動します。スニペットAPIの保存先はPostgreSQLで、現在 &lt;strong&gt;API自体はRedisを使っていません&lt;&#x2F;strong&gt;。Redisはサンプル共通のインフラに含まれるため、一緒に起動します。&lt;&#x2F;p&gt;
&lt;p&gt;マイグレーションを適用します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --features&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reinhardt&#x2F;commands-server&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; manage&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; migrate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;続けて、開発サーバーを起動します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --features&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reinhardt&#x2F;commands-server&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; manage&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; runserver 127.0.0.1:8000&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; --noreload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;0.3.15では、&lt;code&gt;reinhardt&#x2F;commands-server&lt;&#x2F;code&gt; というfeatureを明示的に有効にする必要があります。初回の検証では、デフォルトのfeature構成でもビルドとマイグレーションは成功しましたが、&lt;code&gt;runserver&lt;&#x2F;code&gt; は &lt;code&gt;Server feature not enabled&lt;&#x2F;code&gt; を表示しました。HTTPリクエストを受け付けないまま、終了コード0で終了しています。上のコマンドは、管理コマンドで使うサーバー機能を有効にします。実際に起動できたかどうかは、次のHTTPリクエストで確認します。&lt;&#x2F;p&gt;
&lt;p&gt;初回のCargo実行では、サンプルと依存クレートのビルドが行われます。サーバーは起動したままにして、リクエストを送るために &lt;strong&gt;別のターミナル&lt;&#x2F;strong&gt; を開いてください。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sunipetutowozuo-cheng-sitequ-de-suru&quot;&gt;スニペットを作成して取得する&lt;&#x2F;h2&gt;
&lt;p&gt;まず、登録されているスニペットの一覧を取得します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;データベースを作り直した直後なら、一覧は空のはずです。&lt;code&gt;-i&lt;&#x2F;code&gt; を付けると、HTTPステータスとレスポンスヘッダーも表示されます。次に、スニペットを一つ作成します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i -X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; POST http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -H&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;#39;Content-Type: application&#x2F;json&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -d&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;#39;{&amp;quot;title&amp;quot;:&amp;quot;Hello Reinhardt&amp;quot;,&amp;quot;code&amp;quot;:&amp;quot;fn main() {}&amp;quot;,&amp;quot;language&amp;quot;:&amp;quot;rust&amp;quot;}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HTTPステータスが &lt;strong&gt;201&lt;&#x2F;strong&gt; になり、応答の &lt;code&gt;snippet.id&lt;&#x2F;code&gt; に作成したスニペットのIDが入っていることを確認します。次のコマンドを実行する前に、&lt;code&gt;REPLACE_WITH_RETURNED_ID&lt;&#x2F;code&gt; を &lt;strong&gt;実際に返った整数のIDに置き換えてください&lt;&#x2F;strong&gt;。IDが1とは限らないので、応答に含まれる値を使います。以降の操作も、この2つ目のターミナルで行います。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SNIPPET_ID&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;REPLACE_WITH_RETURNED_ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;このIDを使ってスニペットを取得します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;quot;http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SNIPPET_ID&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-string&quot;&gt;}&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HTTPステータスが &lt;strong&gt;200&lt;&#x2F;strong&gt; で、送信したタイトル・コード・言語が返ることを確認します。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;geng-xin-xue-chu-bu-zheng-ru-li-woshi-su&quot;&gt;更新、削除、不正入力を試す&lt;&#x2F;h2&gt;
&lt;p&gt;同じIDを指定して内容を更新します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i -X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-string&quot;&gt; PUT &amp;quot;http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SNIPPET_ID&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-string&quot;&gt;}&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -H&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;#39;Content-Type: application&#x2F;json&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -d&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;#39;{&amp;quot;title&amp;quot;:&amp;quot;Updated snippet&amp;quot;,&amp;quot;code&amp;quot;:&amp;quot;fn main() { println!(\&amp;quot;updated\&amp;quot;); }&amp;quot;,&amp;quot;language&amp;quot;:&amp;quot;rust&amp;quot;}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ステータスが &lt;strong&gt;200&lt;&#x2F;strong&gt; で、応答に &lt;code&gt;Updated snippet&lt;&#x2F;code&gt; と更新したコードが含まれることを確認します。続けて、このスニペットを削除します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i -X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-string&quot;&gt; DELETE &amp;quot;http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SNIPPET_ID&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-string&quot;&gt;}&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;削除が成功すると、本文のない &lt;strong&gt;204&lt;&#x2F;strong&gt; の応答が返ります。同じIDでもう一度取得を試します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;quot;http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SNIPPET_ID&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-string&quot;&gt;}&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;検証時には、削除後の取得は &lt;strong&gt;404&lt;&#x2F;strong&gt; となり、本文に &lt;code&gt;{&quot;error&quot;:&quot;Snippet not found&quot;}&lt;&#x2F;code&gt; が返りました。&lt;&#x2F;p&gt;
&lt;p&gt;次に、&lt;code&gt;code&lt;&#x2F;code&gt; の値を空文字列にしたJSONを送信します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i -X&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; POST http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -H&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;#39;Content-Type: application&#x2F;json&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -d&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;#39;{&amp;quot;title&amp;quot;:&amp;quot;Invalid snippet&amp;quot;,&amp;quot;code&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;language&amp;quot;:&amp;quot;rust&amp;quot;}&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;JSONとしては正しいデータを送り、&lt;code&gt;code&lt;&#x2F;code&gt; の入力制約が働くか確かめます。検証時のステータスは &lt;strong&gt;400&lt;&#x2F;strong&gt; でした。エラー本文を確認したら、不正なレコードが追加されていないか、一覧も確認します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;api&#x2F;snippets&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ここまでの操作だけなら、最後の一覧は空のはずです。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;chu-li-noliu-rewokododezhui-u&quot;&gt;処理の流れをコードで追う&lt;&#x2F;h2&gt;
&lt;p&gt;リクエストの入口となる&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;blob&#x2F;reinhardt-web%40v0.3.15&#x2F;examples&#x2F;examples-tutorial-rest&#x2F;src&#x2F;config&#x2F;urls.rs&quot;&gt;&lt;code&gt;src&#x2F;config&#x2F;urls.rs::routes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;では、&lt;code&gt;&#x2F;api&#x2F;&lt;&#x2F;code&gt; の下にsnippetsのルーターを組み込んでいます。&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;blob&#x2F;reinhardt-web%40v0.3.15&#x2F;examples&#x2F;examples-tutorial-rest&#x2F;src&#x2F;apps&#x2F;snippets&#x2F;urls.rs&quot;&gt;&lt;code&gt;url_patterns&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;には、一覧・作成・取得・更新・削除を担当するハンドラー関数が登録されています。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;blob&#x2F;reinhardt-web%40v0.3.15&#x2F;examples&#x2F;examples-tutorial-rest&#x2F;src&#x2F;apps&#x2F;snippets&#x2F;views.rs&quot;&gt;&lt;code&gt;views.rs::create&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;では、リクエスト本文を &lt;code&gt;Json&amp;lt;SnippetSerializer&amp;gt;&lt;&#x2F;code&gt; で、データベース接続を &lt;code&gt;#[inject]&lt;&#x2F;code&gt; による依存注入で受け取ります。&lt;code&gt;pre_validate = true&lt;&#x2F;code&gt; の指定により、ハンドラー本体を実行する前に入力を検証します。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[post(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt;&amp;quot;&#x2F;snippets&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-string&quot;&gt; &amp;quot;snippets-create&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, pre_validate &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; true)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ハンドラーは、検証を通過したフィールドから&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;blob&#x2F;reinhardt-web%40v0.3.15&#x2F;examples&#x2F;examples-tutorial-rest&#x2F;src&#x2F;apps&#x2F;snippets&#x2F;models.rs&quot;&gt;&lt;code&gt;Snippet&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;を組み立てます。続いて、そのモデルのManagerが、渡された接続を使ってデータベースに書き込みます。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; created&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Manager&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Snippet&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;create_with_conn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;db,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;snippet)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    .await?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;blob&#x2F;reinhardt-web%40v0.3.15&#x2F;examples&#x2F;examples-tutorial-rest&#x2F;src&#x2F;apps&#x2F;snippets&#x2F;serializers.rs&quot;&gt;&lt;code&gt;SnippetSerializer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;では、&lt;code&gt;code&lt;&#x2F;code&gt; が空でないことなど、入力の長さに関する制約を定義しています。&lt;code&gt;SnippetResponse::from_model&lt;&#x2F;code&gt; が応答用のフィールドを取り出し、ハンドラーがJSONに変換して返します。&lt;&#x2F;p&gt;
&lt;p&gt;更新処理の &lt;code&gt;views.rs::update&lt;&#x2F;code&gt; では、&lt;code&gt;serializer.validate()?&lt;&#x2F;code&gt; を明示的に呼んでいます。このバージョンでは、作成と更新で検証の仕組みが異なります。空の &lt;code&gt;code&lt;&#x2F;code&gt; に対して示した結果は、&lt;strong&gt;POST&lt;&#x2F;strong&gt; による作成処理を試したものです。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;que-ren-sitafan-wei&quot;&gt;確認した範囲&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;2026-09-05&lt;&#x2F;strong&gt; に、新たにクローンしたリポジトリが冒頭のコミットと一致することを確認しました。本文のコマンドを使い、設定ファイルの作成とインフラの起動、&lt;strong&gt;3件のマイグレーション&lt;&#x2F;strong&gt; の適用に成功しています。続いて、記載どおりのCargoコマンドでHTTPサーバーを起動し、8件のcurlリクエストを実行しました。IDには、作成時の応答に含まれる値を使っています。&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;curlで送信したリクエスト&lt;&#x2F;th&gt;&lt;th&gt;確認できた結果&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;初期一覧&lt;&#x2F;td&gt;&lt;td&gt;200&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;作成&lt;&#x2F;td&gt;&lt;td&gt;201、title・code・languageが一致&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;作成したIDの取得&lt;&#x2F;td&gt;&lt;td&gt;200、フィールドが一致&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;更新&lt;&#x2F;td&gt;&lt;td&gt;200、更新したフィールドが一致&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;削除&lt;&#x2F;td&gt;&lt;td&gt;204、本文なし&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;削除したIDの取得&lt;&#x2F;td&gt;&lt;td&gt;404、&lt;code&gt;{&quot;error&quot;:&quot;Snippet not found&quot;}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;codeを空文字列にして作成&lt;&#x2F;td&gt;&lt;td&gt;400&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;最後の一覧&lt;&#x2F;td&gt;&lt;td&gt;200、&lt;code&gt;{&quot;snippets&quot;:[]}&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;これとは別に、初回の検証では、サンプルに付属するBrunoの &lt;code&gt;Snippets CRUD&lt;&#x2F;code&gt; と &lt;code&gt;Validation Tests&lt;&#x2F;code&gt; を実行し、&lt;strong&gt;8リクエスト・12テストがすべて成功&lt;&#x2F;strong&gt;しました。追加で、&lt;code&gt;title&lt;&#x2F;code&gt; を省略したPOSTも試したところ、&lt;strong&gt;400&lt;&#x2F;strong&gt; が返りました。このリクエストは、上記8件のcurlには含まれていません。&lt;&#x2F;p&gt;
&lt;p&gt;ここで確認したのは、ネイティブ環境で動作する、関数ベースのRESTサンプルです。フレームワークの全機能を検証したものではありません。Pagesはまだ開発中のため、本番利用は推奨していません。Pagesについては、今回とは別に検証範囲を決めて進めます。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hou-pian-fu-ketohuidobatuku&quot;&gt;後片付けとフィードバック&lt;&#x2F;h2&gt;
&lt;p&gt;最初のターミナルで &lt;strong&gt;Ctrl-C&lt;&#x2F;strong&gt; を押してサーバーを止めます。そのままサンプルのディレクトリで、次のコマンドを実行してください。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; scripts&#x2F;infra_down.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;PostgreSQLとRedisのコンテナが停止し、保存したデータも削除されます。&lt;&#x2F;p&gt;
&lt;p&gt;サンプルが動いたら、一つずつ変更を加えて、動きの違いを確かめてみてください。使い方の質問は&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;discussions&quot;&gt;GitHub Discussions&lt;&#x2F;a&gt;へ。再現できる不具合は&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kent8192&#x2F;reinhardt-web&#x2F;issues&#x2F;new&#x2F;choose&quot;&gt;Issueフォーム&lt;&#x2F;a&gt;から、使用したバージョンまたはコミット、OSとRustのバージョン、実行コマンド、期待する動作と実際の結果を添えて報告してください。どの手順でつまずいたかを教えてもらえると、導入手順の改善に役立ちます。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;執筆について：この記事はLLMの支援を受けて作成しました。内容は対象タグのソースと、本文に記載した実行結果に照らして確認しています。&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
