<?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>DEV Community: Shabd Saran</title>
    <description>The latest articles on DEV Community by Shabd Saran (@saranshabd).</description>
    <link>https://dev.to/saranshabd</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%2F500058%2F1bcf8270-3806-4a17-a180-2bc31fa07b81.jpg</url>
      <title>DEV Community: Shabd Saran</title>
      <link>https://dev.to/saranshabd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saranshabd"/>
    <language>en</language>
    <item>
      <title>Contextualising identifiers in a system</title>
      <dc:creator>Shabd Saran</dc:creator>
      <pubDate>Wed, 02 Aug 2023 06:42:06 +0000</pubDate>
      <link>https://dev.to/saranshabd/contextualising-identifiers-in-a-system-4mm6</link>
      <guid>https://dev.to/saranshabd/contextualising-identifiers-in-a-system-4mm6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;At least two unique identifiers exist even in the most rudimentary authentication systems: user ID and session ID. It is hard to keep track of different identifiers in a system. These identifiers are logged to files, reported to Sentry, sent to the frontend, passed around to developers in Slack in bug reports, and, most importantly, shared with non-programmers in the team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JRfUpNTE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1mip0f441ghgme8c98b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JRfUpNTE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1mip0f441ghgme8c98b.png" alt="first" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In no time, the &lt;code&gt;user.Id&lt;/code&gt; is propagated as just 507f1f77bcf86cd799439011, which is then, for example, shared on Slack by customer support to report a bug. The developers then have to make sense out of this random ID and try to map it to an actual database record. The backtracking becomes a nuisance when the context is unclear.&lt;/p&gt;

&lt;h2&gt;
  
  
  The missing jigsaw piece
&lt;/h2&gt;

&lt;p&gt;The identifier may propagate to a log file, Slack message, Sentry report, CMS dashboard or Google Analytics. The root cause of the problem is the loss of context from the identifier. The problem seems trivial if the system is not large enough. In systems with myriad unique identifiers, each representing an essential entity, issues related to backtracking or context retention can escalate rapidly.&lt;/p&gt;

&lt;p&gt;But what if the context is attached to the identifier itself? That will solve the problem. The identifier may reach the end of the universe, but the relevant context will travel with it.&lt;/p&gt;

&lt;p&gt;That is where identifier prefixing comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expounding the argument
&lt;/h2&gt;

&lt;p&gt;Most modern systems have identifiers like TXN_507f1f77bcf86cd799439011. Here, the prefix “TX_” contextualises the identifier. For example, the given identifier can be guessed as a transaction ID without additional information.&lt;/p&gt;

&lt;p&gt;The idea is to attach meaningful prefixes to critical identifiers. That will ensure these identifiers easily differentiate from the noise outside the system. The prefix is carrying relevant information about the identifier itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting down to business
&lt;/h2&gt;

&lt;p&gt;Here is an example to demonstrate the implementation.&lt;/p&gt;

&lt;p&gt;A program uses UUID strings to assign unique IDs to its database records. The program MUST respect the UUID formatting during retrieval and modification of the database documents. But it may ignore the formatting elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_nzwUAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g73r5lsavzbpafm2fw64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_nzwUAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g73r5lsavzbpafm2fw64.png" alt="second" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In such a system, all the entity modules can implement &lt;code&gt;toUUID&lt;/code&gt; and &lt;code&gt;fromUUID&lt;/code&gt; functions. Role of these functions, implemented internally, will be to convert a &lt;em&gt;(prefix)_ID&lt;/em&gt; to ID and vice-versa, respectively. These functions can translate prefixed identifiers to UUID formatted strings before the database query construction. Attachment of prefix to the returning value of identifiers from the entity modules can also be guaranteed.&lt;/p&gt;

&lt;p&gt;The type of the IDs returned from the modules may only be asserted as a string (as opposed to a valid UUID). It is one of the caveats of the implementation: only the entity module can assert the UUID formatting. Everyone else may treat the ID as any other string.&lt;/p&gt;

&lt;p&gt;The prefixed identifier may now be sent to Sentry or logged to AWS S3, but it will always carry the context of the identifier with it. Even the non-programmers will recognise a transaction ID from the CMS dashboard. What a relief!&lt;/p&gt;

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

&lt;p&gt;The idea is simple enough to explain without code. It just need two functions to convert an ID to a prefixed ID and vice-versa. But the value addition is massive.&lt;/p&gt;

&lt;p&gt;Identifier contextualising is not a new concept. People have been doing it for years now.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Python w/ strict typechecker</title>
      <dc:creator>Shabd Saran</dc:creator>
      <pubDate>Fri, 23 Dec 2022 23:26:22 +0000</pubDate>
      <link>https://dev.to/saranshabd/python-w-strict-typechecker-3l7g</link>
      <guid>https://dev.to/saranshabd/python-w-strict-typechecker-3l7g</guid>
      <description>&lt;p&gt;I’m embarrassed that I didn’t know Python has support for strict type-checking. It was tricky to embed type checking with Python2.x but that was changed with the introduction of Python3.x.&lt;/p&gt;

&lt;p&gt;If you didn’t know about this either then it's going to blow your mind!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fl3umllza1vx3zt7u9bcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fl3umllza1vx3zt7u9bcc.png" alt="mind-blown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up pretext
&lt;/h2&gt;

&lt;p&gt;I will assume that you are already familiar with the concept of “typing” in Python3.x. I’d highly recommend you do some research on the topic before moving forward.&lt;/p&gt;

