<?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: Samuel Mugane</title>
    <description>The latest articles on DEV Community by Samuel Mugane (@roguecode25).</description>
    <link>https://dev.to/roguecode25</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%2F714211%2Fe71a86dc-9267-4ae5-892b-eebc427b4665.jpeg</url>
      <title>DEV Community: Samuel Mugane</title>
      <link>https://dev.to/roguecode25</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/roguecode25"/>
    <language>en</language>
    <item>
      <title>Syncing AWS S3 Storage Bucket Objects to LocalStack S3 Storage Bucket</title>
      <dc:creator>Samuel Mugane</dc:creator>
      <pubDate>Thu, 27 Mar 2025 12:06:46 +0000</pubDate>
      <link>https://dev.to/roguecode25/syncing-aws-s3-storage-bucket-objects-to-localstack-s3-storage-bucket-46c9</link>
      <guid>https://dev.to/roguecode25/syncing-aws-s3-storage-bucket-objects-to-localstack-s3-storage-bucket-46c9</guid>
      <description>&lt;p&gt;Banner image courtesy: &lt;a href="https://tudip.com/blog-post/what-is-aws-s3-and-storage-classes-in-aws-s3/" rel="noopener noreferrer"&gt;Tudip Digital&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.localstack.cloud/" rel="noopener noreferrer"&gt;LocalStack&lt;/a&gt; is a cloud service emulator that runs in a single container on your laptop or in your CI environment. With LocalStack, you can run your AWS applications or Lambdas entirely on your local machine without connecting to a remote cloud provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;In this tutorial, we will install LocalStack CLI on our x86-64 Linux machine, for ARM64 kindly check the &lt;a href="https://docs.localstack.cloud/getting-started/installation/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. The CLI starts and manages the LocalStack 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;&lt;span class="c"&gt;# Download the pre-built binary&lt;/span&gt;
curl &lt;span class="nt"&gt;--output&lt;/span&gt; localstack-cli-4.2.0-linux-amd64-onefile.tar.gz &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt; https://github.com/localstack/localstack-cli/releases/download/v4.2.0/localstack-cli-4.2.0-linux-amd64-onefile.tar.gz

&lt;span class="c"&gt;# Extract the LocalStack CLI from the terminal&lt;/span&gt;
&lt;span class="nb"&gt;sudo tar &lt;/span&gt;xvzf localstack-cli-4.2.0-linux-&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-onefile&lt;/span&gt;.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /usr/local/bin

&lt;span class="c"&gt;# Verify installed version&lt;/span&gt;
localstack &lt;span class="nt"&gt;--version&lt;/span&gt;
4.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring and Starting LocalStack
&lt;/h3&gt;

&lt;p&gt;We need an API key from LocalStack to configure LocalStack on our local machine. Head over to &lt;a href="https://app.localstack.cloud/sign-up" rel="noopener noreferrer"&gt;LocalStack&lt;/a&gt; and signup. Within your LocalStack dashboard, go to &lt;code&gt;WorkSpace&lt;/code&gt; → &lt;code&gt;Auth Tokens&lt;/code&gt; and copy the personal auth token provided. This personal auth token will be used to activate the LocalStack pro hobby subscription which grants use access to all of LocalStack’s features such as the Resource Browser which will use in this tutorial. Now add the auth token to your local stack CLI and start LocalStack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;localstack auth set-token &amp;lt;YOUR_AUTH_TOKEN&amp;gt;
&lt;span class="c"&gt;# By default, LocalStack runs on port 4566. Make sure no service is running on this port otherwise LocalStack won't start&lt;/span&gt;
localstack start

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ &lt;span class="se"&gt;\/&lt;/span&gt; ___/ __ &lt;span class="sb"&gt;`&lt;/span&gt;/ /&lt;span class="se"&gt;\_&lt;/span&gt;_ &lt;span class="se"&gt;\/&lt;/span&gt; __/ __ &lt;span class="sb"&gt;`&lt;/span&gt;/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,&amp;lt;
 /_____/&lt;span class="se"&gt;\_&lt;/span&gt;___/&lt;span class="se"&gt;\_&lt;/span&gt;__/&lt;span class="se"&gt;\_&lt;/span&gt;_,_/_//____/&lt;span class="se"&gt;\_&lt;/span&gt;_/&lt;span class="se"&gt;\_&lt;/span&gt;_,_/&lt;span class="se"&gt;\_&lt;/span&gt;__/_/|_|

- LocalStack CLI: 4.2.0
- Profile: default
- App: https://app.localstack.cloud

&lt;span class="o"&gt;[&lt;/span&gt;12:31:41] starting LocalStack &lt;span class="k"&gt;in &lt;/span&gt;Docker mode 🐳                                                       localstack.py:512
2025-03-27T12:31:41.282  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;  MainThread] l.p.c.b.licensingv2        : Successfully activated cached license &amp;lt;license-id&amp;gt;:hobby from /home/user/.cache/localstack-cli/license.json 🔑✅
──────────────────────────────────── LocalStack Runtime Log &lt;span class="o"&gt;(&lt;/span&gt;press CTRL-C to quit&lt;span class="o"&gt;)&lt;/span&gt; ─────────────────────────────────────

LocalStack version: 4.2.1.dev87
LocalStack build &lt;span class="nb"&gt;date&lt;/span&gt;: 2025-03-26
LocalStack build git &lt;span class="nb"&gt;hash&lt;/span&gt;: c6fc9b010

2025-03-27T09:31:48.092  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;  MainThread] l.p.c.b.licensingv2        : Successfully activated cached license &amp;lt;license-id&amp;gt;:hobby from /etc/localstack/conf.d/license.json 🔑✅
2025-03-27T09:31:52.329  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;  MainThread] l.p.c.extensions.platform  : loaded 0 extensions
Ready.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing AWS CLI and LocalStack’s AWS CLI
&lt;/h3&gt;

&lt;p&gt;We now need to have both the AWS official CLI and LocalStack’s AWS CLI which is a thin wrapper of the AWS official CLI for LocalStack. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;AWS CLI installation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify installation of the official AWS CLI&lt;/span&gt;
aws &lt;span class="nt"&gt;--version&lt;/span&gt;
aws-cli/2.25.4 Python/3.12.9 Linux/5.15.167.4-microsoft-standard-WSL2 exe/x86_64.ubuntu.24

&lt;span class="c"&gt;# Install LocalStack's AWS CLI&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;awscli-local
awslocal &lt;span class="nt"&gt;--version&lt;/span&gt;
aws-cli/2.25.4 Python/3.12.9 Linux/5.15.167.4-microsoft-standard-WSL2 exe/x86_64.ubuntu.24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating S3 Storage Bucket in LocalStack
&lt;/h3&gt;

&lt;p&gt;Before syncing the buckets, we need to create an S3 storage bucket within LocalStack in our local machine:&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;# Create bucket&lt;/span&gt;
awslocal s3api create-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--acl&lt;/span&gt; public-read &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bucket&lt;/span&gt; test-s3-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--object-ownership&lt;/span&gt; BucketOwnerPreferred &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--create-bucket-configuration&lt;/span&gt; &lt;span class="s1"&gt;'{"LocationConstraint": "us-east-2"}'&lt;/span&gt; 

&lt;span class="c"&gt;# Sample output with bucket name set to test-s3-bucket&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"Location"&lt;/span&gt;: &lt;span class="s2"&gt;"http://test-s3-bucket.s3.localhost.localstack.cloud:4566/"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Syncing S3 Storage Buckets
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will focus on two keys methods for syncing our AWS S3 storage bucket with our LocalStack S3 storage bucket within our local machine. &lt;/p&gt;

&lt;h3&gt;
  
  
  Method 1: Sequential sync
&lt;/h3&gt;

