<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:yandex="http://news.yandex.ru" xmlns:media="http://search.yahoo.com/mrss/" xmlns:turbo="http://turbo.yandex.ru" version="2.0"><channel><title>Dart, Framework, Server-Side, Programming on TenderOwl</title><link>https://tenderowl.com/tags/dart-framework-server-side-programming/</link><description>Recent content in Dart, Framework, Server-Side, Programming on TenderOwl</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Tue, 04 Oct 2022 01:26:21 +0300</lastBuildDate><atom:link href="https://tenderowl.com/tags/dart-framework-server-side-programming/index.xml" rel="self" type="application/rss+xml"/><item turbo="true"><turbo:extendedHtml>true</turbo:extendedHtml><title>Server-side Dart</title><link>https://tenderowl.com/posts/server-side-dart/</link><pubDate>Tue, 04 Oct 2022 01:26:21 +0300</pubDate><guid>https://tenderowl.com/posts/server-side-dart/</guid><description>&lt;h2 id="disclaimer">Disclaimer&lt;/h2>
&lt;p>Laska is under active development and is not supposed to be used in production. API may change dramatically in future versions.&lt;/p>
&lt;h2 id="intro">Intro&lt;/h2>
&lt;p>It&amp;rsquo;s not a secret that Dart&amp;rsquo;s popularity comes from the Flutter framework and its acceptance by the community. I love Flutter as well, but what I miss is server-side. How cool it could be to be a full-stack developer by using only Dart language?&lt;/p></description><turbo:content><![CDATA[
            <h2 id="disclaimer">Disclaimer</h2>
<p>Laska is under active development and is not supposed to be used in production. API may change dramatically in future versions.</p>
<h2 id="intro">Intro</h2>
<p>It&rsquo;s not a secret that Dart&rsquo;s popularity comes from the Flutter framework and its acceptance by the community. I love Flutter as well, but what I miss is server-side. How cool it could be to be a full-stack developer by using only Dart language?</p>
<p>There was a time, I want to start a new project and have to choose what technologies to use for the frontend and backend parts as well. Research gets me to <a href="https://aqueduct.io/">Aqueduct</a> and <a href="https://pub.dev/packages/shelf">Shelf</a>, both of them weren&rsquo;t looking actively developing and supported and that leads me to the idea to make my own small micro-framework like <a href="https://echo.labstack.com/">Echo</a> for Golang or <a href="https://bottlepy.org/">Bottle</a> for Python. And it was easy to decide: I&rsquo;ve had time and motivation :)</p>
<p>And before we get started, I&rsquo;d like to answer some questions that will definitely come up: why do we need one more framework, and what&rsquo;s the problem your framework resolves? The first one is easy: ask JavaScript developers! But OK, the real answer is competition: the more frameworks we have, the more we learn from each other and, eventually, we build better apps. The second answer: it was designed and built for micro-services and small applications. Sure, there is a way to extend it with middleware and extensions that come later, but as I said I treat it as a Dart alternative to Bottle or Echo. And when I say built I mean will be built 😄</p>
<h2 id="architecture">Architecture</h2>
<p>Laska - that&rsquo;s how the project is named - is a micro-framework, it&rsquo;s not aimed to be a full-featured app like Django. Therefore the architecture is quite simple: every request is processed by the same process while performance is based on leveraging the async nature of Dart.</p>
<p>Let&rsquo;s briefly review how it works.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/21sorv8stnckxhl0yb21.png" alt="Async server diagram"></p>
<p>As we can see on the diagram, asynchronous server processing works like a charm :)</p>
<p>I did experiment with Isolates and multiprocessing, but finally, I decided it would require the developers to work with additional limitations. It is not the way I want to use any kind of software, so why does anyone should do it? Programming should be easy and fun therefore there is no kind of parallelism in Laska.</p>
<h2 id="lets-build-something">Let&rsquo;s build something</h2>
<p>There is a trivial way to present programming languages and frameworks called &lsquo;Hello world&rsquo;. Let&rsquo;s be trivial!</p>
<div class="rounded"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;package:laska/laska.dart&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">main</span><span class="p">()</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">final</span> <span class="n">laska</span> <span class="o">=</span> <span class="n">Laska</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">laska</span><span class="p">.</span><span class="n">GET</span><span class="p">(</span><span class="s1">&#39;/hello/:name&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="n">context</span><span class="p">)</span> <span class="kd">async</span> <span class="o">=&gt;</span> <span class="kd">await</span> <span class="n">context</span><span class="p">.</span><span class="n">Text</span><span class="p">(</span><span class="s2">&#34;Hello </span><span class="si">${</span><span class="n">context</span><span class="p">.</span><span class="n">param</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">!&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">await</span> <span class="n">run</span><span class="p">(</span><span class="n">laska</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>It&rsquo;s easy to understand what&rsquo;s going on here:</p>
<ul>
<li>initialize a Laska object</li>
<li>add a handler for GET requests at the route &lsquo;/hello/:name&rsquo;, where <code>name</code> is a placeholder for context parameters</li>
<li>code a handler that returns a string with a parameter given in the path</li>
<li>and run the server</li>
</ul>
<p>That&rsquo;s it, an asynchronous server is up and running on http://localhost:3789.</p>
<h2 id="more-realistic-example">More realistic example</h2>
<p>Surely, &lsquo;Hello world&rsquo; is not a kind of real-world application someone will deploy to production. The more realistic would be to build a server that logs user requests to the stdout and has routes that require authorization.</p>
<div class="rounded"><pre tabindex="0" class="chroma"><code class="language-dart" data-lang="dart"><span class="line"><span class="cl"><span class="k">import</span> <span class="s1">&#39;package:laska/laska.dart&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Custom middleware that checks user access.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">class</span> <span class="nc">Acl</span> <span class="kd">implements</span> <span class="n">Middleware</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">final</span> <span class="n">allowedRoles</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">Acl</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">allowedRoles</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="err">@</span><span class="n">override</span>
</span></span><span class="line"><span class="cl">  <span class="n">Future</span><span class="o">&lt;</span><span class="n">Function</span><span class="o">&gt;</span> <span class="n">execute</span><span class="p">(</span><span class="n">Function</span> <span class="n">next</span><span class="p">,</span> <span class="n">Context</span> <span class="n">context</span><span class="p">)</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">Context</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// In this case it&#39;s simple check:
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="c1">// Does the request contains `role` header with `admin` value.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="kd">final</span> <span class="n">role</span> <span class="o">=</span> <span class="n">context</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">headers</span><span class="p">.</span><span class="n">value</span><span class="p">(</span><span class="s1">&#39;role&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="c1">// If the header&#39;s `role` is not in `allowedRoles`, reject the request.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">allowedRoles</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">role</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">context</span><span class="p">.</span><span class="n">Text</span><span class="p">(</span><span class="s1">&#39;Role </span><span class="si">$</span><span class="n">role</span><span class="s1"> is not allowed.&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="n">print</span><span class="p">(</span><span class="s1">&#39;Role </span><span class="si">$</span><span class="n">role</span><span class="s1"> is allowed.&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="c1">// Don&#39;t forget to call the handler.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">return</span> <span class="n">next</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Custom middleware that prints request path and given prefix.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">class</span> <span class="nc">Logger</span> <span class="kd">implements</span> <span class="n">Middleware</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">String</span> <span class="n">prefix</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">Logger</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">prefix</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="err">@</span><span class="n">override</span>
</span></span><span class="line"><span class="cl">  <span class="n">Future</span><span class="o">&lt;</span><span class="n">Function</span><span class="o">&gt;</span> <span class="n">execute</span><span class="p">(</span><span class="n">Function</span> <span class="n">next</span><span class="p">,</span> <span class="n">Context</span> <span class="n">context</span><span class="p">)</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">Context</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">$</span><span class="n">prefix</span><span class="s1">: Path: </span><span class="si">${</span><span class="n">context</span><span class="p">.</span><span class="n">path</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="c1">// Don&#39;t forget to call the handler.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="k">return</span> <span class="n">next</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">main</span><span class="p">()</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">final</span> <span class="n">laska</span> <span class="o">=</span> <span class="n">Laska</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">final</span> <span class="n">acl_middleware</span> <span class="o">=</span> <span class="n">Acl</span><span class="p">([</span><span class="s1">&#39;admin&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Add global middleware
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="n">laska</span><span class="p">.</span><span class="n">Use</span><span class="p">(</span><span class="n">Logger</span><span class="p">(</span><span class="s1">&#39;global&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Create handler with per-route middlewares: logger and acl
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="n">laska</span><span class="p">.</span><span class="n">GET</span><span class="p">(</span><span class="s1">&#39;/secret&#39;</span><span class="p">,</span> <span class="n">secretHandler</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nl">middlewares:</span> <span class="p">{</span><span class="n">Logger</span><span class="p">(</span><span class="s1">&#39;route&#39;</span><span class="p">),</span> <span class="n">acl_middleware</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Add route handler, only global middleware will apply
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="n">laska</span><span class="p">.</span><span class="n">GET</span><span class="p">(</span><span class="s1">&#39;/users&#39;</span><span class="p">,</span> <span class="n">getUsers</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Add route with acl middleware, but only for the POST method.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="n">laska</span><span class="p">.</span><span class="n">POST</span><span class="p">(</span><span class="s1">&#39;/users&#39;</span><span class="p">,</span> <span class="n">getUsers</span><span class="p">,</span> <span class="nl">middlewares:</span> <span class="p">{</span><span class="n">acl_middleware</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kd">await</span> <span class="n">run</span><span class="p">(</span><span class="n">laska</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">secretHandler</span><span class="p">(</span><span class="n">Context</span> <span class="n">context</span><span class="p">)</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">await</span> <span class="n">context</span><span class="p">.</span><span class="n">Text</span><span class="p">(</span><span class="s1">&#39;You have access to secret path!&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">getUsers</span><span class="p">(</span><span class="n">Context</span> <span class="n">context</span><span class="p">)</span> <span class="kd">async</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">await</span> <span class="n">context</span><span class="p">.</span><span class="n">JSON</span><span class="p">([</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s1">&#39;id&#39;</span><span class="o">:</span> <span class="m">1</span><span class="p">,</span> <span class="s1">&#39;name&#39;</span><span class="o">:</span> <span class="s1">&#39;Make something useful&#39;</span><span class="p">,</span> <span class="s1">&#39;status&#39;</span><span class="o">:</span> <span class="m">0</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s1">&#39;id&#39;</span><span class="o">:</span> <span class="m">2</span><span class="p">,</span> <span class="s1">&#39;name&#39;</span><span class="o">:</span> <span class="s1">&#39;Make new website&#39;</span><span class="p">,</span> <span class="s1">&#39;status&#39;</span><span class="o">:</span> <span class="m">1</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">]);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>I hope this code is self-explanatory but you can ask me  any questions  in comments :)</p>
<h2 id="roadmap">Roadmap</h2>
<p>🅿️ - P is for planned.</p>
<ul>
<li>✅ Dynamic routing with placeholders</li>
<li>✅ Middlewares</li>
<li>✅ JSON handling</li>
<li>✅ Form handling</li>
<li>✅ Null-Safety</li>
<li>🅿️ Logging</li>
<li>🅿️ Serve static files</li>
<li>🅿️ Template rendering?</li>
<li>🅿️ Extensions</li>
<li>🅿️ Health checks</li>
<li>❓ What&rsquo;s more?</li>
</ul>
<h2 id="the-end">The end</h2>
<p>I&rsquo;d love to see more server-side Dart projects and hope you do too. If you think so it would be very encouraging if you star the project on <a href="https://github.com/TenderOwl/laska">GitHub</a> and like it on Dev.to.</p>
        ]]></turbo:content></item></channel></rss>