<?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>Practical guides and tested examples for building web APIs with Reinhardt and Rust.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://press.reinhardt-web.dev/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sat, 05 Sep 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Run Reinhardt 0.3.15&#x27;s REST example: database-backed CRUD in Rust</title>
          <pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate>
          <author>Reinhardt Press</author>
          <link>https://press.reinhardt-web.dev/rest-0-3-15/</link>
          <guid>https://press.reinhardt-web.dev/rest-0-3-15/</guid>
          <description xml:base="https://press.reinhardt-web.dev/rest-0-3-15/">&lt;p&gt;If you already write Rust and want to follow a small API from an HTTP request to a database row, Reinhardt&#x27;s existing REST tutorial is a useful place to start. Its example manages code snippets: a title, some code, and a language.&lt;&#x2F;p&gt;
&lt;p&gt;This walkthrough runs that example, exercises CRUD and invalid input, and points to the code responsible for each step. It targets &lt;strong&gt;Reinhardt 0.3.15&lt;&#x2F;strong&gt; and includes two setup details needed for this version: a local settings file and the management server feature. The goal is to make the first attempt reproducible and learn where developers get stuck.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prepare-a-local-environment&quot;&gt;Prepare a local environment&lt;&#x2F;h2&gt;
&lt;p&gt;You need Git, &lt;strong&gt;Rust 1.96.0 or later&lt;&#x2F;strong&gt; with Cargo, a running Docker engine, &lt;strong&gt;Python 3.11 or later&lt;&#x2F;strong&gt; for the infrastructure scripts, Bash, and curl. These commands use the supplied scripts directly; cargo-make is not required. Use a normal local shell without &lt;code&gt;CI&lt;&#x2F;code&gt; or &lt;code&gt;REINHARDT_ENV&lt;&#x2F;code&gt; profile overrides.&lt;&#x2F;p&gt;
&lt;p&gt;Keep ports &lt;strong&gt;5432, 6379, and 8000&lt;&#x2F;strong&gt; free. The helper recreates the disposable containers named &lt;code&gt;examples-tutorial-rest-postgres&lt;&#x2F;code&gt; and &lt;code&gt;examples-tutorial-rest-redis&lt;&#x2F;code&gt;; running it again removes data from an earlier run in those containers. Use this as a local, disposable demonstration.&lt;&#x2F;p&gt;
&lt;p&gt;Clone the pinned tag into a fresh directory:&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;Check that the printed commit is &lt;code&gt;c64a11e2dd945eab35ce3d56d812b0b78ff1b327&lt;&#x2F;code&gt;. Subsequent commands in this terminal run from &lt;code&gt;examples&#x2F;examples-tutorial-rest&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;supply-the-local-settings-and-start-the-api&quot;&gt;Supply the local settings and start the API&lt;&#x2F;h2&gt;
&lt;p&gt;The tag does not contain &lt;code&gt;settings&#x2F;local.toml&lt;&#x2F;code&gt; or a matching example template. Create the local settings expected by the infrastructure helper:&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;These are development settings for the local demonstration. Database configuration is inherited from the existing &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;base settings&lt;&#x2F;a&gt;. Start the supplied containers:&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;The helper starts PostgreSQL and Redis. The snippet API stores its data in PostgreSQL; it does &lt;strong&gt;not&lt;&#x2F;strong&gt; currently use Redis. Redis is started by the shared example infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;Apply migrations:&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;Then start the development server:&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;The explicit &lt;code&gt;reinhardt&#x2F;commands-server&lt;&#x2F;code&gt; feature matters in 0.3.15. During the initial check, the default feature selection built and migrated successfully, but &lt;code&gt;runserver&lt;&#x2F;code&gt; printed &lt;code&gt;Server feature not enabled&lt;&#x2F;code&gt;, exited with code 0, and never accepted HTTP requests. The commands above enable the management command&#x27;s server implementation. Confirm startup with the HTTP request below.&lt;&#x2F;p&gt;
&lt;p&gt;The first Cargo invocation compiles the example and its dependencies. Leave the server running and open a &lt;strong&gt;second terminal&lt;&#x2F;strong&gt; for requests.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-and-retrieve-a-snippet&quot;&gt;Create and retrieve a snippet&lt;&#x2F;h2&gt;
&lt;p&gt;Read the current list:&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;With the freshly recreated database, the list should be empty. The &lt;code&gt;-i&lt;&#x2F;code&gt; option keeps HTTP status and response headers visible. Create a snippet:&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;Look for HTTP &lt;strong&gt;201&lt;&#x2F;strong&gt; and the created object&#x27;s &lt;code&gt;snippet.id&lt;&#x2F;code&gt;. Replace &lt;code&gt;REPLACE_WITH_RETURNED_ID&lt;&#x2F;code&gt; below with that actual integer &lt;strong&gt;before executing the assignment&lt;&#x2F;strong&gt;. Keep this variable in the second terminal; do not assume the ID is 1.&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;Retrieve that record:&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;Look for HTTP &lt;strong&gt;200&lt;&#x2F;strong&gt; and the title, code, and language you sent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update-delete-and-check-invalid-input&quot;&gt;Update, delete, and check invalid input&lt;&#x2F;h2&gt;
&lt;p&gt;Update the same 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;Check the &lt;strong&gt;200&lt;&#x2F;strong&gt; response for &lt;code&gt;Updated snippet&lt;&#x2F;code&gt; and the updated code. Delete the record:&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;A successful deletion returns &lt;strong&gt;204&lt;&#x2F;strong&gt; with no response body. Request the same ID again:&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;Replaying this command returned &lt;strong&gt;404&lt;&#x2F;strong&gt; with &lt;code&gt;{&quot;error&quot;:&quot;Snippet not found&quot;}&lt;&#x2F;code&gt; after deletion.&lt;&#x2F;p&gt;
&lt;p&gt;Now send valid JSON whose &lt;code&gt;code&lt;&#x2F;code&gt; field is an empty string:&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;This exercises a field constraint rather than malformed JSON. Replaying this command returned &lt;strong&gt;400&lt;&#x2F;strong&gt;. Inspect the error body, then confirm that no invalid record was added:&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;If you only performed the steps above, the final list should be empty.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;follow-the-request-through-the-source&quot;&gt;Follow the request through the source&lt;&#x2F;h2&gt;
&lt;p&gt;Start in &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;, which mounts the snippets router under &lt;code&gt;&#x2F;api&#x2F;&lt;&#x2F;code&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;urls.rs&quot;&gt;&lt;code&gt;url_patterns&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; registers the function-based list, create, retrieve, update, and delete handlers.&lt;&#x2F;p&gt;
&lt;p&gt;In &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;, the request body becomes &lt;code&gt;Json&amp;lt;SnippetSerializer&amp;gt;&lt;&#x2F;code&gt; and the database connection arrives through &lt;code&gt;#[inject]&lt;&#x2F;code&gt;. The route declares validation before the handler body runs:&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;The handler builds a &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; from the accepted fields. Its manager performs the database write using that connection:&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; defines the input length constraints, including the nonempty code requirement. &lt;code&gt;SnippetResponse::from_model&lt;&#x2F;code&gt; selects the response fields before the handler serializes the JSON response.&lt;&#x2F;p&gt;
&lt;p&gt;For comparison, &lt;code&gt;views.rs::update&lt;&#x2F;code&gt; calls &lt;code&gt;serializer.validate()?&lt;&#x2F;code&gt; explicitly. Create and update therefore use different validation paths in this version; the empty-code result demonstrated here is for &lt;strong&gt;POST&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-was-checked&quot;&gt;What was checked&lt;&#x2F;h2&gt;
&lt;p&gt;On &lt;strong&gt;2026-09-05&lt;&#x2F;strong&gt;, a fresh clone matched the pinned commit. The settings heredoc and infrastructure script printed above ran successfully. The exact Cargo commands applied &lt;strong&gt;three migrations&lt;&#x2F;strong&gt; and started an HTTP listener. The eight curl requests were then executed from this article&#x27;s command blocks, substituting the actual returned ID.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Printed curl request&lt;&#x2F;th&gt;&lt;th&gt;Observed result&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Initial list&lt;&#x2F;td&gt;&lt;td&gt;200&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Create&lt;&#x2F;td&gt;&lt;td&gt;201; title, code, and language matched&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Retrieve created ID&lt;&#x2F;td&gt;&lt;td&gt;200; fields matched&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Update&lt;&#x2F;td&gt;&lt;td&gt;200; updated fields matched&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Delete&lt;&#x2F;td&gt;&lt;td&gt;204; empty body&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Retrieve deleted 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;Create with empty code&lt;&#x2F;td&gt;&lt;td&gt;400&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Final list&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;Separately, the initial check ran the existing Bruno &lt;code&gt;Snippets CRUD&lt;&#x2F;code&gt; and &lt;code&gt;Validation Tests&lt;&#x2F;code&gt; collections: &lt;strong&gt;8 requests and 12 tests passed&lt;&#x2F;strong&gt;. Its additional missing-title POST also returned &lt;strong&gt;400&lt;&#x2F;strong&gt;; that request is not part of the eight curl requests above.&lt;&#x2F;p&gt;
&lt;p&gt;These observations cover the native function-based REST example. This walkthrough does not validate every framework feature. Pages is under development, and production use is not yet recommended; Pages testing will have a separate scope.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stop-the-demonstration-and-tell-us-where-it-hurt&quot;&gt;Stop the demonstration and tell us where it hurt&lt;&#x2F;h2&gt;
&lt;p&gt;Stop the server with &lt;strong&gt;Ctrl-C&lt;&#x2F;strong&gt; in the first terminal, then run this from the same example directory:&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;This stops the disposable infrastructure and removes its data.&lt;&#x2F;p&gt;
&lt;p&gt;Try the example on your own machine, then change one thing at a time. For a usage question, open &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;. For a reproducible defect, use the &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 form&lt;&#x2F;a&gt; and include the version or commit, OS and Rust version, exact command, expected result, and actual result. A specific setup failure is useful feedback: it tells us which step needs improvement.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Disclosure: This article was drafted with LLM assistance and checked against the pinned source and the execution results described above.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