&lt;p&gt;The sequential sync approach is whereby we sync the bucket to a local temp folder in our local machine then sync our LocalStack S3 storage bucket with data in the local temp folder.&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;# Syncing bucket data to local temp folder&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;sync &lt;/span&gt;s3://&amp;lt;source-bucket i.e test-s3-bucket&amp;gt; ./local-folder &lt;span class="nt"&gt;--region&lt;/span&gt; &amp;lt;region i.e us-east-2&amp;gt;

&lt;span class="c"&gt;# Syncing local folder to LocalStack S3 bucket&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;sync&lt;/span&gt; ./local-folder s3://&amp;lt;destination-bucket i.e test-s3-bucket&amp;gt; &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt; http://localhost:4566 

&lt;span class="c"&gt;# Verify upload&lt;/span&gt;
awslocal s3 &lt;span class="nb"&gt;ls &lt;/span&gt;s3://test-s3-bucket
2025-03-27 13:04:21     165892 test-s3-file.jpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Method 2: Direct Sync (Without Local Storage)
&lt;/h3&gt;

&lt;p&gt;The direct sync approach avoids syncing the bucket data to local storage first but rather syncs the bucket data directly to the LocalStack S3 storage bucket. In this tutorial, we will use a bash script to sync the buckets. You can create a python script and use boto3 and LocalStack’s &lt;a href="https://docs.localstack.cloud/user-guide/integrations/sdks/python/" rel="noopener noreferrer"&gt;python client&lt;/a&gt; to sync the buckets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;ls &lt;/span&gt;s3://&amp;lt;aws-s3-bucket&amp;gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $4}'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
xargs &lt;span class="nt"&gt;-P&lt;/span&gt; 10 &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'aws s3 cp --debug "s3://&amp;lt;aws-test-s3-bucket&amp;gt;/{}" - | awslocal s3 cp - "s3://&amp;lt;localstack-test-s3-bucket&amp;gt;/{}" --debug'&lt;/span&gt;

&lt;span class="c"&gt;# Sample output in terminal running localstack&lt;/span&gt;
2025-03-27T10:12:24.654  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;et.reactor-0] localstack.request.aws     : AWS s3.PutObject &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 200
2025-03-27T10:12:27.443  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;et.reactor-0] localstack.request.aws     : AWS s3.PutObject &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 200
2025-03-27T10:12:37.219  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;et.reactor-0] localstack.request.aws     : AWS s3.PutObject &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 200
2025-03-27T10:12:41.503  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;et.reactor-0] localstack.request.aws     : AWS s3.PutObject &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 200
2025-03-27T10:12:45.346  INFO &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;et.reactor-0] localstack.request.aws     : AWS s3.PutObject &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the upload is complete, you can head to your LocalStack dashboard navigate to local instances, go to resource browser, search for S3, choose bucket and browse your files or folders in your bucket.&lt;/p&gt;

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

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

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

&lt;p&gt;The local storage first approach is more performant as compared to the direct approach since the direct approach relies on &lt;code&gt;xargs&lt;/code&gt; to achieve parallel transfers using sub-processes. One can spawn multiple separate sub processes using &lt;code&gt;xargs -P N&lt;/code&gt; when &lt;code&gt;N&lt;/code&gt; is the number of sub processes required. The sub process parallelism is great for S3 sync as this is an I/O bound task. In terms of speed, using &lt;code&gt;xargs&lt;/code&gt; even with tuned parallelism can be slow. If you are looking to speed up syncs, you can use tools such as &lt;a href="https://github.com/peak/s5cmd" rel="noopener noreferrer"&gt;&lt;code&gt;s5cmd&lt;/code&gt;&lt;/a&gt; which supports true multithreading. I will sure do a tutorial on &lt;code&gt;s5cmd&lt;/code&gt; and do a benchmark to check how it compares to using &lt;code&gt;xargs&lt;/code&gt; in parallel mode. The approach in this tutorial was not created with the context of large S3 storage buckets. If you have a tutorial on this please share. Thanks again for reaching to the end of this tutorial. Cheers!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>aws</category>
      <category>bash</category>
      <category>devops</category>
    </item>
    <item>
      <title>Web Authentication on Stellar: A Deep Dive</title>
      <dc:creator>Samuel Mugane</dc:creator>
      <pubDate>Fri, 25 Aug 2023 03:04:37 +0000</pubDate>
      <link>https://dev.to/roguecode25/web-authentication-on-stellar-a-deep-dive-1bim</link>
      <guid>https://dev.to/roguecode25/web-authentication-on-stellar-a-deep-dive-1bim</guid>
      <description>&lt;p&gt;Banner copyright: &lt;a href="https://www.gemini.com/cryptopedia/stellar-blockchain-payments-xlm-coin" rel="noopener noreferrer"&gt;Gemini&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The Stellar Web Authentication also referred to as &lt;a href="https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md" rel="noopener noreferrer"&gt;SEP-0010&lt;/a&gt; is based on JSON Web Token (JWT) &lt;a href="https://datatracker.ietf.org/doc/html/rfc7519" rel="noopener noreferrer"&gt;RFC7519&lt;/a&gt; which is the most used self-contained way for securely transmitting information between parties as a JSON object. One of the use cases for JWT is authentication which is the focus of this article. Stellar Web Authentication uses a wallet's keypair which comprises the public key: &lt;code&gt;G...&lt;/code&gt; and the secret key: &lt;code&gt;S...&lt;/code&gt; as base credentials for authentication. &lt;/p&gt;

&lt;h2&gt;
  
  
  Stellar Web Authentication
&lt;/h2&gt;

&lt;p&gt;This walk-through comprises different components and keywords that will be highlighted earlier for ease of understanding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note: This implementation of SEP-0010 does not feature client attribution which entails the verification of the &lt;code&gt;client_domain&lt;/code&gt; and &lt;code&gt;verify_challenge_transaction_signed_by_client_master_key&lt;/code&gt; operation.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Assuming you have already set up your Django project, let's go ahead and define an app that will handle our auth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py startapp sep10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the created app to the installed apps list in the &lt;code&gt;settings.py&lt;/code&gt; file in the root folder of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSTALLED_APPS = [
    "sep10",
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define the variables below in the &lt;code&gt;settings.py&lt;/code&gt; file in the root folder of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from stellar_sdk import Server

STELLAR_NETWORK = "Test SDF Network ; September 2015"
HORIZON_URI = "https://horizon-testnet.stellar.org"
SERVER_JWT_KEY = "key_used_to_hash_the_jwt_str"
HORIZON_SERVER = Server(horizon_url=HORIZON_URI)
SIGNING_KEY = "server_account_public_key"
SIGNING_SEED = "server_account_secret_seed"
HOST_URL = "http://localhost:8000"
SEP10_HOME_DOMAINS="foo.com, bar.io"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define a custom JWT token class
&lt;/h3&gt;

&lt;p&gt;In the &lt;code&gt;sep10&lt;/code&gt; app folder add the JWT token class below in the &lt;code&gt;token.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from jwt import decode
from datetime import datetime, timezone
from jwt.exceptions import InvalidTokenError
from typing import Optional, Union, Dict

from stellar_sdk import Keypair, MuxedAccount
from stellar_sdk.strkey import StrKey
from stellar_sdk.exceptions import (
    Ed25519PublicKeyInvalidError,
    MuxedEd25519AccountInvalidError,
)
from project_name import settings # replace project_name with actual Django project name


