<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: webduvet</title>
    <description>The latest articles on Forem by webduvet (@webduvet).</description>
    <link>https://forem.com/webduvet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F625668%2F6a7c69bf-8a41-4eaa-b1b7-19a8c96e0618.jpeg</url>
      <title>Forem: webduvet</title>
      <link>https://forem.com/webduvet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/webduvet"/>
    <language>en</language>
    <item>
      <title>Trouble shooting docker - permission denied</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Mon, 22 May 2023 16:55:31 +0000</pubDate>
      <link>https://forem.com/webduvet/trouble-shooting-docker-permission-denied-4h17</link>
      <guid>https://forem.com/webduvet/trouble-shooting-docker-permission-denied-4h17</guid>
      <description>&lt;p&gt;After installation or just after a an OS update or some package update docker engine starts to complain about insufficient permissions.&lt;br&gt;
Particularly it complains about permission to access &lt;code&gt;/var/run/docker.sock&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
// permission denied message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /var/run/docker.sock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output should show root:docker as {ownder}:{group}.&lt;br&gt;
Run also&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -l /lib/systemd/system/docker.socket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output should show root:docker as {ownder}:{group}.&lt;br&gt;
If it shows root:root there is a problem&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chgrp &lt;/span&gt;docker /lib/systemd/system/docker.socket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;groups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Current user should be member of these groups: &lt;code&gt;docker&lt;/code&gt;, &lt;code&gt;kvm&lt;/code&gt;.&lt;br&gt;
if the &lt;code&gt;docker&lt;/code&gt; group doesn't exist add it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo groupadd docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the new group is added or the group is there but current user is not a member, add it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; kvm &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current user now should be visible in group file &lt;code&gt;/etc/group&lt;/code&gt;&lt;br&gt;
or when running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;getent group
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or simply&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;groups&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If not try running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su $USER -c groups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the list of groups contain &lt;code&gt;kvm&lt;/code&gt; and &lt;code&gt;docker&lt;/code&gt; you need to log out and log back in or somehow restart &lt;code&gt;system-auth&lt;/code&gt;.&lt;br&gt;
After that it should work or there is further problem unrelated to the above.&lt;/p&gt;

&lt;h2&gt;
  
  
  verify
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>docker</category>
      <category>linux</category>
    </item>
    <item>
      <title>Deferred Promise Queue</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Sun, 09 Apr 2023 10:29:16 +0000</pubDate>
      <link>https://forem.com/webduvet/deferred-promise-queue-2eej</link>
      <guid>https://forem.com/webduvet/deferred-promise-queue-2eej</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;I recently published a simple npm package to defer the execution of collection of promise based asynchronous calls. &lt;/p&gt;

&lt;p&gt;If you ever had to do multiple async calls returning a promise object, but the service or client machine was not able to handle all calls concurrently, there are chances that something like this was used.&lt;/p&gt;

&lt;p&gt;An obvious use case would be getting data from the remote API page by page and it is not uncommon that it could be hundreds if not thousands pages long (which was by the way the initial motivation to create the library at first place).&lt;/p&gt;

&lt;h2&gt;
  
  
  Deferred pattern
&lt;/h2&gt;

&lt;p&gt;At the core of the implementation is something which could be described as deferred Promise. We can work with an array of Promises hundreds or thousands items long, but we can't trigger them at the same time. So the the async function calls need to be deferred until the system is able to process them. How to do that I explained in this article about &lt;a href="https://dev.to/webduvet/deferred-promise-pattern-2j59"&gt;Deferred Promise&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Publish - subscribe
&lt;/h2&gt;

&lt;p&gt;The second piece in the puzzle is to implement ability to throttle the calls. &lt;br&gt;
Under the hood this is done by implementing publish-subscribe pattern and schedule-task pattern.&lt;br&gt;
The entire flow is triggered by calling start method which in turn emits event that the queue is available to take a call. (Fig.1). Promise Queue is scheduling the individual async function calls periodically (Fig.2) until the buffer is filled. Buffer here is the limit on currently pending promises. Once this limit is reached the scheduler postpones the next task until at least one pending promise is converted to settled (Fig.3).&lt;/p&gt;
&lt;h2&gt;
  
  
  Flow Chart
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Fig.1, Initial call&lt;/em&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iRBu0NRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpc3zrg0q7ra6z1pfcpk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iRBu0NRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpc3zrg0q7ra6z1pfcpk.png" alt="Fig.1, Initial call" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fig.2, periodic loop&lt;/em&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ORRLCv5M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jb3ghli77u9eij2cxt29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ORRLCv5M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jb3ghli77u9eij2cxt29.png" alt="Fig.2, periodic loop, check buffer" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fig.3, coming back from blocked queue&lt;/em&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2S5Yhij6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7xj774nsuvaroi7fm4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2S5Yhij6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7xj774nsuvaroi7fm4a.png" alt="Fig.3, unblock queue flow" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that all the parts (apart beginning) starts and end with emitting an event. This allows to add multiple consumers e.g. for logging or debugging.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;If anybody find this useful I wrapped all of the above in the platform agnostic &lt;code&gt;npm package&lt;/code&gt;, which can be installed by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;prmsq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basic usage example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// fetchPage(pageNumber) is http call returning promise&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;workload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pageNo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fetchPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageNo&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delayBetweenCalls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;concurentLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PrmsQ&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delayBetweenCalls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;concurentLimit&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doWhenAllSettled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleProblem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;pq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also can be found on &lt;a href="https://github.com/webduvet/prmsq"&gt;github.com/webduvet/prsmq&lt;/a&gt;&lt;br&gt;
with the example in &lt;code&gt;/src/example/&lt;/code&gt;&lt;/p&gt;

</description>
      <category>promise</category>
      <category>async</category>
      <category>javascript</category>
      <category>deferred</category>
    </item>
    <item>
      <title>Deferred (promise) pattern</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Sat, 08 Apr 2023 18:25:12 +0000</pubDate>
      <link>https://forem.com/webduvet/deferred-promise-pattern-2j59</link>
      <guid>https://forem.com/webduvet/deferred-promise-pattern-2j59</guid>
      <description>&lt;p&gt;&lt;strong&gt;Deferred&lt;/strong&gt; pattern is one of the most commonly used design patterns in JavaScript world and in programming in general. It postpones the action to a later stage for whatever reason, but mostly because the expected value is not available yet. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;Promise&lt;/a&gt; falls nicely to this category. It boxes the future value and provides a way to unbox it whether it realizes (then) or fails (catch). The basic usage reveals how the Promise pattern does work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;asyncCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;successHandler&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rejectHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New Promise object is constructed and the resolver function is called some time in the constructor. From inside resolver function the asynchronous call is triggered and once the result comes back the status of the Promise changes from &lt;em&gt;pending&lt;/em&gt; to &lt;em&gt;settled&lt;/em&gt; by calling &lt;code&gt;reject&lt;/code&gt; or &lt;code&gt;resolved&lt;/code&gt;. At that point any callback provided by calling &lt;code&gt;.than()&lt;/code&gt; pipe is executed in the same order how they were registered.&lt;/p&gt;

&lt;p&gt;From the above is evident that the programmer or user has limited control when the promise settlement start to happen. Calling the constructor makes the things moving right away. Of course unless we inject some handlers from calling scope or we close over the provided &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; levers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeDeferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new object contains &lt;code&gt;promise&lt;/code&gt; and the handlers to &lt;code&gt;reject&lt;/code&gt; or &lt;code&gt;resolve&lt;/code&gt; it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. In the simple form and shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deferred as subclass of Promise
&lt;/h2&gt;