&lt;p&gt;Here is a good starting point: &lt;a href="https://docs.python.org/3/library/typing.html" rel="noopener noreferrer"&gt;https://docs.python.org/3/library/typing.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Typing isn’t helpful… on it’s own
&lt;/h2&gt;

&lt;p&gt;“typing” in Python3.x is a suggester rather than a strict type checker. For example, you will not run into any problems before * actually * executing the following piece of code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# file: example.py
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n2&lt;/span&gt;

&lt;span class="nf"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;something&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;somethingElse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This is enough to make a grown man cry 🥲&lt;/p&gt;

&lt;p&gt;You ideally want these types of errors to be raised * while * you are writing code instead of finding them in production logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static type checkers
&lt;/h2&gt;

&lt;p&gt;Google, Facebook and Microsoft have published their static type checkers for Python. The one I will cover here is &lt;a href="http://mypy-lang.org/" rel="noopener noreferrer"&gt;mypy&lt;/a&gt;; it’s one of the most famous ones out there.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun fact: &lt;code&gt;mypy&lt;/code&gt; has been around even before Python3.x. Programmers would add special comments to annotate types to their functions in Python2.x; similar to how types can be defined in JavaScript using JSDocs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;mypy&lt;/code&gt; will go through all the files (that you specify) and check the type definitions of all the functions, methods and variables. For example, you will get the following output when running the above &lt;code&gt;example.py&lt;/code&gt; file through &lt;code&gt;mypy&lt;/code&gt;:&lt;/p&gt;

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

mypy example.py

&lt;span class="c"&gt;# --- Output ---&lt;/span&gt;
example.py:2: error: Unsupported operand types &lt;span class="k"&gt;for&lt;/span&gt; + &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"int"&lt;/span&gt; and &lt;span class="s2"&gt;"str"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;operator]
example.py:5: error: Argument 2 to &lt;span class="s2"&gt;"add_numbers"&lt;/span&gt; has incompatible &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="s2"&gt;"Dict[str, str]"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; expected &lt;span class="s2"&gt;"str"&lt;/span&gt;  &lt;span class="o"&gt;[&lt;/span&gt;arg-type]
Found 2 errors &lt;span class="k"&gt;in &lt;/span&gt;1 file &lt;span class="o"&gt;(&lt;/span&gt;checked 1 &lt;span class="nb"&gt;source &lt;/span&gt;file&lt;span class="o"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That’s what we’re talking about! 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Type checking during development
&lt;/h2&gt;

&lt;p&gt;This is great but what if one of my teammates forgot to use &lt;code&gt;mypy&lt;/code&gt; before committing the code to production? That's a solvable problem.&lt;/p&gt;

&lt;p&gt;Firstly, we need strict type-checking during the development process.; running a command after writing each function is inconvenient. You can create a &lt;code&gt;mypy.ini&lt;/code&gt; file at the root directory of your project with the following content:&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;mypy]
strict &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="c"&gt;# run type checker through all the included files&lt;/span&gt;
exclude &lt;span class="o"&gt;=&lt;/span&gt; .venv/


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

&lt;/div&gt;

&lt;p&gt;This will set global strict type-checking configurations for your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  VSCode setup
&lt;/h3&gt;

&lt;p&gt;Open the command palette using Command + P (or, Control + P for Windows/Linux users). Search for “Python: Select linter” and choose “mypy”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fsdu9a6wdjz0xdajlkud4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fsdu9a6wdjz0xdajlkud4.png" alt="select-mypy-linter-in-vscode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, your VSCode will inform you of the errors while you are writing code. Here’s an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjrhtiofzh73v1dzq7izz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjrhtiofzh73v1dzq7izz.png" alt="vscode-inline-linting-error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enforcing type checking
&lt;/h2&gt;

&lt;p&gt;A programmer will still be able to push type-unsafe code to production, even after all these configurations. Because remember, these restrictions are only set at mypy-level; Python3.x interpreter itself allows type unsafe code to be executed.&lt;/p&gt;

&lt;p&gt;Our job as a code-maintainer is to ensure that all of our code is type-safe before committing a change, and ensure the type-safety at the remote repository-level as well i.e. GitHub/GitLab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-commit scripts
&lt;/h3&gt;

&lt;p&gt;We want to run &lt;code&gt;mypy&lt;/code&gt; before the code is committed to Git. This can easily be configured using &lt;a href="https://pre-commit.com/" rel="noopener noreferrer"&gt;pre-commit&lt;/a&gt;. It’s a Python package that can be used with any language to run Git-specific scripts.&lt;/p&gt;

&lt;p&gt;We can use the following command to install &lt;code&gt;pre-commit&lt;/code&gt; to our project:&lt;/p&gt;

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

pip &lt;span class="nb"&gt;install &lt;/span&gt;pre-commit &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt


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

&lt;/div&gt;

&lt;p&gt;Create a &lt;code&gt;.pre-commit-config.yaml&lt;/code&gt; file at the root directory to run scripts &lt;strong&gt;before&lt;/strong&gt; committing the code:&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;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;typechecker&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;typechecker&lt;/span&gt; &lt;span class="c1"&gt;# description to be displayed in STDOUT&lt;/span&gt;
        &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mypy . --strict&lt;/span&gt;
        &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;system&lt;/span&gt;
        &lt;span class="na"&gt;always_run&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;pass_filenames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This file is pretty self-explanatory so I don’t think there’s anything to add here.&lt;/p&gt;