class SEP10Token:
    """An object that represents the authenticated sessions of the client."""

    _CLAIMS = {"iss", "sub", "exp", "iat"}

    def __init__(self, jwt: Union[str, Dict]):
        if isinstance(jwt, str):
            try:
                jwt = decode(jwt, settings.SERVER_JWT_KEY, algorithms=["HS256"])
            except InvalidTokenError:
                raise ValueError("jwt token has expired or is invalid")

        elif not isinstance(jwt, Dict):
            raise ValueError(
                "invalid type for 'jwt' parameter: must be a string or dictionary"
            )

        if not self._CLAIMS.issubset(set(jwt.keys())):
            raise ValueError(
                f"jwt is missing one of the required claims: {', '.join(self._CLAIMS)}"
            )

        self.memo = None
        self.stellar_account = None

        if jwt["sub"].startswith("M"):
            try:
                StrKey.decode_muxed_account(jwt["sub"])
            except (ValueError, MuxedEd25519AccountInvalidError):
                raise ValueError(f"invalid muxed account: {jwt['sub']}")
        elif ":" in jwt["sub"]:
            try:
                self.stellar_account, self.memo = jwt["sub"].split(":")
            except ValueError:
                raise ValueError(f"improperly formatted 'sub' value: {jwt['sub']}")
        else:
            self.stellar_account = jwt["sub"]

        if self.stellar_account:
            try:
                Keypair.from_public_key(self.stellar_account)
            except Ed25519PublicKeyInvalidError:
                raise ValueError(f"invalid Stellar public key: {jwt['sub']}")

        if self.memo:
            try:
                int(self.memo)
            except ValueError:
                raise ValueError(
                    f"invalid memo in 'sub' value, expected 64-bit integer: {self.memo}"
                )

        try:
            iat = datetime.fromtimestamp(jwt["iat"], tz=timezone.utc)
        except (OSError, ValueError, OverflowError):
            raise ValueError("invalid iat value")
        try:
            exp = datetime.fromtimestamp(jwt["exp"], tz=timezone.utc)
        except (OSError, ValueError, OverflowError):
            raise ValueError("invalid exp value")

        now = datetime.now(tz=timezone.utc)
        if now &amp;lt; iat or now &amp;gt; exp:
            raise ValueError("jwt is no longer valid")

        self._payload = jwt

        @property
        def account(self) -&amp;gt; str:
            """
            The Stellar account (`G...`) authenticated. Note that a muxed account
            could have been authenticated, in which case `Token.muxed_account` should
            be used.
            """
            if self._payload["sub"].startswith("M"):
                return MuxedAccount.from_account(self._payload["sub"]).account_id
            elif ":" in self._payload["sub"]:
                return self._payload["sub"].split(":")[0]
            else:
                return self._payload["sub"]

        @property
        def muxed_account(self) -&amp;gt; Optional[str]:
            """
            The M-address specified in the payload's ``sub`` value, if present
            """
            if self._payload["sub"].startswith("M"):
                return self._payload["sub"]
            else:
                return None

        @property
        def memo(self) -&amp;gt; Optional[int]:
            """
            The memo included with the payload's ``sub`` value, if present
            """
            return (
                int(self._payload["sub"].split(":")[1])
                if ":" in self._payload["sub"]
                else None
            )

        @property
        def issuer(self) -&amp;gt; str:
            """
            The principal that issued a token, RFC7519, Section 4.1.1 — a Uniform
            Resource Identifier (URI) for the issuer
            (https://example.com or https://example.com/G...)
            """
            return self._payload["iss"]

        @property
        def issued_at(self) -&amp;gt; datetime:
            """
            The time at which the JWT was issued RFC7519, Section 4.1.6 -
            represented as a UTC datetime object
            """
            return datetime.fromtimestamp(self._payload["iat"], tz=timezone.utc)

        @property
        def expires_at(self) -&amp;gt; datetime:
            """
            The expiration time on or after which the JWT will not accepted for
            processing, RFC7519, Section 4.1.4 — represented as a UTC datetime object
            """
            return datetime.fromtimestamp(self._payload["exp"], tz=timezone.utc)

        @property
        def payload(self) -&amp;gt; dict:
            """
            The decoded contents of the JWT string
            """
            return self._payload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define a custom authentication scheme
&lt;/h3&gt;

&lt;p&gt;The authentication scheme inherits from the &lt;code&gt;BaseAuthentication&lt;/code&gt; class and allows us to override the authenticate method that performs checks on the request object such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying authorization header format in request i.e. &lt;code&gt;Bearer &amp;lt;token&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Verifying and decoding the JWT token provided in the authorization header.&lt;/li&gt;
&lt;li&gt;Verifying that the credentials provided are tied to an existing User object assuming the User model contains the stellar account as a field. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;code&gt;sep10&lt;/code&gt; app folder add the authentication scheme class below in the &lt;code&gt;authentication.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.contrib.auth import get_user_model
from rest_framework.request import Request
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed as SEP10AuthenticationFailed
from sep10.token import SEP10Token

User = get_user_model()


class SEP10Authentication(BaseAuthentication):
    def authenticate(self, request: Request) -&amp;gt; tuple[User, SEP10Token]:
        """
        This function authenticates a user by verifying and decoding
        a JWT token from the authorization header of a request.

        :param request: The HTTP request object that contains information
                        about the incoming request, such as headers, query
                        parameters, and request body
        :return: a tuple containing the authenticated User object and
                 the SEP10 token object.
        """
        auth_header = request.headers.get("Authorization")

        if not auth_header:
            return None

        if not auth_header.startswith("Bearer "):
            raise SEP10AuthenticationFailed("Invalid auth header format.")

        jwt = auth_header.split(" ", 1)[1]

        token = SEP10Token(jwt)

        try:
            user = User.objects.get(stellar_account=token.stellar_account)
        except User.DoesNotExist:
            raise SEP10AuthenticationFailed(
                "No active account found with the given credentials."
            )

        return (user, token)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The custom authentication scheme can be set globally on the default authentication classes setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["sep10.authentication.SEP10Authentication",]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or on a per-view or per-viewset basis, using the APIView class-based views:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sep10.authentication import SEP10Authentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    authentication_classes = [SEP10Authentication]
    permission_classes = [IsAuthenticated]

    def get(self, request, format=None):
        content = {}
        return Response(content)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if you're using the &lt;code&gt;@api_view&lt;/code&gt; decorator with function-based views:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@api_view(['GET'])
@authentication_classes([SEP10Authentication])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):
    content = {}
    return Response(content)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define helper functions
&lt;/h3&gt;

&lt;p&gt;These helper functions wrap the functionality of the SEP10 Authentication into tangible views or viewsets using the following operations: &lt;code&gt;build_challenge_transaction&lt;/code&gt;, &lt;code&gt;read_challenge_transaction&lt;/code&gt; and &lt;code&gt;verify_challenge_transaction_threshold&lt;/code&gt; which can be found in detail in the &lt;a href="https://stellar-sdk.readthedocs.io/en/stable/api.html#sep-0010-stellar-web-authentication" rel="noopener noreferrer"&gt;stellar-sdk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;sep10&lt;/code&gt; app folder add the helper functions below in the &lt;code&gt;helpers.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
import jwt
import logging
from urllib.parse import urlparse
from stellar_sdk.sep.stellar_web_authentication import (
    build_challenge_transaction,
    read_challenge_transaction,
    InvalidSep10ChallengeError,
    verify_challenge_transaction_threshold,
)
from stellar_sdk import MuxedAccount, exceptions
from project_name import settings


logger = logging.getLogger(__name__)


def _challenge_transaction(
    client_account_id,
    home_domain,
    client_domain=None,
    client_signing_key=None,
    memo=None,
):
    """
    This function generates a challenge transaction for a client account in Python, as per SEP 10.

    :param client_account_id: The Stellar account ID of the client requesting authentication
    :param home_domain: The domain of the Stellar account issuing the challenge transaction.
    This is typically the domain of the server that is providing the authentication service
    :param client_domain: The domain of the client requesting the challenge transaction. It is an
    optional parameter
    :param client_signing_key: The public key of the client account's signing key. This is used to
    verify the signature of the challenge transaction
    :param memo: A memo to include in the challenge transaction. This is an optional parameter and can
    be used to include additional information in the transaction
    :return: The XDR encoding of the challenge transaction for a client account.
    """
    return build_challenge_transaction(
        server_secret=settings.SIGNING_SEED,
        client_account_id=client_account_id,
        home_domain=home_domain,
        web_auth_domain=urlparse(settings.HOST_URL).netloc,
        network_passphrase=settings.STELLAR_NETWORK,
        client_domain=client_domain,
        client_signing_key=client_signing_key,
        memo=memo,
    )