&lt;p&gt;The disadvantage if this approach is &lt;em&gt;hacky&lt;/em&gt; implementation. The Promise object needs to be &lt;em&gt;thenable&lt;/em&gt; and as per specification it needs to return the Promise object instantiated from the same class as the calling object. This means internally the constructor is called with standard resolver method which we need to support. Hence the check for the resolver argument. Also it is going against type definition where &lt;code&gt;Promise&lt;/code&gt; expects resolver function in the constructor. Secondly we are robbing ourselves from any potential native performance optimization regarding &lt;code&gt;Promise&lt;/code&gt; class or it's instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DeferredPromise&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DeferredPromise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doStuffWithValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this is not recommended, it might be sometimes useful if you have existing middle-ware pipeline working with promise objects and you can get away with dodgy typing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deferred as result of a factory function
&lt;/h2&gt;

&lt;p&gt;Building on the original principle, much cleaner and recommended approach is to user factory method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Defer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_resolve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;_resolve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;_reject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;_resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;_reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;workload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_p&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Defer&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// in some class or API expecting Promise value&lt;/span&gt;
&lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doStuffWithValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// some later stage in app&lt;/span&gt;
&lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation takes the async function returning a Promise and returns the new Promise object wrapping the future promise object returned from the async function and the handler to allow as to trigger the async function in the future.&lt;/p&gt;

&lt;p&gt;We can see that the &lt;code&gt;_reject&lt;/code&gt; and &lt;code&gt;_resolve&lt;/code&gt; variables are closed over and the &lt;code&gt;resolve&lt;/code&gt; resp &lt;code&gt;reject&lt;/code&gt; handlers from the Promise implementation are assigned.&lt;br&gt;
&lt;code&gt;trigger&lt;/code&gt; method implements simple caching in case it gets called multiple times.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;If anybody find this useful I wrapped all of the above in the platform agnostic &lt;code&gt;npm package&lt;/code&gt;, which can be installed by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;deferable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or it can be found on &lt;a href="https://github.com/webduvet/deferable.git"&gt;github/webduvet/deferable.git&lt;/a&gt;. It offers both the Class flavor as well as the Factory flavor.&lt;/p&gt;

&lt;p&gt;Deferred Promise pattern has many use cases e.g. api call throttling, user input de-bounce, user action timeout etc.&lt;/p&gt;

&lt;p&gt;In this the next article I elaborate one particular use case of Deferred Promise pattern - throttling the async calls.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>promise</category>
    </item>
    <item>
      <title>Vim: ignore casing in search</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Mon, 09 Jan 2023 13:07:15 +0000</pubDate>
      <link>https://forem.com/webduvet/vim-ignore-casing-in-search-594n</link>
      <guid>https://forem.com/webduvet/vim-ignore-casing-in-search-594n</guid>
      <description>&lt;p&gt;escape sequence anywhere in the pattern &lt;code&gt;\c&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;/\ccmake
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will match &lt;code&gt;cmake&lt;/code&gt; and &lt;code&gt;CMake&lt;/code&gt; or &lt;code&gt;cMake&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;/&lt;span class="k"&gt;c&lt;/span&gt;\cmake
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will match &lt;code&gt;cMake&lt;/code&gt; and &lt;code&gt;cmake&lt;/code&gt; but not &lt;code&gt;CMake&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;the inverse of &lt;code&gt;\c&lt;/code&gt; is &lt;code&gt;\C&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;/\&lt;span class="k"&gt;cc&lt;/span&gt;\CMake
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will match &lt;code&gt;CMake&lt;/code&gt; and &lt;code&gt;cMake&lt;/code&gt; but not &lt;code&gt;cmake&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  further options:
&lt;/h3&gt;

&lt;p&gt;This will ignore casing in all searching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:set ignorecase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;unset with &lt;code&gt;no&lt;/code&gt; prefix as usual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:set noignorecase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the above this will ignore casing if search string is all lowercase, but will be case sensitive if the search string contains any upper case letter. The &lt;code&gt;ignorecase&lt;/code&gt; must me set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:set smartcase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>vim</category>
    </item>
    <item>
      <title>Scanning for open ports</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Wed, 04 Jan 2023 12:13:47 +0000</pubDate>
      <link>https://forem.com/webduvet/scanning-for-open-ports-5dco</link>
      <guid>https://forem.com/webduvet/scanning-for-open-ports-5dco</guid>
      <description>&lt;h2&gt;
  
  
  lsof
&lt;/h2&gt;

&lt;p&gt;list of open files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;LISTEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  netstat
&lt;/h2&gt;

&lt;p&gt;Print network connections, routing tables, interface statistics, masquerade connections, and multicast memberships&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netstat &lt;span class="nt"&gt;-tulpn&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;LISTEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ss
&lt;/h2&gt;

&lt;p&gt;utility to investigate sockets&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ss &lt;span class="nt"&gt;-tulpn&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;LISTEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  nmap
&lt;/h2&gt;

&lt;p&gt;network exploration tool, port scanner&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;-open&lt;/span&gt; 192.168.3.34
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  scanning open ports on remote IP address
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-zv&lt;/span&gt; 192.168.3.34 2&amp;gt;&amp;amp;1 1-1024 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this scans open ports in the range of 1 to 1024 on the above IP address.&lt;br&gt;
redirects the error output to standard outoput and matches all lines except refused&lt;/p&gt;

&lt;h2&gt;
  
  
  scanning all open ports on the subnet using nmap
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;-n&lt;/span&gt; 192.168.3.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linux for Networking Professionals&lt;/strong&gt; by Rob VandenBrink&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyberciti.biz/faq/unix-linux-check-if-port-is-in-use-command/"&gt;https://www.cyberciti.biz/faq/unix-linux-check-if-port-is-in-use-command/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;man pages&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>bash</category>
    </item>
    <item>
      <title>Setting up private network with a gateway</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Wed, 21 Dec 2022 01:02:55 +0000</pubDate>
      <link>https://forem.com/webduvet/setting-up-private-network-with-a-gateway-1dln</link>
      <guid>https://forem.com/webduvet/setting-up-private-network-with-a-gateway-1dln</guid>
      <description>&lt;h3&gt;
  
  
  Building a Kubernetes cluster at home, part One.
&lt;/h3&gt;

&lt;p&gt;This chapter will focus on the preparation work. I will wire all computers together and I configure one of my laptops to serve as an access point to the cluster and also it will serve as a gateway from the cluster to the outside world. I already gathered about 5 old computers and a simple non-managed Ethernet switch with 5 ports. I will start with the simplest possible solutions and will add complexity as goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1
&lt;/h2&gt;

&lt;p&gt;Plugin the first laptop. This one will serve as a gateway as it has two network interfaces. Wifi will interface with my router network and the Ethernet will interface private network. When you connect your laptop to your home WIFI, it usually will obtain the dynamic IP address from a router, something like 192.168.0.15. The router is set as the default gateway for all internet traffic. When you plug in the computer with an Ethernet cable, it does the same (minus the WIFI security bit). The operating system usually activates only one network interface (Ethernet takes precedes if both are present). In our case, we need to enable both so the machine can communicate with the cluster and with me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mnode@mnode:~&lt;span class="nv"&gt;$ &lt;/span&gt;ip address show
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    &lt;span class="nb"&gt;link&lt;/span&gt;/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
        valid_lft forever preferred_lft forever
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    &lt;span class="nb"&gt;link&lt;/span&gt;/ether 49:ba:4e:4a:eb:c5 brd ff:ff:ff:ff:ff:ff
    altname enp1s0
    inet 192.168.3.34/24 brd 192.168.3.255 scope global eth0
        valid_lft forever preferred_lft forever
    inet6 fc80::4aba:4eff:fe39:ebc5/64 scope &lt;span class="nb"&gt;link
        &lt;/span&gt;valid_lft forever preferred_lft forever