&lt;p&gt;Run the following command to install &lt;code&gt;pre-commit&lt;/code&gt; to the project Git setup:&lt;/p&gt;

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

pre-commit &lt;span class="nb"&gt;install&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can now edit the &lt;code&gt;.pre-commit-config.yaml&lt;/code&gt; file without having to run any more commands. I know that’s a relief 🤌&lt;/p&gt;

&lt;p&gt;Here’s what you will see when you try to commit the &lt;code&gt;example.py&lt;/code&gt; file we defined earlier:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0scappb3uvzsw4m5ebzr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0scappb3uvzsw4m5ebzr.png" alt="pre-commit-error-message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The changes were not committed to Git. Pretty sweet, huh?&lt;/p&gt;

&lt;h3&gt;
  
  
  Quality control at remote-repository level
&lt;/h3&gt;

&lt;p&gt;You still want all of these changes at the remote-repository level i.e. GitHub/GitLab. I will demonstrate the setup on GitHub; setup on GitLab wouldn’t be much different.&lt;/p&gt;

&lt;p&gt;The aim is to run &lt;code&gt;mypy&lt;/code&gt; when a commit is pushed to one of the “important” branches or when a pull request is created to be merged in one of these “important” branches. We can easily configure this using GitHub actions.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# file: .github/workflows/code-quality-checks.yaml&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Code quality checks&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.10.6"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python ${{ matrix.python-version }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.python-version }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Type checker&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mypy . --strict&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You will be able to view the results of these actions on GitHub itself:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fki8k9mvdi8n8gubg1hjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fki8k9mvdi8n8gubg1hjc.png" alt="github-action"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We made sure that our code is type-safe when we are committing it to VCS (Version Control System) i.e. Git, and we made sure that all the code is correctly merged at the remote-repository level i.e. GitHub.&lt;/p&gt;

&lt;p&gt;That’s all to take care of. You can take it from here to build a Docker image or push it directly to a deployment service. You can be ABSOLUTELY SURE that you will not be surprised by any of the bugs on production unless something is wrong with the business logic itself.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.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%2Fv4wwkpe66ekb6q83y8eu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fv4wwkpe66ekb6q83y8eu.png" alt="it-is-done"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go on now, comrades! Write quality and type-safe code with Python3.x.&lt;/p&gt;




&lt;p&gt;Drop a comment if you think I left something or if you have any suggestions for future posts.&lt;/p&gt;

</description>
      <category>python</category>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Go migrate from-express</title>
      <dc:creator>Shabd Saran</dc:creator>
      <pubDate>Sun, 30 Oct 2022 17:31:05 +0000</pubDate>
      <link>https://dev.to/saranshabd/go-migrate-from-express-2amm</link>
      <guid>https://dev.to/saranshabd/go-migrate-from-express-2amm</guid>
      <description>&lt;h2&gt;
  
  
  Background: why the switch?
&lt;/h2&gt;

&lt;p&gt;NodeJS made backend programming simpler for programmers as it enables you to write services in JavaScript. While NodeJS is still relevant today, JavaScript as a programming language isn’t ideal to write. Microsoft helped the JavaScript community with the introduction of TypeScript but that didn’t solve the underlying problem: the code is still transpiled to JavaScript.&lt;/p&gt;

&lt;p&gt;I can write an entire article on JavaScript and TypeScript. Drop a comment if you’d like me to do that. Moving on…&lt;/p&gt;

&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;You can find all the code from this article here: &lt;a href="https://github.com/saranshabd/migrate-from-express"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I highly suggest that you go through the code to better understand things. Use this article just for understanding the reasoning behind the decisions made in the repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking the right framework
&lt;/h2&gt;

&lt;p&gt;The focus will be to write an HTTP server. &lt;a href="https://expressjs.com/"&gt;ExpressJS&lt;/a&gt; is the most popular framework to build HTTP servers using JavaScript. The base assumption from here will be that you are already familiar with it, and are now trying to switch to Go. I am not going to focus on Go itself. The focus will be how to replicate the same ExpressJS structure in Go. Some familiarity with Go will be helpful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gin-gonic.com/"&gt;Gin&lt;/a&gt; is one of the most popular frameworks in Golang to build HTTP servers. My general advice would be to go for the most popular framework and libraries when picking a language you’re not comfortable with yet. Once you have mastered the default configurations and setup then you can focus on optimization and picking the right framework for your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic project setup and directory structure
&lt;/h2&gt;

&lt;p&gt;A good project structure is always going to help you down the road as the project scales. Code management is dependent on the programming language itself. Here are a few must-read articles on Golang project structure standard conventions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Standard Package Layout: &lt;a href="https://www.gobeyond.dev/standard-package-layout/"&gt;https://www.gobeyond.dev/standard-package-layout&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Golang standards - project layout: &lt;a href="https://github.com/golang-standards/project-layout"&gt;https://github.com/golang-standards/project-layout&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Standard practices to structure Go code
&lt;/h3&gt;