def _generate_jwt(envelope_xdr: str) -&amp;gt; str:
    """
    Generates the JSON web token from the challenge transaction XDR.

    See: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md#token
    """
    try:
        challenge = read_challenge_transaction(
            challenge_transaction=envelope_xdr,
            server_account_id=settings.SIGNING_KEY,
            home_domains=settings.SEP10_HOME_DOMAINS,
            web_auth_domain=urlparse(settings.HOST_URL).netloc,
            network_passphrase=settings.STELLAR_NETWORK,
        )

    except (InvalidSep10ChallengeError, TypeError) as e:
        logger.error(f"Invalid challenge transaction: {e}")
        raise ValueError(f"Invalid challenge transaction: {e}")

    # extract the Stellar account from the muxed account to check for its existence
    stellar_account = challenge.client_account_id
    if challenge.client_account_id.startswith("M"):
        stellar_account = MuxedAccount.from_account(
            challenge.client_account_id
        ).account_id

    with settings.HORIZON_SERVER as server:
        try:
            account = server.load_account(stellar_account)
        except exceptions.NotFoundError:
            raise ValueError(f"Account {stellar_account} not found")

    signers = account.load_ed25519_public_key_signers()
    threshold = account.thresholds.med_threshold
    try:
        signers_found = verify_challenge_transaction_threshold(
            challenge_transaction=envelope_xdr,
            server_account_id=settings.SIGNING_KEY,
            home_domains=settings.SEP10_HOME_DOMAINS,
            web_auth_domain=urlparse(settings.HOST_URL).netloc,
            network_passphrase=settings.STELLAR_NETWORK,
            threshold=threshold,
            signers=signers,
        )
        logger.info(
            f"Generating SEP-10 token for account {challenge.client_account_id}"
        )
    except InvalidSep10ChallengeError as e:
        logger.error(f"Invalid challenge transaction: {e}")
        raise ValueError(f"Invalid challenge transaction: {e}")

    logger.info(
        "Challenge verified using account signers: "
        f"{[s.account_id for s in signers_found]}"
    )

    # set iat value to minimum timebound of the challenge so that the JWT returned
    # for a given challenge is always the same.
    # https://github.com/stellar/stellar-protocol/pull/982
    issued_at = challenge.transaction.transaction.preconditions.time_bounds.min_time

    # format sub value based on muxed account or memo
    if challenge.client_account_id.startswith("M") or not challenge.memo:
        sub = challenge.client_account_id
    else:
        sub = f"{challenge.client_account_id}:{challenge.memo}"

    jwt_dict = {
        "iss": os.path.join(settings.HOST_URL, "auth"),
        "sub": sub,
        "iat": issued_at,
        "exp": issued_at + 24 * 60 * 60,
        "jti": challenge.transaction.hash().hex(),
    }
    return jwt.encode(jwt_dict, settings.SERVER_JWT_KEY, algorithm="HS256")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define views to handle the authentication flow
&lt;/h3&gt;

&lt;p&gt;The views will be defined based on the auth flow below:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbenkiko.s3.us-east-2.amazonaws.com%2Fsep10auth.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbenkiko.s3.us-east-2.amazonaws.com%2Fsep10auth.png" alt="sep-10 auth flow" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going with the single responsibility principle, we'll separate the auth flow into three separate class-based views; &lt;code&gt;GetChallengeTransaction&lt;/code&gt;, &lt;code&gt;SignChallengeTransaction&lt;/code&gt; and &lt;code&gt;GetJWTToken&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;sep10&lt;/code&gt; app folder add the view-based classes below in the &lt;code&gt;views.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import logging

from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

from rest_framework import status
from stellar_sdk import Keypair, exceptions, helpers
from sep10.helpers import _challenge_transaction, _generate_jwt
from project_name import settings

logger = logging.getLogger(__name__)


