vial 0.0.5

a micro micro-framework
Documentation
<!DOCTYPE html>
<html>
  <head>
    <title>~ vial: a micro micro-framework ~</title>
    <style type="text/css">
      body {
        margin: 40px auto;
        max-width: 950px;
        line-height: 1.6;
        font-size: 20px;
        color: #444;
        padding: 16px;
        font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica,
          Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
      }
      h1:first-of-type {
        text-align: center;

        text-align: left;
        margin-bottom: 0;
        font-size: 150px;
        margin-top: 40px;
      }
      h4:first-of-type {
        margin: 0;
        font-size: 50px;
        color: #aaa;
        margin-top: -30px;
        margin-bottom: 50px;
        font-weight: normal;
      }
      img:first-of-type {
        margin-top: -20px;
        margin-right: 20px;
      }
      h1 {
        font-size: 2em;
      }
      h2 {
        border-bottom: 1px solid #ddd;
        font-size: 1.75em;
      }

      h1,
      h2,
      h3 {
        line-height: 1.2;
      }

      p {
        text-align: justify;
      }

      /** pandoc styles below **/
      code {
        white-space: pre-wrap;
      }
      span.smallcaps {
        font-variant: small-caps;
      }
      span.underline {
        text-decoration: underline;
      }
      div.column {
        display: inline-block;
        vertical-align: top;
        width: 50%;
      }
      div.hanging-indent {
        margin-left: 1.5em;
        text-indent: -1.5em;
      }
      pre > code.sourceCode {
        white-space: pre;
        position: relative;
      }
      pre > code.sourceCode > span {
        display: inline-block;
        line-height: 1.25;
      }
      pre > code.sourceCode > span:empty {
        height: 1.2em;
      }
      code.sourceCode > span {
        color: inherit;
        text-decoration: inherit;
      }
      div.sourceCode {
        margin: 1em 0;
      }
      pre.sourceCode {
        margin: 0;
      }
      @media screen {
        div.sourceCode {
          overflow: auto;
        }
      }
      @media print {
        pre > code.sourceCode {
          white-space: pre-wrap;
        }
        pre > code.sourceCode > span {
          text-indent: -5em;
          padding-left: 5em;
        }
      }
      pre.numberSource code {
        counter-reset: source-line 0;
      }
      pre.numberSource code > span {
        position: relative;
        left: -4em;
        counter-increment: source-line;
      }
      pre.numberSource code > span > a:first-child::before {
        content: counter(source-line);
        position: relative;
        left: -1em;
        text-align: right;
        vertical-align: baseline;
        border: none;
        display: inline-block;
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        -khtml-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
        padding: 0 4px;
        width: 4em;
        color: #aaaaaa;
      }
      pre.numberSource {
        margin-left: 3em;
        border-left: 1px solid #aaaaaa;
        padding-left: 4px;
      }
      div.sourceCode {
      }
      @media screen {
        pre > code.sourceCode > span > a:first-child::before {
          text-decoration: underline;
        }
      }
      code span.al {
        color: #ff0000;
        font-weight: bold;
      } /* Alert */
      code span.an {
        color: #60a0b0;
        font-weight: bold;
        font-style: italic;
      } /* Annotation */
      code span.at {
        color: #7d9029;
      } /* Attribute */
      code span.bn {
        color: #40a070;
      } /* BaseN */
      code span.bu {
      } /* BuiltIn */
      code span.cf {
        color: #007020;
        font-weight: bold;
      } /* ControlFlow */
      code span.ch {
        color: #4070a0;
      } /* Char */
      code span.cn {
        color: #880000;
      } /* Constant */
      code span.co {
        color: #60a0b0;
        font-style: italic;
      } /* Comment */
      code span.cv {
        color: #60a0b0;
        font-weight: bold;
        font-style: italic;
      } /* CommentVar */
      code span.do {
        color: #ba2121;
        font-style: italic;
      } /* Documentation */
      code span.dt {
        color: #902000;
      } /* DataType */
      code span.dv {
        color: #40a070;
      } /* DecVal */
      code span.er {
        color: #ff0000;
        font-weight: bold;
      } /* Error */
      code span.ex {
      } /* Extension */
      code span.fl {
        color: #40a070;
      } /* Float */
      code span.fu {
        color: #06287e;
      } /* Function */
      code span.im {
      } /* Import */
      code span.in {
        color: #60a0b0;
        font-weight: bold;
        font-style: italic;
      } /* Information */
      code span.kw {
        color: #007020;
        font-weight: bold;
      } /* Keyword */
      code span.op {
        color: #666666;
      } /* Operator */
      code span.ot {
        color: #007020;
      } /* Other */
      code span.pp {
        color: #bc7a00;
      } /* Preprocessor */
      code span.sc {
        color: #4070a0;
      } /* SpecialChar */
      code span.ss {
        color: #bb6688;
      } /* SpecialString */
      code span.st {
        color: #4070a0;
      } /* String */
      code span.va {
        color: #19177c;
      } /* Variable */
      code span.vs {
        color: #4070a0;
      } /* VerbatimString */
      code span.wa {
        color: #60a0b0;
        font-weight: bold;
        font-style: italic;
      } /* Warning */
    </style>
  </head>
  <body>
    <p><img src="./img/drink-me.jpeg" alt="Drink Me." align="left" height="300" /></p>