&lt;p&gt;Note that it is not a standard practice to put all the code inside the &lt;code&gt;src&lt;/code&gt; directory in Go. The following directories are a must in almost all the projects:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;cmd&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is the application's entrypoint. It’s the Go equivalent of &lt;code&gt;index.js&lt;/code&gt; in JavaScript projects. You don’t want to put a lot of code here; just project-level structs/interfaces and basic initialization setup.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cmd&lt;/code&gt; directory must not include any implementation logic. Note that the root directory is not allowed to have any external dependencies. It must only call/initiate the respective application packages.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;pkg&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is where you define the public packages in your application. This is where you write the actual implementation logic. &lt;strong&gt;Packages inside the &lt;code&gt;pkg&lt;/code&gt; directory are meant to be shared outside of your application&lt;/strong&gt;; keep that in mind.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;internal&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This directory is similar to the &lt;code&gt;pkg&lt;/code&gt; directory except it is only meant to be used by your application. This layout pattern is enforced by the Go compiler itself.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;internal&lt;/code&gt; directory may also have a &lt;code&gt;pkg&lt;/code&gt; sub-directory to better segregate the code. The &lt;code&gt;pkg&lt;/code&gt; sub-directory will contain packages that are shared amongst the &lt;code&gt;internal&lt;/code&gt; packages.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;vendor&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This directory contains your application dependencies. It is an automatically managed directory so you don’t have to manually change anything here. All you need to do is execute &lt;code&gt;go mod vendor&lt;/code&gt; to create and maintain this directory. The base assumption here is that you are using Go modules for managing dependencies.&lt;/p&gt;

&lt;p&gt;Note that you will need to add &lt;code&gt;-mod=vendor&lt;/code&gt; to the &lt;code&gt;go build&lt;/code&gt; command for building the project.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;configs&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Your application configurations will go here. You are probably going to read most of the configurations from the environment variables. You may use this directory to extract configurations from the environment variables and store them in a struct.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project structure example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd/
    __app_name__/
        init.go &lt;span class="c"&gt;# entrypoint&lt;/span&gt;
pkg/
    __app_name__/
        &lt;span class="nb"&gt;users&lt;/span&gt;/
        auth/
internal/
    __app_name__/
        razorpay/
vendor/
    github.com/
    golang.org/
    google.golang.org/
configs/
    configs.go
build/
    deploy/
        Dockerfile
go.mod
go.sum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Route structure and middleware
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;main.go&lt;/code&gt; file inside the &lt;code&gt;cmd/__app_name__&lt;/code&gt; directory will be simple. Its sole purpose will be to initiate the project and setup things in order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/saranshabd/migrate-from-express/cmd/mfe/http"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/saranshabd/migrate-from-express/cmd/mfe/logger"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/saranshabd/migrate-from-express/configs"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c"&gt;// Create a Gin server application with default configurations &amp;amp; middlewares&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Load all the application HTTP endpoints&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InitRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Start listening to HTTP requests from the client&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msgf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Firing it up on %d port number."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;configs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;configs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not fire up Gin :/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Kill the application&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;All the route handlers will go inside the &lt;code&gt;internal/__app_name__/&lt;/code&gt; directory, based on the directory structure discussed above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;internal/
    middlewares/
    __route_name__/
        routes.go
        handler1.go
        handler2.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Firstly, we must ensure that all the HTTP responses we send are by default JSON. We can create a simple middleware for this purpose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;middlewares&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;JSONResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&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;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&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;Secondly, we need a place to import all the HTTP route handlers and map them to specific endpoints. We can place this piece of code inside the &lt;code&gt;cmd&lt;/code&gt; directory since all we will do is important a bunch of handlers and map them to their respective endpoints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/saranshabd/migrate-from-express/internal/mfe/middlewares"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;InitRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Ensure that all the HTTP responses are by-default in the JSON format&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;middlewares&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONResponse&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c"&gt;// Load all the application HTTP routes&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! The router and middleware setup in Gin is similar to that in ExpressJS. We can call this &lt;code&gt;InitRoutes&lt;/code&gt; function from the &lt;code&gt;main.go&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract request parameters from different sources
&lt;/h2&gt;

&lt;p&gt;We can move on to creating a bunch of HTTP endpoints with the current project setup. The endpoints will primarily focus on extracting request parameters from different sources e.g. request body, query and URI. The request params will all be returned in the response object as is.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have created a bunch of simple HTTP utility functions for better code readability. These functions don’t have anything to do with the tutorial so I won’t go into the detail. You can find all the source code on GitHub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go treats functions as first-class citizens so your HTTP setup is going to be just a bunch of functions. An HTTP handler in Gin takes a single argument: Gin context. Context is one of the fundamentals of Go. If you’re not already familiar with it then I’d suggest you take some time in understanding them before you continue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extract from request body
&lt;/h3&gt;

&lt;p&gt;Go provides a beautiful “binding” package out of the box for basic validation. The binding module can be loosely compared with “Joi” package in NodeJS. The primary difference between the two is that binding is part of Go language itself so we don’t have to define our validation logic separately.&lt;/p&gt;