class GetChallengeTransaction(APIView):
    def get(self, request: Request) -&amp;gt; Response:
        with settings.HORIZON_SERVER as server:
            client_account = request.query_params.get("client_account")
            home_domain = request.query_params.get("home_domain")

            try:
                server.load_account(client_account)
            except exceptions.NotFoundError:
                return Response(
                    {"error": "Client account not found."},
                    status=status.HTTP_404_NOT_FOUND,
                )

            if home_domain not in settings.SEP10_HOME_DOMAINS:
                return Response(
                    {"error": "invalid 'home_domain' value."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            try:
                transaction = _challenge_transaction(client_account, home_domain)
            except ValueError as e:
                return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

            logger.info(f"Returning SEP-10 challenge for account {client_account}")

            return Response(
                {
                    "transaction": transaction,
                    "network_passphrase": settings.STELLAR_NETWORK,
                },
                status=status.HTTP_200_OK,
            )


class SignChallengeTransaction(APIView):
    def post(self, request: Request) -&amp;gt; Response:
        with settings.HORIZON_SERVER as server:
            transaction = request.data.get("challenge_transaction_xdr")
            client_account_seed = request.data.get("client_account_seed")
            signer_keypair = Keypair.from_secret(client_account_seed)
            source = signer_keypair.public_key

            # load source account. fail-safe if source account is not found
            try:
                server.load_account(source)
            except exceptions.NotFoundError:
                return Response(
                    {"error": "Client account not found."},
                    status=status.HTTP_404_NOT_FOUND,
                )

            # sign challenge transaction
            try:
                # Parse xdr obj to transaction envelope
                envelope = helpers.parse_transaction_envelope_from_xdr(
                    transaction, settings.STELLAR_NETWORK
                )
                envelope.sign(signer_keypair)
                logger.info(f"Signed SEP-10 challenge for client account {source}")
                return Response(
                    {
                        "transaction": envelope.to_xdr(),
                        "network_passphrase": settings.STELLAR_NETWORK,
                    },
                    status=status.HTTP_200_OK,
                )
            except (exceptions.SignatureExistError, ValueError) as e:
                logger.error("%s", str(e))
                return Response(
                    {"error": str(e)}, status=status.HTTP_400_BAD_REQUEST
                )

class GetJWTToken(APIView):
    def post(self, request: Request) -&amp;gt; Response:
        transaction = request.data.get("signed_challenge_transaction_xdr")
        # Parse xdr obj to transaction envelope to validate
        try:
            helpers.parse_transaction_envelope_from_xdr(
                transaction, settings.STELLAR_NETWORK
            )

        except ValueError as e:
            logger.error("%s", str(e))
            return Response(
                {"error": str(e)}, status=status.HTTP_400_BAD_REQUEST
            )

        try:
            jwt_token = _generate_jwt(transaction)
            return Response(
                {
                    "token": jwt_token,
                },
                status=status.HTTP_200_OK,
            )
        except Exception as e:
            logger.error("%s", str(e))
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, in the &lt;code&gt;urls.py&lt;/code&gt; file in the &lt;code&gt;sep10&lt;/code&gt; app folder add the following paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from sep10 import views
from django.urls import path


app_name = "sep10"

urlpatterns = [
    path(
        "challenge",
        views.GetChallengeTransaction.as_view(),
        name="sep10-challenge",
    ),
    path(
        "sign",
        views.SignChallengeTransaction.as_view(),
        name="sign-challenge",
    ),
    path(
        "token",
        views.GetJWTToken.as_view(),
        name="jwt-token",
    ),
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;add &lt;code&gt;sep10&lt;/code&gt; app URLs in &lt;code&gt;project_name/urls.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.urls import include, re_path

urlpatterns = [
    re_path(r"^v1/auth/", include("sep10.urls", namespace="v1:sep10")),
]

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

&lt;/div&gt;



&lt;p&gt;Response snippets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET auth/challenge

 data: {
    "transaction": "AAAAAgAAAAAOzp8SYe...",
    "network_passphrase": "Test SDF Network ; September 2015"
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST auth/sign

 data: {
    "transaction": "AAAAAgAAAAAOzp8SYe...",
    "network_passphrase": "Test SDF Network ; September 2015"
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST auth/token

 data: {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...."
  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The Stellar network boasts ecosystem proposals that depict engineering marvels and Stellar Web Authentication (SEP-0010) is one of them, you can find other ecosystem proposals in detail &lt;a href="https://github.com/stellar/stellar-protocol/tree/master/ecosystem" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Thank you for reading to the end of this article. You can find a live implementation of the SEP-0010 protocol &lt;a href="https://api.benkiko.io/#tag/Access" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://auth0.com/learn/json-web-tokens" rel="noopener noreferrer"&gt;Get started with JWT&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/stellar/django-polaris/tree/master/polaris/sep10" rel="noopener noreferrer"&gt;Django Polaris&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>blockchain</category>
      <category>restapi</category>
    </item>
    <item>
      <title>What happens when you type a URL on the browser and press enter</title>
      <dc:creator>Samuel Mugane</dc:creator>
      <pubDate>Fri, 12 May 2023 11:24:12 +0000</pubDate>
      <link>https://dev.to/roguecode25/what-happens-when-you-type-a-url-on-the-browser-and-press-enter-1eng</link>
      <guid>https://dev.to/roguecode25/what-happens-when-you-type-a-url-on-the-browser-and-press-enter-1eng</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Understanding how the web works is a great start to building web stacks that align with the principles associated with the web. Hence, in this article, the focus will be to debunk what happens when you request a specific URL through the browser. The article goes into detail in explaining the various components of the URL, communication protocols used on the web, and server components that are involved in processing the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow of the request
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Typing the URL and pressing enter
&lt;/h3&gt;

&lt;p&gt;When you type the URL, it is usually characterized by various components separated by special characters such as semi-colons, backward slashes, or periods. The URL is composed of the scheme i.e. &lt;code&gt;https://&lt;/code&gt;, the domain i.e. &lt;code&gt;google.com&lt;/code&gt;, the path i.e. &lt;code&gt;/maps&lt;/code&gt;, and the resource i.e. &lt;code&gt;{long, lat}&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Scheme&lt;/p&gt;

&lt;p&gt;The scheme &lt;code&gt;https://&lt;/code&gt; stands for &lt;code&gt;HyperText Transfer Protocol Secure&lt;/code&gt;. Its an extension of &lt;code&gt;HTTP&lt;/code&gt;, an application protocol (OSI 7) built on &lt;code&gt;TCP&lt;/code&gt; as the transport layer (OSI 3). This scheme tells the browser to make a connection to the server using &lt;code&gt;TLS&lt;/code&gt; (Transport Layer Security). &lt;code&gt;TLS&lt;/code&gt; is a secure successor to &lt;code&gt;SSL&lt;/code&gt; (Secure Sockets Layer). &lt;code&gt;SSL&lt;/code&gt; is a technology that clients and servers rely upon to communicate in a secure manner using encrypted communication channels over any network. To set up the encrypted communication channel, the client and the server perform a handshake facilitated through digital certificates known as `TLS/SSL certificates.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Domain&lt;/p&gt;

&lt;p&gt;The component &lt;code&gt;google.com&lt;/code&gt; is the domain name. A domain name is a human-readable address that points to a specific &lt;code&gt;IP&lt;/code&gt; (Internet protocol) address. Domain names make it easier for clients to access resources across the web. It is hard to memorize an &lt;code&gt;IP&lt;/code&gt; address in comparison to a domain name. &lt;code&gt;IP&lt;/code&gt; addresses are versioned where we have &lt;code&gt;IPV4&lt;/code&gt; the fourth version of the Internet Protocol made up of 32 bits, divided into four 8-bit segments i.e. 8.8.8.8/8.8.4.4 for &lt;code&gt;google.com&lt;/code&gt;. &lt;code&gt;IPV4&lt;/code&gt; is only limited to 4.3B unique addresses. There is also &lt;code&gt;IPV6&lt;/code&gt;, the sixth version of the Internet Protocol made up of 128-bit addresses that allow for trillions of unique addresses i.e. 2001:4860:4860::8888 for &lt;code&gt;google.com&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Path&lt;br&gt;
 A path i.e. &lt;code&gt;/maps&lt;/code&gt; points a resource that the user wants to access on the site visited. The resource might be static content i.e. HTML, CSS or JavaScript or dynamically generated content i.e. reviews.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource&lt;br&gt;
 The resource &lt;code&gt;{long, lat}&lt;/code&gt; represents a place within the maps resource path provided by Google in the maps service. The resource might be in the form of static or dynamic content. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Browser resolves the domain to its unique IP
&lt;/h3&gt;

&lt;p&gt;When the URL is accessed, the browser first makes a &lt;code&gt;DNS&lt;/code&gt; request to the &lt;code&gt;DNS&lt;/code&gt; server where the domain in the URL is resolved and an &lt;code&gt;IP&lt;/code&gt; address is returned as a response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DNS (Domain Name System)&lt;/p&gt;

&lt;p&gt;A database system that maps domain names to &lt;code&gt;IP&lt;/code&gt; addresses, allowing browsers to request specific websites and servers to communicate with each other. It is a high-level abstraction that abstracts the complexity of &lt;code&gt;IP&lt;/code&gt; addresses.&lt;br&gt;
The lookup process is shown below:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  3. Browser initiates a &lt;code&gt;TCP&lt;/code&gt; connection with the server
&lt;/h3&gt;

&lt;p&gt;Transmission Control Protocol (TCP) is a communications protocol that enables reliable and ordered delivery of data packets between two hosts i.e. the client and the server. The browser uses the &lt;code&gt;IP&lt;/code&gt; address from the DNS server to make the TCP connection using a 3-way handshake shown below: &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk7o3gmp6zsnp2x9s1mk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzk7o3gmp6zsnp2x9s1mk.jpg" alt="TCP 3-way handshake" width="526" height="464"&gt;&lt;/a&gt;&lt;br&gt;
The communication channel establish between the client and the server relies on &lt;code&gt;TLS&lt;/code&gt; to encrypt all data packets shared between the two hosts.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Browser sends the HTTP request to the server.
&lt;/h3&gt;

&lt;p&gt;After the encrypted communication channel is established, the browser can now send a HTTP request to the server and receive a response safely. A HTTP request is a message sent by a client to a server to request access to some resource. A HTTP request is made up of various components including a request line, request headers, and message body (optional). &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Request line&lt;/p&gt;

&lt;p&gt;The request line contains the method i.e. &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt;. It also contains the path i.e. &lt;code&gt;/&lt;/code&gt; depicting the root path and the version of HTTP being used to make the request i.e. &lt;code&gt;HTTP/1.1&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Request headers&lt;/p&gt;

&lt;p&gt;The request provides additional information such as the browser making the request i.e &lt;code&gt;User-Agent: Chrome/68.0.3440.106&lt;/code&gt;, the type of content the server accepts i.e &lt;code&gt;Content-Type: application/json&lt;/code&gt; to show the server accepts content in JSON format, or the host the request is being made to i.e &lt;code&gt;Host: google.com&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Message body&lt;/p&gt;

&lt;p&gt;The message body represents data being sent to the server and it is used with request methods such as &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;PUT&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of a HTTP request:&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
GET / HTTP/1.1&lt;br&gt;
Host: google.com&lt;br&gt;
User-Agent: Chrome/68.0.3440.106&lt;br&gt;
Accept: text/html&lt;br&gt;
Accept-Language: en-US&lt;br&gt;
Accept-Encoding: gzip&lt;br&gt;
Connection: keep-alive&lt;br&gt;
Content-Type: multipart/form-data&lt;br&gt;
Content-Length: 256&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Server receives request, processes the request and returns a response
&lt;/h3&gt;

&lt;p&gt;The HTTP request goes through the Web Application Firewall (WAF) which is a component of the web stack that protects the web application from malicious HTTP traffic by analyzing and filtering the traffic.&lt;/p&gt;

&lt;p&gt;The HTTP request then goes through a load balancer which is another component within the web stack that ensures traffic is distributed appropriately to the web server(s). The load balancer is also used to terminate TLS/SSL. HAProxy is one of the most used load balancers.&lt;/p&gt;

&lt;p&gt;The web server, a software that serves static or dynamic content to the web receives the request and processes it. It ensures that all the required headers are in the request and that the resource path exists. If the request is for static content i.e. &lt;code&gt;GET /index.html&lt;/code&gt;, the web server will look up the &lt;code&gt;.html&lt;/code&gt; file within the application code. If the content is dynamic and requires any business logic to generate, the web server communicates with the application server. Examples of web servers include NGINX and Apache.&lt;/p&gt;

&lt;p&gt;An application server is a software framework that handles business logic, database transactions, and communication between applications and users. The application server resolves the request for dynamic content and returns a response to the web server.&lt;/p&gt;

&lt;p&gt;The web server returns the content as a HTTP response back to the client (browser). The HTTP response is made up of various components including the status line, response headers, and message body.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Status line&lt;/p&gt;

&lt;p&gt;The status line contains the version of HTTP used i.e &lt;code&gt;HTTP/1.1&lt;/code&gt; and the status code of the request i.e &lt;code&gt;200 OK&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Response headers&lt;/p&gt;

&lt;p&gt;The response headers can include: &lt;code&gt;Server: Apache/2.4.46&lt;/code&gt;, &lt;code&gt;Content-Length: 1024&lt;/code&gt;, or &lt;code&gt;Content-Type: text/html&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Message body&lt;/p&gt;

&lt;p&gt;The message body contains the content returned by the web server i.e. a text or a JSON response.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of a HTTP response&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
HTTP/1.1 200 OK&lt;br&gt;
Date: Fri, 12 May 2023 01:11:12 GMT&lt;br&gt;
Server: Nginx/1.24&lt;br&gt;
Last-Modified: Thur, 11 May 2023&lt;br&gt;
ETag: "0-23-4024c3a5"&lt;br&gt;
Accept-Ranges: bytes&lt;br&gt;
Content-Length: 42&lt;br&gt;
Connection: close&lt;br&gt;
Content-Type: text/html&lt;/p&gt;

&lt;h1&gt;Holberton School&lt;/h1&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Browser renders the content
&lt;/h3&gt;

&lt;p&gt;The browser receives the response from the server and checks the response headers to know how to render the content. for example, if the &lt;code&gt;Content-Type&lt;/code&gt; header is &lt;code&gt;text/html&lt;/code&gt;, the browser knows that it will render a html file to the user. If the &lt;code&gt;Content-Type&lt;/code&gt; is &lt;code&gt;application/json&lt;/code&gt; the browser will parse the JSON data into an object and wrap the object in a HTML element and render it. The rendering of the content is done through the DOM, a high-level Web API provided by the browser to efficiently render a webpage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Understanding the concepts outlaid above helps assess avenues for improving the reliability, performance, and security of the web.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Caching Django Application using Redis</title>
      <dc:creator>Samuel Mugane</dc:creator>
      <pubDate>Tue, 31 May 2022 18:36:44 +0000</pubDate>
      <link>https://dev.to/roguecode25/caching-django-applications-using-redis-8l3</link>
      <guid>https://dev.to/roguecode25/caching-django-applications-using-redis-8l3</guid>
      <description>&lt;p&gt;&lt;a href="https://www.treinaweb.com.br/blog/utilizando-o-redis-como-cache-em-um-projeto-django" rel="noopener noreferrer"&gt;Banner Source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When building web applications, optimization is key for user experience. In most cases, requests made in the client-side prompt the back-end to communicate with the database.The back-end retrieves the data from the database and relays it to the client. In a normal use case, the client will prompt the server multiple times. Hence, multiple hits are made by the back-end to the database to retrieve data and process it to the client. &lt;/p&gt;

&lt;p&gt;In Django, this can be a performance trade-off. Caching can help eliminate the performance trade-off by storing copies of data where it can be accessed more quickly in the client-side when the same request is made multiple times. A browser cache comes into play when handling client-side requests. There are more optimization tricks that one can implement as discussed in the &lt;a href="https://docs.djangoproject.com/en/4.0/topics/performance/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A visual of Browser Cache functionality
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsugyuvdksx7n7yyt41q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsugyuvdksx7n7yyt41q.png" alt="Cache Functionality" width="681" height="510"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://cdn.pressidium.com/wp-content/uploads/2017/05/Pressidium_blogpost_04_05_2017-05.png" rel="noopener noreferrer"&gt;Image Source: Pressidium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learn more about the browser cache functionality &lt;a href="https://www.section.io/engineering-education/understanding-browser-caching/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To implement caching in Django application. First, set up your Django project and application. Then install django-redis, a project by &lt;a href="https://github.com/jazzband/django-redis" rel="noopener noreferrer"&gt;Jazzband&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install django-redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;settings.py&lt;/code&gt; file, add the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {  
          "CLIENT_CLASS":"django_redis.client.DefaultClient",         
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can add more configurations as provided in the package &lt;a href="https://github.com/jazzband/django-redis" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing caching on views
&lt;/h3&gt;

&lt;p&gt;In this case, the caching functionality will be implemented to a view in an e-commerce API I developed, you can check it &lt;a href="https://github.com/mugane-dj/django-ecommerce-api" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rest_framework.views import APIView
from django.core.cache import cache

class ProductDetailView(APIView):

   def get(self, request, *args, **kwargs):
       productID = kwargs['pk']
       if cache.get(productID):
          product = cache.get(productID)
          print("Cache hit")
       else:
           try:
             product = Product.objects.get(pk=productID)
                cache.set(productID, product)
                print("Cache miss")
           except Product.DoesNotExist:
                return Response(status=404)
       serializer = ProductSerializer(product, many=False)
       return Response(serializer.data)

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

&lt;/div&gt;



&lt;p&gt;In the code above, when a request is made to the ProductDetailView route, the database will be prompted to retrieve a product based on the productID. When the same request is made, the console will print out &lt;code&gt;Cache hit&lt;/code&gt; and use the data stored prior to the request to serve to the client.&lt;/p&gt;

&lt;p&gt;When the request is new in the subsequent queue, the console will print out &lt;code&gt;Cache miss&lt;/code&gt; since no data regarding the request was cached prior to the request being made. Hence, the database will be prompted again and the back-end will process the new request. Otherwise, a code 404 will be raised to signal that the Product Model doesn't exist; hence, no data is retrievable. &lt;/p&gt;

&lt;h3&gt;
  
  
  Final Note
&lt;/h3&gt;

&lt;p&gt;In production, the cache configuration in the &lt;code&gt;settings.py&lt;/code&gt; file will require changes depending on the cache service used.&lt;br&gt;
The example below is deployment on &lt;a href="https://devcenter.heroku.com/articles/heroku-redis" rel="noopener noreferrer"&gt;heroku&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": os.getenv('REDIS_URL'),
        "OPTIONS": {
          "CLIENT_CLASS":"django_redis.client.DefaultClient",
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The location is changed to match the url of the Cache service for example ElastiCache from AWS. &lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>redis</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Setting up a PostgreSQL database in AWS RDS and connecting it to pgAdmin.</title>
      <dc:creator>Samuel Mugane</dc:creator>
      <pubDate>Mon, 28 Mar 2022 11:14:34 +0000</pubDate>
      <link>https://dev.to/roguecode25/setting-up-a-postgresql-database-in-aws-rds-and-connecting-it-to-pgadmin-10mb</link>
      <guid>https://dev.to/roguecode25/setting-up-a-postgresql-database-in-aws-rds-and-connecting-it-to-pgadmin-10mb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;PgAdmin is a client-side platform for adminstration and development of PostgreSQL database. It simplifies the visualization of schemas, logs and other relevant information based on SQL standards. Amazon has a great relational database hosting service known as Amazon Relational Database Service (RDS). The article focuses on creating a PostgreSQL database in RDS and connecting it pgAdmin.&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a PostgreSQL database in AWS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Setup and login to your AWS account as ROOT user. Go to services, choose database and select RDS. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4n0hsvgfh09rosvt8ah3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4n0hsvgfh09rosvt8ah3.png" alt="screenshot" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will be redirected to a dashboard as shown below. Click on create database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
Select PostgreSQL under engine options and choose templates as shown below. Use Free Tier if setting up the database for personal projects. &lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
Scroll down to settings and set master username and password. Copy these credentials to the clipboard as they will be used to make the pgAdmin connection. &lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
Scroll down to connectivity and select "Yes" for public access. This will allow the database to accept the connection from local setup. &lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
Scroll down and click on "create database". The process will take a few minutes and you will be directed to the page below. Copy the endpoint to the clipboard for later reference.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
Under security, click on the VPC security groups  and you will be redirected to an EC2 console as shown below.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
Click on security group ID and you will be redirected to the page below.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
Under inbound rules, check if there are rules for PostgreSQL that accepts TCP connections. If there isn't click on "edit inbound rules". Click on "Add rule". Under type, select PostgreSQL. Under source, select custom. Under the search input, select &lt;code&gt;0.0.0.0/0&lt;/code&gt; and click on "Save rules".&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The PostgreSQL database has been successfully been created and ready to accept connections from a local host.&lt;/p&gt;



&lt;h2&gt;
  
  
  Installing pgAdmin and making RDS connection
&lt;/h2&gt;

&lt;p&gt;First we need to install pgAdmin to make the connection to our PostgreSQL database hosted in AWS RDS. &lt;br&gt;
Here is an &lt;a href="https://www.pgadmin.org/download/pgadmin-4-apt/" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt; for installing pgAdmin on Ubuntu, Mac and Windows.&lt;/p&gt;

&lt;p&gt;After installing pgAdmin, launch it and register a new server as shown below.&lt;/p&gt;

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

&lt;p&gt;Under general, enter server name and move to connection tab. Under host name/address, paste the endpoint copied from AWS-RDS console. Enter the port set in RDS. Enter the master username set on RDS under username and corresponding password. Under advanced, set connection timeout (seconds) to 1000 secs to avoid timeout during connection. Leave every other configuration in its default.&lt;/p&gt;

&lt;p&gt;After the connection is accepted, the pgAdmin dashboard will look as follows;&lt;/p&gt;

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

&lt;p&gt;Now you can view tables created under schemas/tables. &lt;/p&gt;

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

&lt;p&gt;PgAdmin offers a versatile interface to view database information while AWS RDS offers a great service to host databases to the cloud for better security and ease of access. &lt;/p&gt;

</description>
      <category>aws</category>
      <category>postgres</category>
      <category>database</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using Django Template Context</title>
      <dc:creator>Samuel Mugane</dc:creator>
      <pubDate>Sun, 13 Mar 2022 12:03:04 +0000</pubDate>
      <link>https://dev.to/roguecode25/using-django-template-context-2ela</link>
      <guid>https://dev.to/roguecode25/using-django-template-context-2ela</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Django has proven its resilience as a framework for web development. Django provides developers with a discrete playing field with powerful libraries that help cut down on development time. Django enables the developer to engage with both the client-side and the server-side in a well versed environment. In this article, we explore the Django template context that helps with rendering content to a template on the client-side.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Python 3.x&lt;/li&gt;
&lt;li&gt;Django&lt;/li&gt;
&lt;li&gt;Pip&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;As always, having a virtual environment set up is crucial as it helps with controlling code dependencies. So create a virtual environment using python venv a standard library for creating and managing virtual environments. Using terminal, implement the following steps. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make new directory &lt;code&gt;mkdir directoryname&lt;/code&gt; and cd into the new directory &lt;code&gt;cd directoryname&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create virtual environment &lt;code&gt;python3 -m venv myvenv&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CD into the virtual environment &lt;code&gt;cd myvenv&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Activate virtual environment &lt;code&gt;source bin/activate&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Now install Django in new virtual environment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, install pip &lt;code&gt;sudo apt-get install python3-pip&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using pip, install Django framework &lt;code&gt;pip3 install django&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify installation &lt;code&gt;django-admin --version&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Set up Django project
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With Django framework now installed, create Django project using &lt;code&gt;django-admin startproject projectname&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CD into the project created &lt;code&gt;cd projectname&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make migrations for the database &lt;code&gt;python3 manage.py migrate&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create super user for admin access using &lt;code&gt;python3 manage.py createsuperuser&lt;/code&gt;  and enter your username, email and password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now create your first Django app using &lt;code&gt;python3 manage.py startapp appname&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start server &lt;code&gt;python3 manage.py runserver&lt;/code&gt; and on your terminal you will get a link i.e &lt;code&gt;http://127.0.0.1:8000/&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you click the link, you will be directed to a webpage on your browser and it should look as shown below:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Rendering your first template
&lt;/h2&gt;

&lt;p&gt;Django has a dynamic templating system that helps in rendering HTML files to the web. &lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring settings.py file
&lt;/h3&gt;

&lt;p&gt;Go to settings.py under your project folder and configure the INSTALLED_APPS list variable. Add &lt;code&gt;'my_app.apps.WebAppConfig'&lt;/code&gt; to the list variable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating templates folder
&lt;/h4&gt;

&lt;p&gt;In your app folder, create a new folder and name it templates. Inside the templates folder create another folder with the same name as your app name i.e if you app name is my_app the folder inside the templates folder should be my_app too.&lt;/p&gt;

&lt;p&gt;Create an index.html file in the newly created folder.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating your first view
&lt;/h4&gt;

&lt;p&gt;Go to views.py file in your app folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.shortcuts import render

def home(request):
    return render(request, 'my_app/index.html')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your app folder, create a urls.py file and initiate your home page route&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.urls import path
from my_app.views home

urlpatterns = [
    path('', home, name='home'),
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your project folder, edit the urls.py file to include the urls from your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django import urls
from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('my_app.urls'))
]

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using template context
&lt;/h3&gt;

&lt;p&gt;The template context is a dictionary with variable names represented as key value pairs. It is initiated within a view function to pass content to be render to a webpage. For example, we want to render data from the database to a webpage. Let the data be personal information for users. &lt;/p&gt;

&lt;p&gt;Let's create a model for users in models.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.db import models

class Users(models.Model):
    fullname = models.CharField(max_length=100)
    email = models.CharField(max_length=50)
    mobile = models.CharField(max_length=15)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make migrations to database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 manage.py makemigrations
python3 manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To render the data, we can add the context to the home view function as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from multiprocessing import context
from django.shortcuts import render
from .models import Users

def home(request):
    context = {'users_list': Users.objects.all()}
    return render(request, 'my_app/index.html', context)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the index.html file, we can use template tags to render the user information as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!--Users Table--&amp;gt;

&amp;lt;div class="row"&amp;gt;
    &amp;lt;div class="table-responsive bg-white my-3" style="border-radius: 5px;"&amp;gt;
    &amp;lt;div class="title fw-bold fs-3"&amp;gt;
        Users List
    &amp;lt;/div&amp;gt;
    &amp;lt;table class="table table-striped"&amp;gt;
        &amp;lt;thead class="border-bottom font-weight-bold"&amp;gt;
        &amp;lt;tr
            &amp;lt;td&amp;gt;Full Name&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;Mobile&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;Email&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;/thead&amp;gt;
        &amp;lt;tbody&amp;gt;
        {% for user in users_list %}
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;{{user.fullname}}&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;{{user.mobile}}&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;{{user.email}}&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
        {% endfor %}
        &amp;lt;/tbody&amp;gt;
    &amp;lt;/table&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the user information will be render on the webpage inform of a table. The &lt;code&gt;{{user.fullname}}&lt;/code&gt; will be replaced by the fullname of the user and the same is true for the other variable names. &lt;/p&gt;

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

&lt;p&gt;The template context's functionality helps in rendering content to a webpage in a quick and efficient manner. You can learn more about Django template context &lt;a href="https://docs.djangoproject.com/en/4.0/ref/templates/api/#:~:text=A%20context%20processor%20has%20a,added%20to%20the%20template%20context.&amp;amp;text=Custom%20context%20processors%20can%20live%20anywhere%20in%20your%20code%20base." rel="noopener noreferrer"&gt;here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>webdev</category>
      <category>python</category>
      <category>html</category>
    </item>
    <item>
      <title>Using Twilio API in Node.js</title>
      <dc:creator>Samuel Mugane</dc:creator>
      <pubDate>Thu, 03 Mar 2022 14:12:42 +0000</pubDate>
      <link>https://dev.to/roguecode25/using-twilio-api-in-nodejs-27fn</link>
      <guid>https://dev.to/roguecode25/using-twilio-api-in-nodejs-27fn</guid>
      <description>&lt;p&gt;Banner courtesy of &lt;a href="https://dribbble.com/spencergabor" rel="noopener noreferrer"&gt;Spencer Gabor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;APIs (Application programmable interfaces) have revolutionized how data is shared in different sectors across the globe. Developers have a more easier way of accessing data, and providing uniquely, well crafted services to their customers through APIs. Twilio has been a key player in revolutionizing how communication can be leveraged by developers to enhance customer service. Twilio offers programmable voice calls, short-message service (SMS), email service and whatsapp integration as some of the products available to developers. The Twilio API is a pay as you go service, and provides a reliable API for communication. Find more about &lt;a href="https://www.twilio.com/pricing" rel="noopener noreferrer"&gt;pricing here&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
The article focuses on making programmable voice calls, and sending SMS. Twilio API calls for both voice calls, and SMS are easy to make especially when one is familiar with the node environment. The following steps will have you setup, and running:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;NPM&lt;/li&gt;
&lt;li&gt;Dotenv&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;STEP 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Firstly, install twilio library through node package manager (npm). As prerequisites, install &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;node.js&lt;/a&gt;, and &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;. If you are on Ubuntu 20.04, open terminal, and run the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nodejs
sudo apt install npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use different methods to install Node, and npm as shown &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Make a new directory &lt;code&gt;mkdir&lt;/code&gt;, and &lt;code&gt;cd&lt;/code&gt; into that directory. Initialize the directory with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then install the node.js twilio library through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install twilio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STEP 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sign up to &lt;a href="https://www.twilio.com/" rel="noopener noreferrer"&gt;twilio&lt;/a&gt;, and set up a phone number. Under your account info, you'll see your account SID, Auth token, and phone number. Copy them to the clipboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your node development environment, set up a dotenv (.env) file to create environment variables to secure your account SID, and Auth token. As a prerequisite, install dotenv using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install dotenv --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
In your dotenv file, paste your account SID, and Auth Token in the following format:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TWILIO_ACCOUNT_SID={your account SID}
TWILIO_AUTH_TOKEN={your Auth token}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure no spacing between variable name, equal sign, and value. Also, remove curly braces when keying the values.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
In your development environment, create script.js file, and paste the following code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
require('dotenv').config();
const client = require('twilio')(accountSid, authToken);

client.calls
      .create({
         url: 'http://demo.twilio.com/docs/voice.xml',
         to: '',
         from: ''
       })
      .then(call =&amp;gt; console.log(call));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
Paste your phone number as a string to the &lt;code&gt;from:&lt;/code&gt; key, and the phone number your want to call on &lt;code&gt;to:&lt;/code&gt; key i.e  &lt;code&gt;(area code) – (phone number) or (XXX)- XXX - XXXX&lt;/code&gt; . Ensure to follow the &lt;a href="https://en.wikipedia.org/wiki/E.164" rel="noopener noreferrer"&gt;E.164 format&lt;/a&gt; while entering the phone numbers. For message API calls. Using the following code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
require('dotenv').config();
const client = require('twilio')(accountSid, authToken);

client.messages
      .create({
         body: ' ',
         to: '',
         from: ''
       })
      .then(call =&amp;gt; console.log(call));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under &lt;code&gt;body:&lt;/code&gt; key, enter your message. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;N/B&lt;/strong&gt; 
To avoid error during call due to Geo restrictions, go back to your twilio account dashboard, on your left tab click on &lt;strong&gt;&lt;em&gt;#phone&lt;/em&gt;&lt;/strong&gt;, and go to &lt;strong&gt;&lt;em&gt;settings&lt;/em&gt;&lt;/strong&gt;. Click on &lt;strong&gt;&lt;em&gt;Geo permissions&lt;/em&gt;&lt;/strong&gt;, search for your country and enable as shown below:
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedcbabenvg8em3zbn4hm.png" alt="Geo permission settings" width="800" height="330"&gt;
Select country, and save. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Run and Test&lt;/strong&gt;&lt;br&gt;
Back in you development environment, save your code, and run it on terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A JSON response will be logged to your console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "annotation": null,
  "answered_by": null,
  "api_version": "2010-04-01",
  "caller_name": null,
  "date_created": "Tue, 31 Aug 2010 20:36:28 +0000",
  "date_updated": "Tue, 31 Aug 2010 20:36:44 +0000",
  "direction": "inbound",
  "duration": "15",
  "end_time": "Tue, 31 Aug 2010 20:36:44 +0000",
  "forwarded_from": "+141586753093",
  "from": "+987654321",
  "from_formatted": "+987654321",
  "group_sid": null,
  "parent_call_sid": null,
  "phone_number_sid": "PNXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "price": "-0.03000",
  "price_unit": "USD",
  "sid": "CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "start_time": "Tue, 31 Aug 2010 20:36:29 +0000",
  "status": "completed",
  "subresource_uris": {
    "notifications": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Notifications.json",
    "recordings": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Recordings.json",
    "feedback": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Feedback.json",
    "feedback_summaries": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/FeedbackSummary.json",
    "payments": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Payments.json",
    "events": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Events.json",
    "siprec": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Siprec.json",
    "streams": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Streams.json"
  },
  "to": "+123456789",
  "to_formatted": "+123456789",
  "trunk_sid": null,
  "uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Calls/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json",
  "queue_time": "1000"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if status is &lt;code&gt;complete&lt;/code&gt;, you'll receive a demo call to the number you entered to the &lt;code&gt;to:&lt;/code&gt; key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Twilio has a great use case in automating sending confirmation code through SMS or email to users. The programmable voice allows one to make, and receive calls with no hassle. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>npm</category>
      <category>ubuntu</category>
    </item>
  </channel>
</rss>