<h1 id="vial">Vial</h1>
<h4 id="a-micro-micro-framework">~ a micro micro-framework ~</h4>
<p><strong>vial</strong> is a micro web “framework” for making micro web “sites”. It only includes a handful of basic features, hopeful that you’ll add whatever other features you need on your own. Kind of like ice cream toppings at one of those ice cream places.</p>
<p>The goal is a small, lean core that compiles quickly and has as few dependencies as possible. Use it for HTML stuff: prototyping ideas, testing out concepts, or, perhaps, even writing tiny personal apps.</p>
<p>This manual is an overview of <strong>vial</strong>’s built in features, as well as the few <em>optional</em> features you can enable. It also includes suggestions for many “common tasks”, like using a database to store information.</p>
<h2 id="hello-world">Hello, World</h2>
<p>This global greeting shows off some of <strong>vial</strong>’s built-in features.</p>
<p>You can play with it in real time by running this command in your local copy of this repository:</p>
<pre><code>$ cargo run --example manual</code></pre>
<p>Feel free to open it in your favorite text editor and poke around!</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">use</span> <span class="pp">vial::prelude::</span><span class="op">*;</span></span>
<span id="cb2-2"><a href="#cb2-2"></a></span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="pp">routes!</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>    GET <span class="st">&quot;/&quot;</span> <span class="op">=&gt;</span> hello_world<span class="op">;</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>    POST <span class="st">&quot;/&quot;</span> <span class="op">=&gt;</span> redirect_to_greeting<span class="op">;</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>    GET <span class="st">&quot;/:name&quot;</span> <span class="op">=&gt;</span> hello_name<span class="op">;</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>    GET <span class="st">&quot;/*path&quot;</span> <span class="op">=&gt;</span> <span class="op">|</span>req<span class="op">|</span></span>
<span id="cb2-8"><a href="#cb2-8"></a>      <span class="pp">Response::</span>from(<span class="dv">404</span>)<span class="op">.</span>with_body(</span>
<span id="cb2-9"><a href="#cb2-9"></a>        <span class="pp">format!</span>(<span class="st">&quot;&lt;h1&gt;404 Not Found: {}&lt;/h1&gt;&quot;</span><span class="op">,</span></span>
<span id="cb2-10"><a href="#cb2-10"></a>          req<span class="op">.</span>arg(<span class="st">&quot;path&quot;</span>)<span class="op">.</span>unwrap_or(<span class="st">&quot;&quot;</span>)))<span class="op">;</span></span>
<span id="cb2-11"><a href="#cb2-11"></a><span class="op">}</span></span>
<span id="cb2-12"><a href="#cb2-12"></a></span>
<span id="cb2-13"><a href="#cb2-13"></a><span class="kw">fn</span> hello_world(_req<span class="op">:</span> Request) <span class="op">-&gt;</span> <span class="kw">impl</span> Responder <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14"></a>    <span class="st">&quot;&lt;h1&gt;Hello, world!&lt;/h1&gt;</span></span>
<span id="cb2-15"><a href="#cb2-15"></a><span class="st">    &lt;p&gt;&lt;strong&gt;What&#39;s your name?&lt;/strong&gt;&lt;/p&gt;</span></span>
<span id="cb2-16"><a href="#cb2-16"></a><span class="st">    &lt;form method=&#39;POST&#39; action=&#39;/&#39;&gt;</span></span>
<span id="cb2-17"><a href="#cb2-17"></a><span class="st">        &lt;p&gt;&lt;input name=&#39;name&#39; type=&#39;text&#39;/&gt;&lt;/p&gt;</span></span>
<span id="cb2-18"><a href="#cb2-18"></a><span class="st">        &lt;p&gt;&lt;input type=&#39;submit&#39;/&gt;&lt;/p&gt;</span></span>
<span id="cb2-19"><a href="#cb2-19"></a><span class="st">    &lt;/form&gt;&quot;</span></span>
<span id="cb2-20"><a href="#cb2-20"></a><span class="op">}</span></span>
<span id="cb2-21"><a href="#cb2-21"></a></span>
<span id="cb2-22"><a href="#cb2-22"></a><span class="kw">fn</span> redirect_to_greeting(req<span class="op">:</span> Request) <span class="op">-&gt;</span> <span class="dt">Option</span><span class="op">&lt;</span><span class="kw">impl</span> Responder<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb2-23"><a href="#cb2-23"></a>    <span class="kw">let</span> name <span class="op">=</span> req<span class="op">.</span>form(<span class="st">&quot;name&quot;</span>)<span class="op">?;</span></span>
<span id="cb2-24"><a href="#cb2-24"></a>    <span class="cn">Some</span>(<span class="pp">Response::</span>redirect_to(<span class="pp">format!</span>(<span class="st">&quot;/{}&quot;</span><span class="op">,</span> name)))</span>
<span id="cb2-25"><a href="#cb2-25"></a><span class="op">}</span></span>
<span id="cb2-26"><a href="#cb2-26"></a></span>
<span id="cb2-27"><a href="#cb2-27"></a><span class="kw">fn</span> hello_name(req<span class="op">:</span> Request) <span class="op">-&gt;</span> <span class="kw">impl</span> Responder <span class="op">{</span></span>
<span id="cb2-28"><a href="#cb2-28"></a>    <span class="pp">format!</span>(<span class="st">&quot;&lt;h1&gt;Why hello there, {}!&lt;/h1&gt;&quot;</span><span class="op">,</span> req<span class="op">.</span>arg(<span class="st">&quot;name&quot;</span>)<span class="op">.</span>unwrap())</span>
<span id="cb2-29"><a href="#cb2-29"></a><span class="op">}</span></span>
<span id="cb2-30"><a href="#cb2-30"></a></span>
<span id="cb2-31"><a href="#cb2-31"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
<span id="cb2-32"><a href="#cb2-32"></a>    <span class="pp">run!</span>()<span class="op">.</span>unwrap()<span class="op">;</span></span>
<span id="cb2-33"><a href="#cb2-33"></a><span class="op">}</span></span></code></pre></div>
<h2 id="getting-started">Getting Started</h2>
<ul>
<li>Add it to your project</li>
<li>Include the prelude</li>
<li>Define <code>routes!</code></li>
<li>Call <code>run!</code></li>
</ul>
<h2 id="routes">Routes</h2>
<p>Routes are written using the <code>routes!</code> macro in the format:</p>
<pre><code>HTTP_METHOD ROUTE_PATTERN =&gt; ACTION;</code></pre>
<p>The order in which routes are written matters - routes written first will be checked for matches first, meaning you can declare many routes that point to <code>"/"</code>, but only the first one declared will ever match.</p>
<p><code>HTTP_METHOD</code> can be one of:</p>
<ul>
<li><code>GET</code></li>
<li><code>HEAD</code></li>
<li><code>POST</code></li>
<li><code>PUT</code></li>
<li><code>DELETE</code></li>
<li><code>PATCH</code></li>
</ul>
<p><code>ACTION</code> can be either of:</p>
<ol type="1">
<li>A closure in the form of <code>|req| { code }</code> that returns an <code>impl Responder</code></li>
<li>The name of a function with the signature of <code>fn(Request) -&gt; impl Responder</code>.</li>
</ol>
<p><code>ROUTE_PATTERN</code> can be an exact match, such as <code>"/user"</code> or <code>"/v2/search.php3"</code>, or it can include a named parameter:</p>
<ol type="1">
<li><code>"/:name"</code> — This will match almost anything except paths with <code>/</code> in them or with <code>.</code> in them.</li>
<li><code>"/:name.md"</code> — Use this format to match on a specific file extension.</li>
<li><code>"/*name"</code> — This will match everything, including <code>/</code>.</li>
</ol>
<p>In the three examples above, calling <code>req.arg("name")</code> in an <code>ACTION</code> will deliver <code>Some(&amp;str)</code>.</p>
<h2 id="requests">Requests</h2>
<p>When a route matches and an <code>ACTION</code> is called, it’s passed a <a href="https://docs.rs/vial/latest/vial/struct.Request.html">Request</a> object.</p>
<ul>
<li><code>arg(&amp;str) -&gt; Option&lt;&amp;str&gt;</code></li>
<li><code>query(&amp;str) -&gt; Option&lt;&amp;str&gt;</code></li>
<li><code>form(&amp;str) -&gt; Option&lt;&amp;str&gt;</code></li>
<li><code>header(&amp;str) -&gt; Option&lt;&amp;str&gt;</code></li>
<li><code>method() -&gt; &amp;str</code></li>
<li><code>path() -&gt; &amp;str</code></li>
</ul>
<h2 id="responses">Responses</h2>
<p>All <code>ACTIONs</code> return <a href="https://docs.rs/vial/latest/vial/trait.Responder.html">Responders</a>, which are turned into <a href="https://docs.rs/vial/latest/vial/struct.Response.html">Responses</a> before being sent back to the client.</p>
<ul>
<li><code>Response::from()</code></li>
<li><code>Response::from_body()</code></li>
<li><code>Response::from_text()</code></li>
<li><code>Response::from_file()</code></li>
<li><code>Response::from_asset()</code></li>
<li><code>Response::from_code()</code></li>
</ul>
<h2 id="assets">Assets</h2>
<ul>
<li><code>static_dir!</code></li>
<li><code>asset::exists()</code></li>
<li><code>asset::path()</code></li>
</ul>
<h2 id="bundling-assets">Bundling Assets</h2>
<ul>
<li><code>vial::bundle_assets(path_to_asset_dir)</code></li>
</ul>
<h2 id="cookies">Cookies</h2>
<h2 id="sessions">Sessions</h2>
<h2 id="json">JSON</h2>
<h2 id="state">State</h2>
<h2 id="database">Database</h2>
<h2 id="markdown">Markdown</h2>
<h2 id="hatter-templates">Hatter Templates</h2>
<h2 id="horrorshow-templates">Horrorshow Templates</h2>
<h2 id="tera-templates">Tera Templates</h2>

  </body>
</html>