&lt;p&gt;This is how a typical Go HTTP handler looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;CreateExtractParamsArgs&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Arg1&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"arg1" binding:"required"`&lt;/span&gt;
    &lt;span class="n"&gt;Arg2&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;  &lt;span class="s"&gt;`json:"arg2" binding:"required"`&lt;/span&gt;
    &lt;span class="n"&gt;Arg3&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;   &lt;span class="s"&gt;`json:"arg3,omitempty"`&lt;/span&gt; &lt;span class="c"&gt;// optional&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;CreateExtractParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Extract the parameters from the request.body &amp;amp; validate the object received&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;CreateExtractParamsArgs&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BindJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Return HTTP 400 if invalid params are passed&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvalidRequestParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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="c"&gt;// Return the params object in response if everything is fine&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RespondOkay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Request parameters extracted successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&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;Note that I am using the custom &lt;code&gt;http&lt;/code&gt; package, which is just a utility package I created. You can refer to the &lt;code&gt;RespondOkay&lt;/code&gt; function below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;RespondOkay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Respond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Respond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"success"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;omitempty&lt;/code&gt; property will remove the field while deserialising, to let’s say JSON. The struct value of the field will be the default value of the type. E.g. if you access &lt;code&gt;args.Arg3&lt;/code&gt; then you will receive &lt;code&gt;false&lt;/code&gt; in the response. &lt;strong&gt;Beware of this behaviour. This is not JavaScript!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract from query parameters
&lt;/h2&gt;

&lt;p&gt;We can use the same pattern to validate query parameters using the binding package. We will use the &lt;code&gt;BindQuery&lt;/code&gt; function instead of &lt;code&gt;BindJSON&lt;/code&gt;. Everything else will look the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GetExtractParamsArgs&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Arg1&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`form:"arg1" json:"arg1" binding:"required"`&lt;/span&gt;
    &lt;span class="n"&gt;Arg2&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;  &lt;span class="s"&gt;`form:"arg2" json:"arg2" binding:"required"`&lt;/span&gt;
    &lt;span class="n"&gt;Arg3&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;   &lt;span class="s"&gt;`form:"arg3" json:"arg3,omitempty"`&lt;/span&gt; &lt;span class="c"&gt;// optional&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GetExtractParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Extract the parameters from the request.query &amp;amp; validate the object received&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;GetExtractParamsArgs&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BindQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Return HTTP 400 if invalid params are passed&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvalidRequestParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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="c"&gt;// Return the params object in response if everything if fine&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RespondOkay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Request parameres extracted successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&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;h3&gt;
  
  
  Extract from the URI
&lt;/h3&gt;

&lt;p&gt;Again, we can just extend the binding package to validate path parameters i.e. &lt;code&gt;/path/:arg/&lt;/code&gt;. You define the path parameters in Gin like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/:specificPath/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetSpecificExtractParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can swap the &lt;code&gt;BindQuery&lt;/code&gt; function with &lt;code&gt;BindUri&lt;/code&gt; and keep everything the same. By now, you must be getting the hang of Go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GetSpecificExtractParamsArgs&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SpecificPath&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`uri:"specificPath" json:"specificPath" binding:"required"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GetSpecificExtractParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Extract the parameters from the request.params &amp;amp; validate the object received&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;GetSpecificExtractParamsArgs&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BindUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Return HTTP 400 if invalid params are passed&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvalidRequestParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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="c"&gt;// Return the params object in response if everything is fine&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RespondOkay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Request parameters extracted successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&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;
  
  
  Header-based authorization
&lt;/h2&gt;

&lt;p&gt;Authentication and authorization are the base of almost all the REST APIs out there. Auth is usually built on top of HTTP headers. We can use the binding package to validate headers received in the request and write middlewares to add custom logic on top of that.&lt;/p&gt;