3: wlan0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default qlen 1000
    &lt;span class="nb"&gt;link&lt;/span&gt;/ether da:64:6a:9f:cd:1f brd ff:ff:ff:ff:ff:ff
    altname wlp2s0
    inet 192.168.1.5/24 metric 600 brd 192.168.1.255 scope global dynamic wlan0
        valid_lft 86379sec preferred_lft 86379sec
    inet6 fe80::d66a:6aff:fe9c:cd1f/64 scope &lt;span class="nb"&gt;link
        &lt;/span&gt;valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above is the list of all available network interfaces. Those interesting for us are &lt;code&gt;eth0&lt;/code&gt; which is the Ethernet interface and &lt;code&gt;wlan0&lt;/code&gt; which is WIFI. from the above list we can see that Ethernet is in the state &lt;strong&gt;DOWN&lt;/strong&gt;. For comparison the wireless LAN is wlan0 and the state is &lt;strong&gt;UP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Running the following command will turn on the networking interface: &lt;code&gt;sudo ip link set eth0 up&lt;/code&gt; Running &lt;code&gt;ip address show&lt;/code&gt; again will show that the &lt;code&gt;eth0&lt;/code&gt; interface is now with the flag &lt;code&gt;UP&lt;/code&gt;, so the operation worked. However, doing this on the Ubuntu desktop might result in the operating system (Ubuntu) reporting an error message activation &lt;code&gt;of network connection failed Ubuntu&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is because Ubuntu Desktop uses &lt;strong&gt;NetworkManager&lt;/strong&gt; to manage all the network interfaces by default. It is the application responsible for network management via UI. This is not the case in Ubuntu Server which I will be using. The documentation can be found here &lt;a href="https://wiki.gnome.org/Projects/NetworkManager" rel="noopener noreferrer"&gt;NetworkManager&lt;/a&gt; It can be completely turned off by choosing a different renderer or a specific networking interface can be excluded from under the management of NetworkManager. The configuration is in the file &lt;code&gt;/etc/NetworkManager/NetworkManager.conf&lt;/code&gt;. On UI-less versions like Ubuntu Server, there is no NetworkManager installed. The default network renderer is systemd-networkd. In both flavors of Ubuntu, the networking configuration is done via &lt;a href="https://netplan.io/" rel="noopener noreferrer"&gt;Netplan&lt;/a&gt; and the configuration for Netplan is stored in &lt;em&gt;yaml&lt;/em&gt; file in the location &lt;code&gt;/etc/netplan/*.yaml&lt;/code&gt;. There could be more than one configuration file. More information on this are to be found in the provided link.&lt;/p&gt;

&lt;p&gt;The default configuration on the Ubuntu desktop might look like this and it basically tells the system that NetworkManager manages all networking devices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;renderer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkManager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there is no renderer specified, Ubuntu by default uses systemd-networkd as the network renderer. We want to customize values for the gateway and the static IP address as we need to manage two separate network interfaces and we need to have them &lt;code&gt;UP&lt;/code&gt; at the same time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;wifis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;wlan0&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;dhcp4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="na"&gt;dhcp6&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="na"&gt;access-points&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WIFI-Name"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wifi_password"&lt;/span&gt;
    &lt;span class="na"&gt;ethernets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;eth0&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;dhcp4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
            &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;192.168.3.34/24&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
            &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;via&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.1.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above configuration tells the system that both interfaces are managed (by default) by &lt;strong&gt;systemd-networkd&lt;/strong&gt; specifies the access point for WIFI and password. It specifies that WIFI takes the IP address from the router for both ipv4 and ipv6 protocols. It specifies that the Ethernet interface does not try to obtain IP addresses from DHCP server and takes the hard-coded one. The format 192.168.3.34/24 specifies that the IP address in the domain 192.168.3.xx and the address 192.168.3.34 within the domain. There is a lot that can be done configuring the netplan.&lt;/p&gt;

&lt;p&gt;NOTE: for the desktop version turning off the NetworkManager results in an inability to select the network from the dropdown menu in the taskbar.&lt;/p&gt;

&lt;p&gt;An important part is that the Wifi subnet is not clashing with the ethernet subnet. In my case wifi runs on &lt;code&gt;192.168.1.0/24&lt;/code&gt; and I set up the ethernet IP to &lt;code&gt;192.168.3.0/24&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After this netplan's new configuration needs to be applied bash sudo &lt;code&gt;netplan apply&lt;/code&gt; In case this is done on the Ubuntu desktop, there might be a message &lt;code&gt;systemd-networkd not running, output will be incomplete&lt;/code&gt;. this indicates the network manager is not managing the network anymore, but &lt;em&gt;the default networkd&lt;/em&gt; is not running yet. it needs to be started &lt;code&gt;bash systemctl start systemd-networkd&lt;/code&gt; I have to note also that to setup the Ubuntu server is much simpler as there is no &lt;strong&gt;NetworkManager&lt;/strong&gt; and the &lt;strong&gt;systemd-networkd&lt;/strong&gt; is a default network renderer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2, adding another compouter to cluster
&lt;/h2&gt;

&lt;p&gt;This should be fairly simple. For me the second guinea pig is raspberry pi3, running Ubuntu for raspberry, not too dissimilar to the Ubuntu server. The only configuration which I need to do here is to assign a static IP address and point to the default gateway: &lt;code&gt;yaml network: version: 2 ethernets: eth0: dhcp4: false addresses: [192.168.3.40/24]&lt;/code&gt; after &lt;code&gt;bash sudo netplan apply&lt;/code&gt; I can reach the Raspberry node from the gateway laptop and vice versa. I also can reach the gateway laptop on the Wifi domain. I should be good to go to plug in the rest of the computers and do the same to them After that I could start installing k3s and build the Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;It is also worth noting - when you are building the cluster out of old laptops - it is handy to prevent them to go sleep or hibernate when the lid is closed. That way is is possible to stack them on each other to save the space.&lt;br&gt;
On Ubuntu server as per &lt;a href="https://manpages.ubuntu.com/manpages/kinetic/en/man5/systemd-sleep.conf.5.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; this needs to be added to &lt;code&gt;/etc/systemd/sleep.conf&lt;/code&gt; or preferably new file in the location &lt;code&gt;/etc/systemd/sleep.conf.d/00-sleep.conf&lt;/code&gt; to be created as it takes precedence over default configuration in the former file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;[&lt;span class="n"&gt;Sleep&lt;/span&gt;]
&lt;span class="n"&gt;AllowSuspend&lt;/span&gt;=&lt;span class="n"&gt;no&lt;/span&gt;
&lt;span class="n"&gt;AllowHibernation&lt;/span&gt;=&lt;span class="n"&gt;no&lt;/span&gt;
&lt;span class="n"&gt;AllowSuspendThenHibernate&lt;/span&gt;=&lt;span class="n"&gt;no&lt;/span&gt;
&lt;span class="n"&gt;AllowHybridSleep&lt;/span&gt;=&lt;span class="n"&gt;no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3, optional - internet access
&lt;/h2&gt;

&lt;p&gt;However, there is one more thing I wanted to do. It is not essential and perhaps even not recommended, but for my convenience want to have a connection to the internet from the individual machines in the cluster. This will help me with the installation of the required software on individual nodes. This is not a production environment so I can easily get away with it. The same scenario would apply if you had a desktop machine without WIFI. You could use a laptop to connect to WIFI and use the laptop's Ethernet interface to connect with your desktop and to serve as a router.&lt;/p&gt;

&lt;p&gt;To do this we need to add a few rules in IP tables. We need to forward all internet traffic from ethernet to wifi interface and back. We also want to set up network address translation(NAT). For Linux operating system to enable IP forwarding. This can typically be done by editing the &lt;code&gt;/etc/sysctl.conf&lt;/code&gt; file and adding the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;net.ipv4.ip_forward = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or run &lt;code&gt;sysctl -w net.ipv4.ip_forward=1&lt;/code&gt; We also need to add the following rules in the ip tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-A&lt;/span&gt; FORWARD &lt;span class="nt"&gt;-i&lt;/span&gt; eth0 &lt;span class="nt"&gt;-o&lt;/span&gt; wlan0 &lt;span class="nt"&gt;-j&lt;/span&gt; ACCEPT
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; POSTROUTING &lt;span class="nt"&gt;-o&lt;/span&gt; eth0 &lt;span class="nt"&gt;-j&lt;/span&gt; MASQUERADE
iptables &lt;span class="nt"&gt;-A&lt;/span&gt; FORWARD &lt;span class="nt"&gt;-i&lt;/span&gt; wlan0 &lt;span class="nt"&gt;-o&lt;/span&gt; eth0 &lt;span class="nt"&gt;-m&lt;/span&gt; state &lt;span class="nt"&gt;--state&lt;/span&gt; RELATED,ESTABLISHED &lt;span class="nt"&gt;-j&lt;/span&gt; ACCEPT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The first rule forwards all the traffic coming from the individual machines on our subnet to out via wireless LAN.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the second adds a record to NAT table to masquerade packets coming from the individual machines from the private subnet via the gateway laptop as packets coming from the gateway laptop itself (the home router does the same thing again when you are reaching out to the internet)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The third rule forwards all the traffic originating from the individual machines back to them&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save your IP tables rules and make sure they are automatically loaded at startup. This can typically be done by using the &lt;code&gt;iptables-save&lt;/code&gt; and &lt;code&gt;iptables-restore&lt;/code&gt; commands. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables-save &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/iptables.rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the /etc/rc.local file and add the following line before the exit 0 line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables-restore &amp;lt; /etc/iptables.rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this is done it should be possible to access the internet from a machine connected to an Ethernet switch provided the configuration in step 2 is followed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;After the above steps, I do have a cluster of computers wired together via an Ethernet switch. The computers share a private network and can communicate with each other. The private network is connected to the router via a wireless connection and the internet is also reachable from inside the private network.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>microservices</category>
      <category>architecture</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Efficiently Finding and Replacing Text in Multiple Files Using ripgrep and sed</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Tue, 13 Dec 2022 23:52:35 +0000</pubDate>
      <link>https://forem.com/webduvet/efficiently-finding-and-replacing-text-in-multiple-files-using-ripgrep-and-sed-3anl</link>
      <guid>https://forem.com/webduvet/efficiently-finding-and-replacing-text-in-multiple-files-using-ripgrep-and-sed-3anl</guid>
      <description>&lt;h2&gt;
  
  
  subtitle
&lt;/h2&gt;

&lt;p&gt;Convenient way to search for and replace text in multiple files using the powerful ripgrep and sed tools&lt;/p&gt;

&lt;h2&gt;
  
  
  command
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rg &lt;span class="s2"&gt;"some string"&lt;/span&gt; | xargs &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"s/some string/another string/g"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command searches for the specified string using ripgrep and pipes the results to xargs, which executes the sed command on each line returned by ripgrep. The sed command then replaces each occurrence of "find-string" with "new string" in the specified files.&lt;/p&gt;

&lt;p&gt;Here's the breakdown of the command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rg "find-string"&lt;/code&gt;: This uses &lt;strong&gt;ripgrep&lt;/strong&gt; to search for the string "find-string" in the current directory and all its subdirectories.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;|&lt;/code&gt;: This pipes the output of the previous command (the list of files containing "find-string") to the next command.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;xargs -d "\n"&lt;/code&gt;: This takes the output from the previous command and passes it as arguments to the &lt;strong&gt;sed&lt;/strong&gt; command. The -d option narrows down the delimiter to a newline character, so that each line returned by &lt;strong&gt;ripgrep&lt;/strong&gt; is passed as a separate argument to &lt;strong&gt;sed&lt;/strong&gt;. By default it uses new line characters as well as spaces&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sed -i "s/find-string/new string/g"&lt;/code&gt;: This is the &lt;strong&gt;sed&lt;/strong&gt; command, which replaces each occurrence of "find-string" with "new string" in the specified files. The -i option tells &lt;strong&gt;sed&lt;/strong&gt; to edit the files in-place, so the changes are saved directly to the original files. The s command is the substitute command, which performs search and replace operations on the specified files. The g flag at the end tells &lt;strong&gt;sed&lt;/strong&gt; to replace all occurrences of the search string, rather than just the first one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.man7.org/linux/man-pages/man1/sed.1.html" rel="noopener noreferrer"&gt;sed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://man7.org/linux/man-pages/man1/xargs.1.html" rel="noopener noreferrer"&gt;xargs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/BurntSushi/ripgrep" rel="noopener noreferrer"&gt;ripgrep&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to manage versions using update-alternatives</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Thu, 24 Nov 2022 10:05:37 +0000</pubDate>
      <link>https://forem.com/webduvet/how-to-manage-versions-using-update-alternatives-258e</link>
      <guid>https://forem.com/webduvet/how-to-manage-versions-using-update-alternatives-258e</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Recently I needed to run the end to end tests in the older chrome browser as the tool the chrome driver available to me was only working with the older version of chrome.&lt;br&gt;
The solution instead of downgrading my chrome installation was to install multiple versions of chrome-browser. More on this in my recent article &lt;a href="https://dev.to/webduvet/where-and-how-to-get-hands-on-an-older-versions-of-google-chrome-4dj7"&gt;how and where to get older versions of google-chrome&lt;/a&gt;.&lt;br&gt;
Long story short, I would like to be able to &lt;em&gt;hotswap&lt;/em&gt; the chrome version. Any python, node or java developer most likely uses some type or form of version manager. In java world people might be using &lt;code&gt;sdkman&lt;/code&gt; [&lt;a href="http://www.sdkman.org"&gt;www.sdkman.org&lt;/a&gt;] or node js world us used &lt;code&gt;nvm&lt;/code&gt; &lt;a href="http://github/nvm"&gt;www.getnvm.org&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is update-alternatives
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;update-alternatives creates, removes, maintains and displays&lt;br&gt;
       information about the symbolic links comprising the Debian&lt;br&gt;
       alternatives system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is a tool provided by Debian based distributions which is designed to help to manage multiple versions or different implementations of a command or program, read more on &lt;a href="https://wiki.debian.org/DebianAlternatives"&gt;Debian Alternatives&lt;/a&gt;. Update-alternatives in Debian based system like Ubuntu is used as default option by &lt;code&gt;apt&lt;/code&gt;, however, it offers the command-line interface to interact with the settings and to add and remove entries manually.&lt;/p&gt;

&lt;p&gt;It can also provide functionality to update something what is called slave links to cater for associated software or manual pages which also need to change when the main target changes.&lt;br&gt;
 The analogy in the nodejs world would be corresponding &lt;code&gt;npm&lt;/code&gt; installation or in python world it would be corresponding &lt;code&gt;pip&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to install another version with update-alternatives
&lt;/h2&gt;

&lt;p&gt;if you plan to use &lt;strong&gt;update-alternavives&lt;/strong&gt; to e.g. install the multiple node versions you will download the desired version and unpack it in the directory of the choice In my case I need older version of google chrome so it would be  &lt;code&gt;/opt/google/chromium/1027016/chrome-linux/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This will contain binary &lt;code&gt;/opt/google/chromium/1027016/chrome-linux/chrome&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;if you already have &lt;code&gt;chrome&lt;/code&gt; installed and you did that from the Debian package by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;google-chrome-stable.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;your already have used &lt;code&gt;update-alternatives&lt;/code&gt; and running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;update-alternatives &lt;span class="nt"&gt;--display&lt;/span&gt; google-chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will show output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;google-chrome - auto mode
&lt;span class="nb"&gt;link &lt;/span&gt;best version is /usr/bin/google-chrome-stable
&lt;span class="nb"&gt;link &lt;/span&gt;currently points to /usr/bin/google-chrome-stable
&lt;span class="nb"&gt;link &lt;/span&gt;google-chrome is /usr/bin/google-chrome
/usr/bin/google-chrome-stable - priority 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This indicates that there is only one version of google-chrome and it shows the location and priority for auto mode (the higher version takes precedence).&lt;br&gt;
I don't want to go into too much detail here as it could be found in man pages or online &lt;a href="https://wiki.debian.org/DebianAlternatives"&gt;debian alternatives&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Running the following lists the existing links stored by update-alternatives.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;update-alternatives &lt;span class="nt"&gt;--list&lt;/span&gt; google-chrome

?&amp;gt; /usr/bin/google-chrome-stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see also here that there is only one. If we follow the symbolic links and investigate further we get to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/usr/bin/google-chrome &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/alternatives/google-chrome
/etc/alternatives/google-chrome &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /usr/bin/google-chrome-stable
/usr/bin/google-chrome-stable &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /opt/google/chrome/google-chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last one is hard link to executable file and paint a pretty clear picture how the update-alternatives work. &lt;code&gt;/usr/bin/google-chrome-stable&lt;/code&gt; is an executable and &lt;code&gt;/usr/bin/google-chrome&lt;/code&gt; is a symbolic link to the executable so we can just type &lt;code&gt;google-chrome&lt;/code&gt; and it starts the browser. &lt;strong&gt;Update-alternatives&lt;/strong&gt; sticks in an extra layer of symbolic links in the middle of which it has the full control.&lt;/p&gt;

&lt;p&gt;To add another version to it execute the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-alternatives &lt;span class="nt"&gt;--install&lt;/span&gt; /usr/bin/google-chrome google-chrome /opt/google/chromium/1027016/chrome-linux/chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you want to use this as default link in auto mode you can add the priority number at the end, higher number takes precedence. For manual intervention enter the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-alternatives &lt;span class="nt"&gt;--config&lt;/span&gt; google-chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output (depending on given priority nubmer this might differ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;There are 2 choices &lt;span class="k"&gt;for &lt;/span&gt;the alternative google-chrome &lt;span class="o"&gt;(&lt;/span&gt;providing /usr/bin/google-chrome&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

Selection    Path                                              Priority   Status
&lt;span class="nt"&gt;------------------------------------------------------------&lt;/span&gt;
  0            /opt/google/chromium/1027016/chrome-linux/chrome   300       auto mode
  1            /opt/google/chromium/1027016/chrome-linux/chrome   300       manual mode
&lt;span class="k"&gt;*&lt;/span&gt; 2            /usr/bin/google-chrome-stable                      200       manual mode

Press &amp;lt;enter&amp;gt; to keep the current choice[&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, or &lt;span class="nb"&gt;type &lt;/span&gt;selection number:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you choose one option the link will no longer be in auto mode, but you can return anytime to automode by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-alternative &lt;span class="nt"&gt;--auto&lt;/span&gt; google-chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  slave links
&lt;/h2&gt;

&lt;p&gt;As mentioned before, these are associated links which should change when &lt;em&gt;master&lt;/em&gt; link changes. The examples are &lt;strong&gt;node&lt;/strong&gt; and &lt;strong&gt;npm&lt;/strong&gt; or &lt;strong&gt;python&lt;/strong&gt; and &lt;strong&gt;pip&lt;/strong&gt;. It also works with manual pages as some packages install also manual pages. This is also the case when installing google-chrome as deb package as above.&lt;br&gt;
Version managers not based on update-alternatives usually add/edit the entry in &lt;code&gt;manpath&lt;/code&gt; pointing to the correct man page or edit (add) entry in &lt;code&gt;$PATH&lt;/code&gt; environment variable.&lt;br&gt;
&lt;code&gt;update-alternatives&lt;/code&gt; does this via mentioned slave links.&lt;/p&gt;

&lt;p&gt;In case of google-chrome, even though it uses update-alternatives by default, it does feature the manual entry, but it does not use slave links and the installer simply copies the man page in the man location. Which prevents update-alternatives to apply sim link here. However, even though we can't do anything with the hard link we can add another manual entry just for the specific version. I'm install chromium so I would be interested to have &lt;code&gt;chromium manual entry&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;manual entry for google chrome can be found here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;man &lt;span class="nt"&gt;-w&lt;/span&gt; google-chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could manually move man entry for google-chrome-stable elsewhere and let update-alternatives utilize slave links, but we could also add another man entry via slave link to demonstrate flexibility. Let's do it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-alternatives &lt;span class="nt"&gt;--install&lt;/span&gt; /usr/bin/google-chrome google-chrome /opt/google/chromium/chrome-linux/chrome &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--slave&lt;/span&gt; /usr/share/man/man1/chromium.1.gz chromium.1.gz /opt/google/chromium/chromium.1.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this will be following. If we use the &lt;strong&gt;google-chrome-stable&lt;/strong&gt; the manual entry for chromium via &lt;code&gt;man chromium&lt;/code&gt; will not be available, but swapping the version for chromium will make the manual entry for chromium available along the original manual entry which is/was set as hard link (actual file).&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This short articles demonstrate the basic capabilities of the tool &lt;strong&gt;update-alternatives&lt;/strong&gt;. More detail can be found on manual pages or on Debian website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/DebianAlternatives"&gt;debian alternatives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linux.die.net/man/8/update-alternatives"&gt;linux man pages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>updatealternatives</category>
      <category>linux</category>
      <category>bash</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Where and how to get hands on an older versions of google-chrome?</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Thu, 24 Nov 2022 09:57:07 +0000</pubDate>
      <link>https://forem.com/webduvet/where-and-how-to-get-hands-on-an-older-versions-of-google-chrome-4dj7</link>
      <guid>https://forem.com/webduvet/where-and-how-to-get-hands-on-an-older-versions-of-google-chrome-4dj7</guid>
      <description>&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;Recently I needed to run some functional tests against the older version of &lt;strong&gt;chrome&lt;/strong&gt; browser as the chrome-driver available to me (part of the 3rd party test tools) was working only with slightly older version of google-chrome than my current system.&lt;br&gt;
I thought it is easy, I just &lt;em&gt;google&lt;/em&gt; where google stores the old version of their browser, download binaries and point my testing tool to the &lt;em&gt;correct&lt;/em&gt; version.&lt;br&gt;
It turned out that both of my assumptions were hiding some troubles behind and I realized that it is actually not that straightforward to get my hands on the older binaries of the chrome browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to get the old version?
&lt;/h2&gt;

&lt;p&gt;Google had not made available the older version of their chrome browser to public due to security issues which are of course patched in the current version. It is possible to downgrade as per this &lt;a href="https://support.google.com/chrome/a/answer/7125792?hl=en" rel="noopener noreferrer"&gt;thread&lt;/a&gt; up to 3 stable versions back, but that is usually not enough and it is a hassle.&lt;br&gt;
After a little bit of searching I've found this &lt;a href="https://www.slimjet.com/chrome/google-chrome-old-version.php" rel="noopener noreferrer"&gt;www.slimjet.com&lt;/a&gt; website offering plethora of old stable versions releases. It doesn't cover all, only the latest of major versions. That might be just enough and if not there is also chromium &lt;a href="https://www.chromium.org/chromium-projects/" rel="noopener noreferrer"&gt;https://www.chromium.org&lt;/a&gt; project which is essentially identical to chrome. It is available through the chromium snapshots.&lt;br&gt;
The information on how the get them can be found directly on chromium website at &lt;a href="https://www.chromium.org/getting-involved/download-chromium/" rel="noopener noreferrer"&gt;https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html&lt;/a&gt;.&lt;br&gt;
It offers to browse the chromium snapshots by &lt;strong&gt;branch base position&lt;/strong&gt;. However this doesn't tell you a lot if you need a specific version let's say &lt;code&gt;105.0.5195.52&lt;/code&gt;, but you can find corresponding number by using this lookup service at &lt;a href="https://omahaproxy.appspot.com/" rel="noopener noreferrer"&gt;omahaproxy.appspot.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enter the version number you are looking for in the lookup field and get the information like commit number along with branch base position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmj2rysa3pon2rbrifys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmj2rysa3pon2rbrifys.png" alt="Image description" width="615" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take the &lt;strong&gt;Branch Base Position&lt;/strong&gt; and browse the &lt;a href="https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Linux_x64/" rel="noopener noreferrer"&gt;available options&lt;/a&gt; if you need Linux, or lookup the corresponding platform.&lt;br&gt;
If there is none, as the google-chrome released versions might not exactly correspond to chromium releases, try decreasing the branch base position until you find the hit. It might be &lt;code&gt;105.0.5195.0&lt;/code&gt;, which most likely will work with your chrome-driver.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to work with the older versions
&lt;/h2&gt;

&lt;p&gt;I probably should note that using the outdated browser version is not advised, actually the opposite. Therefore functional and end to end testing on an out-dated version is not recommended either if not outright pointless except some edge cases where you are required to cater for a legacy systems.&lt;br&gt;
In my case I needed the older version, specifically two major versions down as my third party test tool doesn't get update that often and it happens, that the available latest chromedriver is not enough to run tests against the latest version of my chrome browser. In theory I could downgrade two versions down and still enjoy the google's support, but it might be just inconvenient. I prefer to work with binaries and leave the browser installation which I use daily most up to date. More on this in my following &lt;a href="https://dev.to/webduvet/how-to-manage-versions-using-update-alternatives-258e"&gt;blog&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.slimjet.com/chrome/google-chrome-old-version.php" rel="noopener noreferrer"&gt;simjet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://omahaproxy.appspot.com/" rel="noopener noreferrer"&gt;lookup by version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html" rel="noopener noreferrer"&gt;chromium released versions snapshots&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>frontend</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Multiple github accounts</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Fri, 14 Oct 2022 21:03:56 +0000</pubDate>
      <link>https://forem.com/webduvet/multiple-github-accounts-55dk</link>
      <guid>https://forem.com/webduvet/multiple-github-accounts-55dk</guid>
      <description>&lt;h2&gt;
  
  
  What is the use case?
&lt;/h2&gt;

&lt;p&gt;Recently my company moved all the repositories from a privately hosted git repository to an enterprise GitHub account. That means all the company repositories have now domain &lt;code&gt;github.com&lt;/code&gt;, the same as all my private ones.&lt;br&gt;
As it soon became evident the company GitHub credentials and associated ssh key would inevitably clash with my private GitHub account on not one, but two fronts. I could not use one instance of my browser to interact with my private and my company's repositories simultaneously. This was easily solved by dedicating one of the browsers (in my case it was opera) to all company matters while I kept Firefox for all my personal related matters. &lt;br&gt;
However as most others I also use ssh key to access git repositories rather than credentials and here I run into few challenges.&lt;/p&gt;
&lt;h2&gt;
  
  
  GIT cli
&lt;/h2&gt;

&lt;p&gt;To make long story short &lt;code&gt;git-cli&lt;/code&gt; uses &lt;code&gt;ssh-agent&lt;/code&gt; to authenticate to git provider. It looks up the cached ssh keys and tries them one by one from top to bottom.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If the key is not cached it will look into the .ssh directory. That's why it will work even if you delete the key pair from there. More on this is to be found on manual pages of &lt;code&gt;ssh-add&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first key which manages successful authentication is to be used even if it doesn't match the organization used in the GitHub URL.&lt;/p&gt;

&lt;p&gt;Here is the URL structure of repository hosted on GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git@github.com:Organisation/repository.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the first ssh key is the private one - none of the company accounts(unless made public) would be accessible.&lt;/p&gt;

&lt;p&gt;If the first ssh key is the company one - everything will work apart accessing the private repos under the private account.&lt;br&gt;
The public repos under private account will still be accessible to clone, but most likely (depending on the repository setup) github will reject any direct changes.&lt;br&gt;
You probably would be able to create a new branch and to open PR albeit not under you private name, but under the name you use on the company account.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution 1 - gitconfig
&lt;/h2&gt;

&lt;p&gt;the solution is using the local &lt;code&gt;.gitconfig&lt;/code&gt; settings.&lt;br&gt;
for private project dedicate a separate folder and create local config file. &lt;/p&gt;

&lt;p&gt;if you are on a linux machine the &lt;em&gt;default&lt;/em&gt; config might be in your home directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/user/home/myname/.gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and all the private "stuff" will need to have a dedicated .config .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/my-private-projects/.gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this is not picked automatically by git. Git does not work the same way as e.g. pip in python&lt;br&gt;
where it would traverse the current and parents direcotries for config.&lt;/p&gt;

&lt;p&gt;It has to be specified in the "main" &lt;code&gt;.gitcofnig&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;user]
    email &lt;span class="o"&gt;=&lt;/span&gt; companyID@company.com
&lt;span class="o"&gt;[&lt;/span&gt;core]
    editor &lt;span class="o"&gt;=&lt;/span&gt; nvim
    sshCommand &lt;span class="o"&gt;=&lt;/span&gt; ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/id_rsa_company
&lt;span class="o"&gt;[&lt;/span&gt;includeIf &lt;span class="s2"&gt;"gitdir:~/private-projects/"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    path &lt;span class="o"&gt;=&lt;/span&gt; ~/private-projects/.gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important bits are &lt;code&gt;user.email&lt;/code&gt; and &lt;code&gt;core.sshCommand&lt;/code&gt;&lt;br&gt;
this way we can instruct github to use specific sshKey for this entire folder and sub-folders.&lt;/p&gt;

&lt;p&gt;If the ssh key is not specified the ssh service will match the first available ssh key working with github domain as described above.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution 2 - ssh config
&lt;/h2&gt;

&lt;p&gt;This solution is using  &lt;code&gt;.ssh/config&lt;/code&gt;. Documentation for &lt;a href="https://www.ssh.com/academy/ssh/config"&gt;ssh config&lt;/a&gt;.&lt;br&gt;
If it doesn't exist (which it probably doesn't if you get this far), create it and add something&lt;br&gt;
along these lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host github-work
    Hostname github.com
    # Username for remote SSH user (For GitHub, everyone uses the name `git`)
    User git
    IdentityFile /home/user/.ssh/id_rsa_company
    IdentitiesOnly yes

Host github.com
    Hostname github.com
    User git
    IdentityFile /home/user/.ssh/id_rsa_private
    IdentitiesOnly yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Few things here is worth to mention, remember this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git@github.com:Organisation/repository.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and your private git repository links are most likely having very a similar form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git@github.com:your-git-name/repository.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The host here is &lt;code&gt;github.com&lt;/code&gt; in both cases. The host &lt;code&gt;github-work&lt;/code&gt; actually could be anything but you would manually need to change the &lt;code&gt;github.com&lt;/code&gt; to something else e.g. &lt;code&gt;github-work&lt;/code&gt; in the &lt;code&gt;.git/config&lt;/code&gt; file of the existing repository, or use it when you are cloning the repository as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github-work:Organisation/repository.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case I left the other repository as &lt;code&gt;github.com&lt;/code&gt; as there would be no further actions needed for all the private repositories already residing on my machine.&lt;br&gt;
You could do it the other way on you work machine or you could use "alias" for both or all organizations you need to access with separate identities.&lt;/p&gt;

</description>
      <category>github</category>
      <category>ssh</category>
      <category>linux</category>
    </item>
    <item>
      <title>Static Content Server with Nodejs without frameworks</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Tue, 21 Sep 2021 11:14:14 +0000</pubDate>
      <link>https://forem.com/webduvet/static-content-server-with-nodejs-without-frameworks-d61</link>
      <guid>https://forem.com/webduvet/static-content-server-with-nodejs-without-frameworks-d61</guid>
      <description>&lt;h1&gt;
  
  
  Static server with Nodejs
&lt;/h1&gt;

&lt;p&gt;This tutorial will walk you through few steps how to set up simple http server for static content using only &lt;strong&gt;nodejs&lt;/strong&gt;. We will add basic features as serving requested resource from file or from memory(cache) and responding with error message when no resource is available. &lt;br&gt;
In reality you will almost never run any http server in this manner however, it might be very helpful to understand what frameworks like &lt;strong&gt;Expressjs&lt;/strong&gt; do under the hood. It also could serve as a very simple testing tool in your local environment.&lt;/p&gt;

&lt;p&gt;Requirements is to have installed &lt;code&gt;nodejs&lt;/code&gt; on the system, preferably newer version (12+). The recommended environment is Unix like machine, but it is not necessary. The target audience is javascript beginner or UI developer who is curious how does http server work in nodejs.&lt;/p&gt;

&lt;p&gt;We will go through the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;setup http server, what is static server&lt;/li&gt;
&lt;li&gt;adding rules how to read the request&lt;/li&gt;
&lt;li&gt;finding resources and caching&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Lets start with the simplest possible
&lt;/h2&gt;

&lt;p&gt;Http server is a network application which listens to incoming network traffic. It is doing so by acquiring some system resources. Specifically it creates the process in the memory which listens to incoming traffic over the network on the dedicated port. To talk to the http server we need the physical address of the computer and the port which the application acquired. Nodejs provides all necessary functionality to do so. Let's have a look how nodesj does it.&lt;/p&gt;

&lt;p&gt;the simplest way how to start and run the most basic http server using nodejs would be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"require('http').createServer((req, res) =&amp;gt; {res.end('hello world')}).listen(3000)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the above code on Linux machine with node installed will start the server.&lt;br&gt;
it can be verified by typing &lt;code&gt;http://localhost:3000&lt;/code&gt; in the browser URL bar.&lt;br&gt;
or by typing the following in new terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; curl http://localhost:3000
// expected response is
hello world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this basic example we can easily see the building stones. We create an object and call the listen which effectively opens up the connection on the given port and it is waiting for the incoming request complying HTTP protocol.&lt;br&gt;
We can test it with &lt;code&gt;netcat&lt;/code&gt; sending a text complying with HTTP GET request header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"GET / HTTP/1.1&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | nc 127.0.0.1 3000
// The expected response is again
HTTP/1.1 200 OK
Date: Tue, 21 Sep 2021 09:59:13 GMT
Connection: keep-alive
Keep-Alive: &lt;span class="nb"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5
Content-Length: 11

hello world%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a little richer because &lt;strong&gt;netcat&lt;/strong&gt; prints just about everything what is received in the response including response header. &lt;code&gt;curl&lt;/code&gt; can do it as well. Go ahead and try using &lt;code&gt;-i&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;The other main component aside &lt;code&gt;createServer()&lt;/code&gt; and &lt;code&gt;listen()&lt;/code&gt; is callback passed into &lt;a href="https://nodejs.org/dist/latest-v16.x/docs/api/http.html#http_http_createserver_options_requestlistener"&gt;createServer&lt;/a&gt;. It contains references to &lt;a href="https://nodejs.org/dist/latest-v16.x/docs/api/http.html#http_class_http_clientrequest"&gt;request&lt;/a&gt; and &lt;a href="https://nodejs.org/dist/latest-v16.x/docs/api/http.html#http_class_http_serverresponse"&gt;response&lt;/a&gt; objects. Working with these two objects we can interact with our http server.&lt;/p&gt;

&lt;p&gt;This article is however not about networking and protocols but tutorial how to build simple static content server using only &lt;strong&gt;nodejs&lt;/strong&gt; and this does not get us too far since it responses with "hello world" to any request. Let's see if we can do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serving response from a file
&lt;/h2&gt;

&lt;p&gt;Let's make one step further in terms of the functionality of our new http server. We are aiming towards the server which can serve static content. The word static here means similar to "static" keyword in javascript. It is something which is already known and defined prior the user request. From the web server we usually referred as static content to files like images, icons, CSS files and so on. So let's server user with the content of the file rather then hard coded message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;staticServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./static_content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// create server object as in previous example&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server listening on port: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in addition, create directory and file &lt;code&gt;./static_content/index.html&lt;/code&gt; containing your content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;
      Hello, this is very simple
    &amp;lt;/h1&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code we define the path where the static content is, in this case it is index.html file we read the file and send the data back to user as a response to client's request.&lt;br&gt;
&lt;code&gt;response.end() executes the above with some [default headers]()&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Finding and serving requested resource
&lt;/h2&gt;

&lt;p&gt;Next in the quest serving the content based on the user request is finding the requested resource our user is asking. The server looks it up and if it exists it serves the content of the file to client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;staticServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./static_content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// create server object as in previous example&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// get the resource from request&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileContents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server listening on port: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;const filePath = path + req.url&lt;/code&gt; show how mapping between the requested resource and the actual resource might work. &lt;code&gt;Path&lt;/code&gt; is relative path to location where our nodejs app is running and &lt;code&gt;req.url&lt;/code&gt; is last bit of the URI identifying what resource user wants.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.example.com/**resource**"&gt;http://www.example.com/**resource**&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching
&lt;/h3&gt;

&lt;p&gt;Let's make one small addition. The cache. When we server the file from a disk it is not a big deal, as it is pretty quick, however if the file would come from some more time expensive resource we want to keep the content of the file for later requests. Here is a very simple example how it can be implemented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;staticServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./static_content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// create server object as in previous example&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// get the resource from request&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileContents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server listening on port: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic error handling and wrap up
&lt;/h2&gt;

&lt;p&gt;In this last section we add some simple error handling. In case the user specifies the resource which is not found in the given location of static content or if the resource in not readable we need to notify the user with an error. The standard way of doing it is to return response with code 404 in the response headers. We also might add some explanation in the content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; 
    &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * lookup content type
 * infer from the extension
 * no extension would resolve in "text/plain"
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;lookupContentType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jpeg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/jpeg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mp4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video/mp4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="cm"&gt;/**
 * plain 404 response
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;send404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error 404: resource not found.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * sending file response
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileContents&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lookupContentType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;))});&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileContents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * serve static content
 * using cache if possible
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;serveStatic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// use cache if there is any&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileExists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// attempt to read the resource only if it exist&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileExists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
          &lt;span class="c1"&gt;// not able to read the resource&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;send404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="nx"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;absPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// resource does not exist&lt;/span&gt;
                &lt;span class="nx"&gt;send404&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;startServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// create server object&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// if no resource is specified use index.html&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;serveStatic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;serveStatic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server listening on port: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can run it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./startServer.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;startServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./static_content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example I added very basic error handling. In the event the resource specified by the user is not found in the static content directory, or it can't be open for reading, the server response with different header with error &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"&gt;code 404&lt;/a&gt; and different content explaining what went wrong.&lt;br&gt;
In order for a browser to understand better what kind of content we are dealing with, it is also a good idea to include some indication about resource &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types"&gt;content type&lt;/a&gt;. In &lt;code&gt;lookupContentType&lt;/code&gt; we can do it just based on the file extension type.&lt;br&gt;
Now if we try &lt;code&gt;pdf&lt;/code&gt; the browser will have no problem opening pdf file instead downloading it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is by no means a robust product, merely a very simplified example how things do work behind the curtain in frameworks like &lt;code&gt;expressjs&lt;/code&gt;. We leveraged the nodejs built in library &lt;code&gt;http&lt;/code&gt; to run simple http server.&lt;br&gt;
We implemented simple routing to find static content in a given location. We also implemented simple in memory caching, content type resolution and basic error handling in case the resource is not found or accessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;If anybody want to build their own server serving static content I would recommend using existing framework. I would also strongly advice looking at least into following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;session and transaction management&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;security, authentication and authorisation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/dist/latest-v16.x/docs/api/http.html"&gt;nodejs/http&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.unix.com/man-page/Linux/1/netcat/"&gt;netcat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol"&gt;http&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"&gt;status codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types"&gt;Common MIME types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pixabay.com"&gt;title image&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Synchronous and asynchronous function composition</title>
      <dc:creator>webduvet</dc:creator>
      <pubDate>Wed, 15 Sep 2021 14:48:17 +0000</pubDate>
      <link>https://forem.com/webduvet/synchronous-and-asynchronous-function-composition-5a20</link>
      <guid>https://forem.com/webduvet/synchronous-and-asynchronous-function-composition-5a20</guid>
      <description>&lt;ul&gt;
&lt;li&gt;what is function composition&lt;/li&gt;
&lt;li&gt;composing simple functions&lt;/li&gt;
&lt;li&gt;composing asynchronous functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this short article I am going to discuss the function composition and how the function composition might work with asynchronous code. I'm going to explain the basic principles of it and give some examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro - Function composition
&lt;/h2&gt;

&lt;p&gt;Javascript is a function friendly language. What we do often is to apply multiple functions in sequence.  Some can say we are chaining the functions,hence the operator called &lt;em&gt;pipe&lt;/em&gt; is often used or some say we are composing functions. This allows for clearly defined flow control and it makes a for a robust and testable code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h(g(f(x)))

//logical representation
x -&amp;gt; f -&amp;gt; g -&amp;gt; h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start with x and we apply functions f, g, h in that sequence. Function composition is not commutative (although some functions can commute), thus the order how we apply functions matters. For more information on this topic see&lt;br&gt;
the sources at the bottom of the is article&lt;/p&gt;
&lt;h2&gt;
  
  
  Composing functions in JavaScript
&lt;/h2&gt;

&lt;p&gt;In this section we go from the basic function composition in JavaScript to more robust approach.&lt;/p&gt;

&lt;p&gt;Example of function composition using synchronous functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;double&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;square&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;half&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dsh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;half&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works nicely, but it is obviously hard to read when we have even slightly more complex logic.&lt;br&gt;
Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hardToRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@space&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is already much harder to read, even if we try a little tidying up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hardToRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
    &lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@space&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
      &lt;span class="nx"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we would have to break some linting rules in order to give it some fasion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hardToRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
  &lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@space&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
  &lt;span class="nx"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="c1"&gt;// calling the function&lt;/span&gt;
&lt;span class="nx"&gt;hardToRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it looks good, but it has few downsides.  We have to read it from bottom to top which is a little counter intuitive and it is not very flexible form. What if we decide that we want to add something after the cleanup operation?  Are we going to rewrite it like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hardToRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;logIt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
  &lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@space&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
  &lt;span class="nx"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;))))&lt;/span&gt;

&lt;span class="c1"&gt;// calling the function&lt;/span&gt;
&lt;span class="nx"&gt;hardToRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is all doable, although we would need to be careful about number of brackets at the end.&lt;/p&gt;

&lt;p&gt;However we can do more, we can introduce a helper function to help us with the function composition. With that the above piece of code can be written this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hardToRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;logIt&lt;/span&gt; &lt;span class="c1"&gt;// now adding extra functionality does not require a lot of rewritting&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// calling the function&lt;/span&gt;
&lt;span class="nx"&gt;hardToRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The benefit of helper composition function is evident. The syntax is a lot cleaner. We can read the steps from top to bottom and we can add and remove any step without counting the closing brackets at the end.&lt;br&gt;
In addition function &lt;strong&gt;pipe&lt;/strong&gt; is what is called higher order function. It returns another function which can be named and passed along or executed on the spot.&lt;br&gt;
Under the hood the pipe function is actually very simple and it does basically the same thing as the calling functions in sequence. It could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice the function composition is already built in JavaScript and conceptually it can be seen as reducing a collection of functions and over an initial parameter into a new value.&lt;br&gt;
Basically, all we are doing is taking the output value from previous operation as an input value of the next operation just like in the schematic diagram in the beginning. At the end we have the final result.&lt;/p&gt;
&lt;h2&gt;
  
  
  Asynchronous code
&lt;/h2&gt;

&lt;p&gt;Composing only synchronous operation sometimes wouldn't get us too far. JavaScript is event driven programming language and asynchronous operation are at the heart of it.&lt;br&gt;
Composing asynchronous code is surprisingly straight forward as well.&lt;/p&gt;

&lt;p&gt;We can leverage already built in common constructs - &lt;strong&gt;Promises&lt;/strong&gt;.&lt;br&gt;
In the asynchronous world the already mention code could be written as follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is already pretty neat and personally I would use it as is as often as I can. So would we need another way to compose asynchronous functions?&lt;br&gt;
Let me explain. Sometimes we need to define the set of unique sequences of functions which might not even be known during the static evaluation. For example, in one path of the execution we would want to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getResult &amp;gt; eval_1 &amp;gt; eval_2 &amp;gt; calculate(param) &amp;gt; cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and in the other path we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getResult &amp;gt; eval_1&amp;gt; eval_2 &amp;gt; eval_3 &amp;gt; calculate(param) &amp;gt; cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or somewhere else we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getResult &amp;gt; eval_1&amp;gt; .... &amp;gt; eval_N &amp;gt; calculate(param) &amp;gt; cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover we could have another dynamic way of defining the number and order of the composed operations.&lt;br&gt;
It is easy to see that chaining promises could become cumbersome and we need some help to create the composition. We can take the &lt;code&gt;pipe&lt;/code&gt; function from sync section and tweak it a little. Or a little more since the current implementation does not support &lt;strong&gt;await&lt;/strong&gt; in &lt;code&gt;Array.reduce&lt;/code&gt;. However, it as long the &lt;strong&gt;await&lt;/strong&gt; keyword is called inside &lt;strong&gt;async&lt;/strong&gt; block any plain loop will wait for promise resolution. We can leverage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;asyncPipe&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pipe function in this implementation can accept both, synchronous and asynchronous function.&lt;br&gt;
To tackle the above challenge we could use it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="nx"&gt;methodN&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;cleanup&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myUniquePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can easily to chain the functions returning promises also in runtime when the set of required operations are not known at compile time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Exceptions?
&lt;/h2&gt;

&lt;p&gt;What about catch block? Did we forget something? What if something goes wrong and we have to provide failed path option?&lt;/p&gt;

&lt;p&gt;No news here. The asynchronous function is only a function returning promise so we have two main ways of handling this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;traditional catch block in promises&lt;/li&gt;
&lt;li&gt;inside asynchronous block of code we have the option using &lt;strong&gt;try - catch&lt;/strong&gt; construct.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;doPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;doSomethingWithResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;doSomethingWithError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;asyncBock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;doPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;doSomethingWithResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;doSomethingWithError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advantages using function composition
&lt;/h2&gt;

&lt;p&gt;In the ideal world of functional programming the function is completely decoupled from the environment where it runs.  This makes it very easy to test as there is virtually no difference how the function is executed in the mocked&lt;br&gt;
test environment, the development environment and in the production environment. The function behaves exactly the same. &lt;br&gt;
Dividing the logic into independent steps gives the opportunity to combine these steps into more a complex operation without increasing the complexity of building stones and without an extra strain to increase complexity of our test environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Function composition is one of the foundation stones of functional programming. In this article we explained the basic rules of function composition and has shown how to apply composition of synchronous and asynchronous functions.  It also outlined the basic implementation details leveraging the built in JavaScript language&lt;br&gt;
construct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;There is a lot of existing libraries offering the pipe or function composition is some shape. I've successfuly used &lt;a href="https://github.com/ramda/ramda"&gt;ramda&lt;/a&gt;.&lt;br&gt;
Others are happy with &lt;a href="https://github.com/lodash/lodash/tree/npm/fp"&gt;lodash/fp&lt;/a&gt;&lt;br&gt;
If somebody is interested in joining discussion there is a proposal for pipes as part of javascript syntax. &lt;a href="https://github.com/tc39/proposal-pipeline-operator"&gt;hackpipes&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Function_composition#In_programming_languages"&gt;function composition&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/ramda/ramda"&gt;ramda&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/tc39/proposal-pipeline-operator"&gt;hackpipes&lt;/a&gt;&lt;br&gt;
image sourced from &lt;a href="https://pixabay.com/"&gt;pixabay&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>functional</category>
    </item>
  </channel>
</rss>