&lt;p&gt;Here’s a simple example of a auth header to check the source of the incoming request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;VerifiedSourcesArgs&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;VerifiedSource&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`header:"verified-source" binding:"required"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AcceptedSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"accepted-source"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;IsVerifiedSource&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&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;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Extract the header value from the HTTP request&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="n"&gt;VerifiedSourcesArgs&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShouldBindHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvalidHeaders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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="c"&gt;// Check if the source of the incoming request is accepted&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VerifiedSource&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;AcceptedSource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvalidHeaders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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="c"&gt;// Continue with the chain of middlewares/handlers&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&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;h3&gt;
  
  
  The &lt;code&gt;Next&lt;/code&gt; function in Gin middlewares
&lt;/h3&gt;

&lt;p&gt;Gin middlewares look awfully similar to ExpressJS middlewares. But, there is a nasty distinction between the two; the &lt;code&gt;Next&lt;/code&gt; function. &lt;strong&gt;You do not need to necessarily call the &lt;code&gt;Next&lt;/code&gt; function in a Gin middleware.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is an important distinction because you cannot expect a request to terminate just because you returned from the middleware without calling the &lt;code&gt;Next&lt;/code&gt; function. The next in-chain function will still be called when your middleware terminates… unless you abort the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;AbortAndRespond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;statusCode&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AbortWithStatusJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"success"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of calling &lt;code&gt;c.JSON&lt;/code&gt; we need to call &lt;code&gt;c.AbortWithStatusJSON&lt;/code&gt; function to set the status code and JSON response before aborting the request. This is a nasty distinction especially for programmers coming from the NodeJS background. Beware!&lt;/p&gt;




&lt;p&gt;That's it! We setup HTTP routes, validated incoming request data from different sources, and created auth middlewares for the application.&lt;/p&gt;

&lt;p&gt;This is just the beginning. The application didn't interact with a database or a third-party service; both are fundamentals to most of the services. That's for the next article in the series :)&lt;/p&gt;

&lt;p&gt;Drop a comment if there's anything I missed or could've explained better.&lt;/p&gt;

&lt;p&gt;Cheers! 👋&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>gin</category>
    </item>
    <item>
      <title>Simple Cookies with Node.js and any frontend JavaScript framework</title>
      <dc:creator>Shabd Saran</dc:creator>
      <pubDate>Sat, 26 Mar 2022 08:17:21 +0000</pubDate>
      <link>https://dev.to/saranshabd/simple-cookies-with-nodejs-and-any-frontend-javascript-framework-42ph</link>
      <guid>https://dev.to/saranshabd/simple-cookies-with-nodejs-and-any-frontend-javascript-framework-42ph</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Fact: Elite programmers do simple things. It's the idiots who complicate things just to look smart.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why another one?
&lt;/h2&gt;

&lt;p&gt;We all have come across blogs to set up HTTP cookies with Node.js and React.js (or any other frontend framework) and let’s be honest it’s hard to find an article with all the information we need to set up our project.&lt;/p&gt;

&lt;p&gt;Out there, you find a lot of ifs and buts in configurations so I’ll just tell you what you need to make it work - that’s it. I’ll keep this one short and to the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agenda
&lt;/h2&gt;

&lt;p&gt;Let’s start with what our setup will look like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Separate configurations for development and production environments; &lt;em&gt;that’s something missing from all the blogs out there.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure the frontend &lt;code&gt;axios&lt;/code&gt; library to allow the backend to set cookies on the browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure the backend API to set a cookie with the right configurations; &lt;em&gt;just the ones you need and care about.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Assumptions
&lt;/h3&gt;

&lt;p&gt;I am assuming you will be hosting the frontend and the backend API on separate domains. Just to clarify, &lt;code&gt;api.example.com&lt;/code&gt; and &lt;code&gt;example.com&lt;/code&gt; are also counted as two separate domains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend configurations
&lt;/h2&gt;

&lt;p&gt;On the frontend, I assume you will use a third-party library like &lt;a href="https://www.npmjs.com/package/axios"&gt;axios&lt;/a&gt; to make requests to your server. I will advise you to create a new instance of Axios, with all the customised default configurations, and use this instance everywhere else in your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Axios instance with custom default configurations
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;.create&lt;/code&gt; function allows you to set different configurations for different types of requests that you want to make to the backend. For example, you could have an Axios instance for making authenticated requests, and another one for making unauthenticated requests.&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;// utils/axios.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&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;axiosInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://api.example.com/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// optional but recommended&lt;/span&gt;
  &lt;span class="na"&gt;withCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// to allow your API to set cookies on the browser&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;axiosInstance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s just a better way of doing things 🤷&lt;/p&gt;

&lt;p&gt;You’re done with frontend configurations. You can now use this newly created Axios instance to make requests to the backend like you normally would.&lt;/p&gt;

&lt;p&gt;For 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;// utils/api.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utils/axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchProducts&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;axios&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products/all/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice, how you don’t have to set the base URL every single time now. You’re welcome :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend configurations
&lt;/h2&gt;

&lt;p&gt;You will just need to install a single library to your project - &lt;a href="https://www.npmjs.com/package/cors"&gt;CORS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment variables
&lt;/h3&gt;

&lt;p&gt;Create an environment variable to store the frontend URL. If you are running the project in the development environment then you might set it to &lt;code&gt;http://localhost:8000&lt;/code&gt;, or if you are running it in production then it might be &lt;code&gt;https://example.com&lt;/code&gt;.&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="c"&gt;# .env&lt;/span&gt;

&lt;span class="nv"&gt;FRONTEND_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use a third-party library like &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt; to load environment variables from the .env file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up Express app
&lt;/h3&gt;

&lt;p&gt;Configure CORS and default response headers to be able to set cookies on the frontend browser.&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;// index.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;main&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...your Express app configurations&lt;/span&gt;

  &lt;span class="c1"&gt;// allow the frontend to make requests to your API&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&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;FRONTEND_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="c1"&gt;// set headers for you to be able to set cookies on the browser&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&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;next&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&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;FRONTEND_URL&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;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Headers&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="s2"&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Credentials&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="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// ...your rest of the configurations&lt;/span&gt;

  &lt;span class="nx"&gt;app&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;process&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;PORT&lt;/span&gt;&lt;span class="p"&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="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;App is up and running&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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// again, just a better way of doing things&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, that’s all you need to set up cookies on your backend project. You can now start setting cookies in your endpoint responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set cookies with working configurations
&lt;/h3&gt;

&lt;p&gt;You can use the given format to set cookies in both development and production environments, using the automatically set environment variable &lt;code&gt;NODE_ENV&lt;/code&gt;.&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;// routes/auth.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isInDevelopment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&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;cookieConfigs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isInDevelopment&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isInDevelopment&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// one year&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signIn/&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...your own login&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;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cookie-name&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="s2"&gt;cookie-value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cookieConfigs&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;204&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// read about HTTP status 204&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;That’s it! No more wandering from one Stackoverflow answer to another in search of workable cookies configurations with Node.js.&lt;/p&gt;

&lt;p&gt;Do like the article if you found this helpful, and/or drop a comment if there’s anything I missed or anything you’d like me to cover in another article.&lt;/p&gt;

&lt;p&gt;Signing off! 👋&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>How and why to use Docker as a package manager?</title>
      <dc:creator>Shabd Saran</dc:creator>
      <pubDate>Mon, 09 Nov 2020 20:31:43 +0000</pubDate>
      <link>https://dev.to/saranshabd/how-and-why-to-use-docker-as-a-package-manager-2jha</link>
      <guid>https://dev.to/saranshabd/how-and-why-to-use-docker-as-a-package-manager-2jha</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hello everyone, hope you're coding well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/saranshabd/how-docker-can-help-you-sleep-well-at-night-3c80"&gt;last article&lt;/a&gt; of this &lt;a href="https://dev.to/saranshabd/series/9616"&gt;DevOps with Docker&lt;/a&gt; series, I explained how you can use Docker to make your life easy. I discussed how most of the developers are hesitant to try Docker and there are several reasons for that, so please check out that article if you've not read it already.&lt;/p&gt;

&lt;p&gt;In that article, I also mentioned a few use cases of Docker. Now, I'm going to write individual articles for each of the use cases I mentioned there, explaining in-depth and providing code snippets so that even amateurs can pick up and use Docker in their daily development life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Today's topic of discussion
&lt;/h2&gt;

&lt;p&gt;In this article, I am going to explain how one can use Docker as a package manager for their development machine. Most of the developers use &lt;code&gt;brew&lt;/code&gt; and &lt;code&gt;apt&lt;/code&gt; as their package managers in macOS and Ubuntu respectively. Although there's nothing wrong with both of them, there might be scenarios where these guys will fail you.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's wrong with &lt;code&gt;brew&lt;/code&gt; and &lt;code&gt;apt&lt;/code&gt;?
&lt;/h1&gt;

&lt;p&gt;Imagine you're a freelancer who's using MongoDB v3.6 for personal projects. You just signed a new client and the client asks you to use the latest version of MongoDB, which is v4.4. Now, how are you going to manage two different versions of MongoDB on your development machine? I'm not saying there's no way of doing this, I'm just saying that there's an easier way, which is to use Docker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker at your service!
&lt;/h2&gt;

&lt;p&gt;Docker is a container management service, and containers by definition provide an isolated environment to whatever is running inside. Isn't that exactly what we need? We need two MongoDB services to run independently, without affecting each other.&lt;/p&gt;

&lt;p&gt;You can simply create two Docker containers and run MongoDB v3.6 on one and MongoDB v4.4 on the other. Problem solved!&lt;/p&gt;

&lt;h1&gt;
  
  
  Solution Implementation
&lt;/h1&gt;

&lt;p&gt;Docker comes with an amazing CLI for developer's to take advantage of its services and features. Docker commands generally tends to be very long and scary, but if you understand the meaning of each and every command and sub-command then it becomes a piece of cake.&lt;/p&gt;

&lt;p&gt;Here's a command to run MongoDB v4.2.5 inside a Docker container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 27017:27017 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;MONGO_INITDB_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;test_api_v4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/volumes/mongo-4.2.5:/data/db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; test_mongodb &lt;span class="se"&gt;\&lt;/span&gt;
  mongo:4.2.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this command, you can create a Docker container running MongoDB v4.2.5 on port 27017. So, you can run multiple such instances on your development machine, with each of them hosted on a separate port number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Command breakdown
&lt;/h2&gt;

&lt;p&gt;As I said, once you fully understand Docker commands, it will take no time for you to write one on your own (maybe for a different use case). I've broken down the above Docker command into meaningful chunks so that it will be easier for anyone to understand what is happening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Docker container
&lt;/h3&gt;

&lt;p&gt;This part of the command is creating a new Docker container. The &lt;code&gt;--rm&lt;/code&gt; flag tells Docker to delete the container once we stop it, and the &lt;code&gt;-d&lt;/code&gt; flag tells Docker to run the container in detached mode (which means the container will not terminate once we close the terminal).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Map port numbers
&lt;/h3&gt;

&lt;p&gt;This part of the command maps host port number with container port number. The mapping format is &lt;code&gt;(host-port):(container-port)&lt;/code&gt;.&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="nt"&gt;-p&lt;/span&gt; 27017:27017
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provide environment variables
&lt;/h3&gt;

&lt;p&gt;This part of the command provides any environment variables (if needed) to the container. This is an ideal use case if you want to create a container to run database inside it because you would want to set user credentials and other required database properties at the time of its creation. Here, we are setting the name of the database MongoDB creates by default.&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="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;MONGO_INITDB_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;test_api_v4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create docker volume
&lt;/h3&gt;

&lt;p&gt;This part of the command creates Docker volume. Docker volume is nothing but a storage bridge between the host and the container. In this case, we would like to persist database files to our development machine (which is the host) so we create a Docker volume which maps our current directory to the directory in the container where MongoDB stores its database files.&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="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/volumes/mongo-4.2.5:/data/db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Name the container
&lt;/h3&gt;

&lt;p&gt;I think this is self-explanatory. By default, Docker assigns a random string to it, if you don't provide a name explicitly.&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="nt"&gt;--name&lt;/span&gt; test_mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define Docker image
&lt;/h3&gt;

&lt;p&gt;This part of the command defines what image you want to run inside the container. The string is of the format: &lt;code&gt;(image-name):(image-version)&lt;/code&gt;. By default, if you don't provide a version then Docker assumes it to be &lt;code&gt;latest&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mongo:4.2.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Support
&lt;/h1&gt;

&lt;p&gt;Please do leave a comment if you feel something could've been improved here. I can only continue writing such articles if I get support from you guys. Share it with your friends or colleagues if you feel like this could really help them.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>How Docker can help you sleep well at night?</title>
      <dc:creator>Shabd Saran</dc:creator>
      <pubDate>Tue, 27 Oct 2020 16:02:43 +0000</pubDate>
      <link>https://dev.to/saranshabd/how-docker-can-help-you-sleep-well-at-night-3c80</link>
      <guid>https://dev.to/saranshabd/how-docker-can-help-you-sleep-well-at-night-3c80</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hello everyone, hope you're coding well.&lt;/p&gt;

&lt;p&gt;I was very surprised to realize that a lot of junior developers, college students and freelancers were not using Docker and some of them were not even interested to learn it. Unbeknownst to them most of the senior developers, DevOps engineers, product managers and the whole software industry is functioning on this technology.&lt;/p&gt;

&lt;p&gt;This article is dedicated to these people, to enlighten them a whole new world of containerization. In this article, we will only focus on Docker and how we can use it to increase our productivity and save our resources.&lt;/p&gt;

&lt;h1&gt;
  
  
  Terminologies
&lt;/h1&gt;

&lt;p&gt;Before we dig deep into the use cases of Docker, let me brief you on a few terminologies:&lt;/p&gt;

&lt;h3&gt;
  
  
  Containerization
&lt;/h3&gt;

&lt;p&gt;It is a concept of running software inside containers. The benefit you get by doing so is that all of your applications will run in isolation and if (for some reason) one of the applications crashes then all the other will still keep on running.&lt;/p&gt;

&lt;h3&gt;
  
  
  Container
&lt;/h3&gt;

&lt;p&gt;A container basically provides an isolated environment to whatever is running inside it. As the name suggests, you can put whatever you want inside a container without worrying about the outer world.&lt;/p&gt;

&lt;h3&gt;
  
  
  Image
&lt;/h3&gt;

&lt;p&gt;This is the piece of software (along with all of its configurations) which runs inside a container. An image interacts with the container, which in turn interacts with the outer world. This gives developers a benefit to not to worry about the environment in which their code might run. They only have to build the software and configure it to run inside a container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;p&gt;At last, our beloved software. This is a container management service, which takes care of all the containers and their interactions with the outer world. For us, it is a magic box which we don't have to worry about.&lt;/p&gt;

&lt;h1&gt;
  
  
  What all can I do with Docker?
&lt;/h1&gt;

&lt;p&gt;There are a lot of things one can use Docker for, and the best part is that developers can use their creativity along with Docker to increase their productivity. At the end, its just a container management service and it is up to you to use those containers for your own benefit.&lt;/p&gt;

&lt;p&gt;People who are not familiar with Docker thinks that it has very specific use cases or that it's just too advanced for them to use. For them Docker is used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either, build software in an environment close to production&lt;/li&gt;
&lt;li&gt;Or, deploy code in an isolated environment using containers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although both of these uses cases are valid, that is not what all Docker can do. Here are a few uses cases that I personally came across with and would like to share with all of you:&lt;/p&gt;

&lt;h3&gt;
  
  
  Install and manage multiple versions of the same software
&lt;/h3&gt;

&lt;p&gt;You can use Docker to install software on your development machine, rather than using &lt;code&gt;apt&lt;/code&gt; or &lt;code&gt;brew&lt;/code&gt;. The main benefit you get here by using Docker is that you can easily manage this software and its configurations. For example, if you're installing MongoDB using Docker than you can run multiple MongoDB containers (one for each of your project) and that too on different ports (just in case one of them is already in use). You can install multiple versions of PostgreSQL on your development machine without those containers affecting each other. How cool is that?&lt;/p&gt;

&lt;h3&gt;
  
  
  Share development and staging infrastructure with the team
&lt;/h3&gt;

&lt;p&gt;Share development infrastructure with your team easily using Docker Compose and GitHub. Imagine a new software developer joined your team, then you will have to share your development infrastructure (test database files, how to run your application on stage, etc). You can do all of that using Docker Compose and push all the files to GitHub, then this new developer will only have to clone this repository and read the &lt;a href="http://readme.md"&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/a&gt; file to understand everything. Some of the startups use services on AWS to do the same task, but here you won't have to spend a dime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Linux shell on Mac or Windows
&lt;/h3&gt;

&lt;p&gt;Easily install and use Linux shell on your Mac or Windows machine. A lot of developers either dual boot their system or install some virtual machine software to use a Linux shell, whereas you can do the same thing using Docker as well. And since containers are lighter than virtual machines, you won't notice the difference between your system shell and the Linux shell running inside a container.&lt;/p&gt;

&lt;p&gt;One disclaimer I would like to add here is that you will have to create appropriate Docker volumes so that you are saving the work on your computer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy code to production with just a single command
&lt;/h3&gt;

&lt;p&gt;Pushing your Docker images to a container registry can be really beneficial because you will not have to move your code manually to the production instance (assuming you're working on a small project). With just a simple Docker command you can build and push your code to a container registry (as a Docker image) and then either create a pipeline to automatically deploy the pushed code or SSH into the production instance and simply pull the latest Docker images from the container registry.&lt;/p&gt;

&lt;p&gt;This is something which I think could be very useful to freelancers because I noticed that most of the time they're busy either completing the projects, finding new clients or attending meetings with their existing clients so they don't have a lot of time pushing code to production or solving minor production issues which could've easily been avoided using Docker.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Notice that I've not mentioned what all features does Docker provide, instead, I've just mentioned some of the use cases where Docker has proven to be very effective. That is how I use Docker and your use cases might be different from mine, but the tool will remain the same.&lt;/p&gt;

&lt;h1&gt;
  
  
  Support
&lt;/h1&gt;

&lt;p&gt;Please do leave a comment if you feel something could've been improved here. I can only continue writing such articles if I get support from you guys. Share it with your friends or colleagues if you feel like this could really help them, and do let me know if you want me to write an article explaining a particular topic or use-case from this one.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>devops</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
