<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Yuvraj's CS Blog - The official blog of Yuvraj]]></title><description><![CDATA[Sharing what I learn in a beginner-friendly way.]]></description><link>https://blog.yuvraj.tech</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 23:48:55 GMT</lastBuildDate><atom:link href="https://blog.yuvraj.tech/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Learning Kafka - Real World Example]]></title><description><![CDATA[Now that we understand the basics of Kafka producers and consumers, let's build a more realistic example that shows how Kafka can be used in a real-world scenario.
We'll create a simple order processing system with these components:

Order Service: C...]]></description><link>https://blog.yuvraj.tech/learning-kafka-real-world-example</link><guid isPermaLink="true">https://blog.yuvraj.tech/learning-kafka-real-world-example</guid><category><![CDATA[kafka]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 14 Mar 2025 16:04:31 GMT</pubDate><content:encoded><![CDATA[<p>Now that we understand the basics of Kafka producers and consumers, let's build a more realistic example that shows how Kafka can be used in a real-world scenario.</p>
<p>We'll create a simple order processing system with these components:</p>
<ol>
<li><p><strong>Order Service</strong>: Creates new orders and sends them to Kafka</p>
</li>
<li><p><strong>Payment Service</strong>: Processes payments for orders</p>
</li>
<li><p><strong>Shipping Service</strong>: Handles shipping for paid orders</p>
</li>
<li><p><strong>Notification Service</strong>: Sends notifications about order status</p>
</li>
</ol>
<p>This is a common pattern in microservices architectures, where different services communicate through Kafka.</p>
<h2 id="heading-project-structure">Project Structure</h2>
<p>Our project will have the following structure:</p>
<pre><code class="lang-plaintext">05-real-world/
├── order-service/
│   ├── package.json
│   └── index.js
├── payment-service/
│   ├── package.json
│   └── index.js
├── shipping-service/
│   ├── package.json
│   └── index.js
├── notification-service/
│   ├── package.json
│   └── index.js
└── package.json
</code></pre>
<h2 id="heading-setting-up-the-project">Setting Up the Project</h2>
<p>First, let's create a main package.json file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"kafka-order-processing"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"A real-world example of Kafka for order processing"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"order"</span>: <span class="hljs-string">"cd order-service &amp;&amp; npm start"</span>,
    <span class="hljs-attr">"payment"</span>: <span class="hljs-string">"cd payment-service &amp;&amp; npm start"</span>,
    <span class="hljs-attr">"shipping"</span>: <span class="hljs-string">"cd shipping-service &amp;&amp; npm start"</span>,
    <span class="hljs-attr">"notification"</span>: <span class="hljs-string">"cd notification-service &amp;&amp; npm start"</span>,
    <span class="hljs-attr">"install-all"</span>: <span class="hljs-string">"npm install &amp;&amp; cd order-service &amp;&amp; npm install &amp;&amp; cd ../payment-service &amp;&amp; npm install &amp;&amp; cd ../shipping-service &amp;&amp; npm install &amp;&amp; cd ../notification-service &amp;&amp; npm install"</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"kafkajs"</span>: <span class="hljs-string">"^2.2.4"</span>,
    <span class="hljs-attr">"dotenv"</span>: <span class="hljs-string">"^16.0.3"</span>
  }
}
</code></pre>
<h2 id="heading-creating-the-services">Creating the Services</h2>
<h3 id="heading-1-order-service">1. Order Service</h3>
<p>The Order Service creates new orders and sends them to Kafka.</p>
<h4 id="heading-packagejson">package.json</h4>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"order-service"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Service for creating orders"</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"module"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node index.js"</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"kafkajs"</span>: <span class="hljs-string">"^2.2.4"</span>,
    <span class="hljs-attr">"dotenv"</span>: <span class="hljs-string">"^16.0.3"</span>,
    <span class="hljs-attr">"express"</span>: <span class="hljs-string">"^4.18.2"</span>,
    <span class="hljs-attr">"body-parser"</span>: <span class="hljs-string">"^1.20.2"</span>,
    <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"^9.0.0"</span>
  }
}
</code></pre>
<h4 id="heading-indexjs">index.js</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// order-service/index.js</span>
<span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> bodyParser <span class="hljs-keyword">from</span> <span class="hljs-string">'body-parser'</span>;
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;

<span class="hljs-comment">// Create Express app</span>
<span class="hljs-keyword">const</span> app = express();
app.use(bodyParser.json());

<span class="hljs-comment">// Define Kafka configuration</span>
<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'order-service'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});

<span class="hljs-comment">// Create a producer</span>
<span class="hljs-keyword">const</span> producer = kafka.producer();

<span class="hljs-comment">// Define the topic for new orders</span>
<span class="hljs-keyword">const</span> NEW_ORDER_TOPIC = <span class="hljs-string">'new-orders'</span>;

<span class="hljs-comment">// Connect to Kafka</span>
<span class="hljs-keyword">const</span> connectToKafka = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> producer.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Order service connected to Kafka'</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to connect to Kafka:'</span>, error);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-comment">// Send an order to Kafka</span>
<span class="hljs-keyword">const</span> sendOrderToKafka = <span class="hljs-keyword">async</span> (order) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> producer.send({
      <span class="hljs-attr">topic</span>: NEW_ORDER_TOPIC,
      <span class="hljs-attr">messages</span>: [
        { 
          <span class="hljs-attr">key</span>: order.id, 
          <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(order),
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">'event-type'</span>: <span class="hljs-string">'order-created'</span>,
            <span class="hljs-string">'timestamp'</span>: <span class="hljs-built_in">Date</span>.now().toString()
          }
        }
      ],
    });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Order sent to Kafka: <span class="hljs-subst">${order.id}</span>`</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error sending order to Kafka: <span class="hljs-subst">${error.message}</span>`</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
};

<span class="hljs-comment">// API endpoint to create a new order</span>
app.post(<span class="hljs-string">'/orders'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { customerId, items, totalAmount } = req.body;

  <span class="hljs-comment">// Validate request</span>
  <span class="hljs-keyword">if</span> (!customerId || !items || !totalAmount) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">'Missing required fields'</span> });
  }

  <span class="hljs-comment">// Create a new order</span>
  <span class="hljs-keyword">const</span> order = {
    <span class="hljs-attr">id</span>: uuidv4(),
    customerId,
    items,
    totalAmount,
    <span class="hljs-attr">status</span>: <span class="hljs-string">'created'</span>,
    <span class="hljs-attr">createdAt</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString()
  };

  <span class="hljs-comment">// Send the order to Kafka</span>
  <span class="hljs-keyword">const</span> success = <span class="hljs-keyword">await</span> sendOrderToKafka(order);

  <span class="hljs-keyword">if</span> (success) {
    res.status(<span class="hljs-number">201</span>).json({
      <span class="hljs-attr">message</span>: <span class="hljs-string">'Order created successfully'</span>,
      <span class="hljs-attr">orderId</span>: order.id
    });
  } <span class="hljs-keyword">else</span> {
    res.status(<span class="hljs-number">500</span>).json({
      <span class="hljs-attr">error</span>: <span class="hljs-string">'Failed to create order'</span>
    });
  }
});

<span class="hljs-comment">// Start the server</span>
<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">3000</span>;
app.listen(PORT, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> connectToKafka();
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Order service running on port <span class="hljs-subst">${PORT}</span>`</span>);
});

<span class="hljs-comment">// Handle graceful shutdown</span>
<span class="hljs-keyword">const</span> shutdown = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> producer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Order service disconnected from Kafka'</span>);
    process.exit(<span class="hljs-number">0</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error during shutdown: <span class="hljs-subst">${error.message}</span>`</span>);
    process.exit(<span class="hljs-number">1</span>);
  }
};

process.on(<span class="hljs-string">'SIGINT'</span>, shutdown);
process.on(<span class="hljs-string">'SIGTERM'</span>, shutdown);
</code></pre>
<h3 id="heading-2-payment-service">2. Payment Service</h3>
<p>The Payment Service processes payments for orders.</p>
<h4 id="heading-packagejson-1">package.json</h4>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"payment-service"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Service for processing payments"</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"module"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node index.js"</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"kafkajs"</span>: <span class="hljs-string">"^2.2.4"</span>,
    <span class="hljs-attr">"dotenv"</span>: <span class="hljs-string">"^16.0.3"</span>
  }
}
</code></pre>
<h4 id="heading-indexjs-1">index.js</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// payment-service/index.js</span>
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;

<span class="hljs-comment">// Define Kafka configuration</span>
<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'payment-service'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});

<span class="hljs-comment">// Create consumer and producer</span>
<span class="hljs-keyword">const</span> consumer = kafka.consumer({ <span class="hljs-attr">groupId</span>: <span class="hljs-string">'payment-service-group'</span> });
<span class="hljs-keyword">const</span> producer = kafka.producer();

<span class="hljs-comment">// Define topics</span>
<span class="hljs-keyword">const</span> NEW_ORDER_TOPIC = <span class="hljs-string">'new-orders'</span>;
<span class="hljs-keyword">const</span> PAYMENT_TOPIC = <span class="hljs-string">'payments'</span>;

<span class="hljs-comment">// Connect to Kafka</span>
<span class="hljs-keyword">const</span> connectToKafka = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.connect();
    <span class="hljs-keyword">await</span> producer.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Payment service connected to Kafka'</span>);

    <span class="hljs-comment">// Subscribe to new orders</span>
    <span class="hljs-keyword">await</span> consumer.subscribe({ <span class="hljs-attr">topic</span>: NEW_ORDER_TOPIC, <span class="hljs-attr">fromBeginning</span>: <span class="hljs-literal">true</span> });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Subscribed to new orders topic'</span>);

    <span class="hljs-comment">// Start consuming messages</span>
    <span class="hljs-keyword">await</span> consumer.run({
      <span class="hljs-attr">eachMessage</span>: <span class="hljs-keyword">async</span> ({ topic, partition, message }) =&gt; {
        <span class="hljs-keyword">await</span> processOrder(message);
      },
    });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to connect to Kafka:'</span>, error);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-comment">// Process an order</span>
<span class="hljs-keyword">const</span> processOrder = <span class="hljs-keyword">async</span> (message) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Parse the order</span>
    <span class="hljs-keyword">const</span> order = <span class="hljs-built_in">JSON</span>.parse(message.value.toString());
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Processing payment for order: <span class="hljs-subst">${order.id}</span>`</span>);

    <span class="hljs-comment">// Simulate payment processing</span>
    <span class="hljs-keyword">const</span> paymentSuccessful = <span class="hljs-built_in">Math</span>.random() &gt; <span class="hljs-number">0.2</span>; <span class="hljs-comment">// 80% success rate</span>

    <span class="hljs-comment">// Create payment result</span>
    <span class="hljs-keyword">const</span> paymentResult = {
      <span class="hljs-attr">orderId</span>: order.id,
      <span class="hljs-attr">status</span>: paymentSuccessful ? <span class="hljs-string">'paid'</span> : <span class="hljs-string">'failed'</span>,
      <span class="hljs-attr">amount</span>: order.totalAmount,
      <span class="hljs-attr">processedAt</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString()
    };

    <span class="hljs-comment">// Send payment result to Kafka</span>
    <span class="hljs-keyword">await</span> producer.send({
      <span class="hljs-attr">topic</span>: PAYMENT_TOPIC,
      <span class="hljs-attr">messages</span>: [
        { 
          <span class="hljs-attr">key</span>: order.id, 
          <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(paymentResult),
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">'event-type'</span>: paymentSuccessful ? <span class="hljs-string">'payment-successful'</span> : <span class="hljs-string">'payment-failed'</span>,
            <span class="hljs-string">'timestamp'</span>: <span class="hljs-built_in">Date</span>.now().toString()
          }
        }
      ],
    });

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Payment <span class="hljs-subst">${paymentSuccessful ? <span class="hljs-string">'successful'</span> : <span class="hljs-string">'failed'</span>}</span> for order: <span class="hljs-subst">${order.id}</span>`</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error processing payment: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};

<span class="hljs-comment">// Start the service</span>
<span class="hljs-keyword">const</span> start = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> connectToKafka();
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Payment service is running'</span>);
};

<span class="hljs-comment">// Handle graceful shutdown</span>
<span class="hljs-keyword">const</span> shutdown = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.disconnect();
    <span class="hljs-keyword">await</span> producer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Payment service disconnected from Kafka'</span>);
    process.exit(<span class="hljs-number">0</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error during shutdown: <span class="hljs-subst">${error.message}</span>`</span>);
    process.exit(<span class="hljs-number">1</span>);
  }
};

process.on(<span class="hljs-string">'SIGINT'</span>, shutdown);
process.on(<span class="hljs-string">'SIGTERM'</span>, shutdown);

<span class="hljs-comment">// Start the service</span>
start().catch(<span class="hljs-built_in">console</span>.error);
</code></pre>
<h3 id="heading-3-shipping-service">3. Shipping Service</h3>
<p>The Shipping Service handles shipping for paid orders.</p>
<h4 id="heading-packagejson-2">package.json</h4>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"shipping-service"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Service for handling shipping"</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"module"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node index.js"</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"kafkajs"</span>: <span class="hljs-string">"^2.2.4"</span>,
    <span class="hljs-attr">"dotenv"</span>: <span class="hljs-string">"^16.0.3"</span>
  }
}
</code></pre>
<h4 id="heading-indexjs-2">index.js</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// shipping-service/index.js</span>
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;

<span class="hljs-comment">// Define Kafka configuration</span>
<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'shipping-service'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});

<span class="hljs-comment">// Create consumer and producer</span>
<span class="hljs-keyword">const</span> consumer = kafka.consumer({ <span class="hljs-attr">groupId</span>: <span class="hljs-string">'shipping-service-group'</span> });
<span class="hljs-keyword">const</span> producer = kafka.producer();

<span class="hljs-comment">// Define topics</span>
<span class="hljs-keyword">const</span> PAYMENT_TOPIC = <span class="hljs-string">'payments'</span>;
<span class="hljs-keyword">const</span> SHIPPING_TOPIC = <span class="hljs-string">'shipping'</span>;

<span class="hljs-comment">// Connect to Kafka</span>
<span class="hljs-keyword">const</span> connectToKafka = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.connect();
    <span class="hljs-keyword">await</span> producer.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Shipping service connected to Kafka'</span>);

    <span class="hljs-comment">// Subscribe to payments</span>
    <span class="hljs-keyword">await</span> consumer.subscribe({ <span class="hljs-attr">topic</span>: PAYMENT_TOPIC, <span class="hljs-attr">fromBeginning</span>: <span class="hljs-literal">true</span> });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Subscribed to payments topic'</span>);

    <span class="hljs-comment">// Start consuming messages</span>
    <span class="hljs-keyword">await</span> consumer.run({
      <span class="hljs-attr">eachMessage</span>: <span class="hljs-keyword">async</span> ({ topic, partition, message }) =&gt; {
        <span class="hljs-keyword">await</span> processPayment(message);
      },
    });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to connect to Kafka:'</span>, error);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-comment">// Process a payment</span>
<span class="hljs-keyword">const</span> processPayment = <span class="hljs-keyword">async</span> (message) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Parse the payment</span>
    <span class="hljs-keyword">const</span> payment = <span class="hljs-built_in">JSON</span>.parse(message.value.toString());

    <span class="hljs-comment">// Only process successful payments</span>
    <span class="hljs-keyword">if</span> (payment.status !== <span class="hljs-string">'paid'</span>) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Skipping shipping for failed payment: <span class="hljs-subst">${payment.orderId}</span>`</span>);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Processing shipping for order: <span class="hljs-subst">${payment.orderId}</span>`</span>);

    <span class="hljs-comment">// Simulate shipping processing</span>
    <span class="hljs-keyword">const</span> shippingSuccessful = <span class="hljs-built_in">Math</span>.random() &gt; <span class="hljs-number">0.1</span>; <span class="hljs-comment">// 90% success rate</span>

    <span class="hljs-comment">// Create shipping result</span>
    <span class="hljs-keyword">const</span> shippingResult = {
      <span class="hljs-attr">orderId</span>: payment.orderId,
      <span class="hljs-attr">status</span>: shippingSuccessful ? <span class="hljs-string">'shipped'</span> : <span class="hljs-string">'shipping-failed'</span>,
      <span class="hljs-attr">trackingNumber</span>: shippingSuccessful ? <span class="hljs-string">`TRK-<span class="hljs-subst">${<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000000</span>)}</span>`</span> : <span class="hljs-literal">null</span>,
      <span class="hljs-attr">processedAt</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString()
    };

    <span class="hljs-comment">// Send shipping result to Kafka</span>
    <span class="hljs-keyword">await</span> producer.send({
      <span class="hljs-attr">topic</span>: SHIPPING_TOPIC,
      <span class="hljs-attr">messages</span>: [
        { 
          <span class="hljs-attr">key</span>: payment.orderId, 
          <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(shippingResult),
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">'event-type'</span>: shippingSuccessful ? <span class="hljs-string">'order-shipped'</span> : <span class="hljs-string">'shipping-failed'</span>,
            <span class="hljs-string">'timestamp'</span>: <span class="hljs-built_in">Date</span>.now().toString()
          }
        }
      ],
    });

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Shipping <span class="hljs-subst">${shippingSuccessful ? <span class="hljs-string">'successful'</span> : <span class="hljs-string">'failed'</span>}</span> for order: <span class="hljs-subst">${payment.orderId}</span>`</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error processing shipping: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};

<span class="hljs-comment">// Start the service</span>
<span class="hljs-keyword">const</span> start = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> connectToKafka();
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Shipping service is running'</span>);
};

<span class="hljs-comment">// Handle graceful shutdown</span>
<span class="hljs-keyword">const</span> shutdown = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.disconnect();
    <span class="hljs-keyword">await</span> producer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Shipping service disconnected from Kafka'</span>);
    process.exit(<span class="hljs-number">0</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error during shutdown: <span class="hljs-subst">${error.message}</span>`</span>);
    process.exit(<span class="hljs-number">1</span>);
  }
};

process.on(<span class="hljs-string">'SIGINT'</span>, shutdown);
process.on(<span class="hljs-string">'SIGTERM'</span>, shutdown);

<span class="hljs-comment">// Start the service</span>
start().catch(<span class="hljs-built_in">console</span>.error);
</code></pre>
<h3 id="heading-4-notification-service">4. Notification Service</h3>
<p>The Notification Service sends notifications about order status.</p>
<h4 id="heading-packagejson-3">package.json</h4>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"notification-service"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Service for sending notifications"</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"module"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node index.js"</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"kafkajs"</span>: <span class="hljs-string">"^2.2.4"</span>,
    <span class="hljs-attr">"dotenv"</span>: <span class="hljs-string">"^16.0.3"</span>
  }
}
</code></pre>
<h4 id="heading-indexjs-3">index.js</h4>
<pre><code class="lang-javascript"><span class="hljs-comment">// notification-service/index.js</span>
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;

<span class="hljs-comment">// Define Kafka configuration</span>
<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'notification-service'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});

<span class="hljs-comment">// Create consumer</span>
<span class="hljs-keyword">const</span> consumer = kafka.consumer({ <span class="hljs-attr">groupId</span>: <span class="hljs-string">'notification-service-group'</span> });

<span class="hljs-comment">// Define topics to listen to</span>
<span class="hljs-keyword">const</span> TOPICS = [<span class="hljs-string">'new-orders'</span>, <span class="hljs-string">'payments'</span>, <span class="hljs-string">'shipping'</span>];

<span class="hljs-comment">// Connect to Kafka</span>
<span class="hljs-keyword">const</span> connectToKafka = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Notification service connected to Kafka'</span>);

    <span class="hljs-comment">// Subscribe to all relevant topics</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> topic <span class="hljs-keyword">of</span> TOPICS) {
      <span class="hljs-keyword">await</span> consumer.subscribe({ topic, <span class="hljs-attr">fromBeginning</span>: <span class="hljs-literal">true</span> });
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Subscribed to <span class="hljs-subst">${topic}</span> topic`</span>);
    }

    <span class="hljs-comment">// Start consuming messages</span>
    <span class="hljs-keyword">await</span> consumer.run({
      <span class="hljs-attr">eachMessage</span>: <span class="hljs-keyword">async</span> ({ topic, partition, message }) =&gt; {
        <span class="hljs-keyword">await</span> processMessage(topic, message);
      },
    });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to connect to Kafka:'</span>, error);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-comment">// Process a message</span>
<span class="hljs-keyword">const</span> processMessage = <span class="hljs-keyword">async</span> (topic, message) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Parse the message</span>
    <span class="hljs-keyword">const</span> data = <span class="hljs-built_in">JSON</span>.parse(message.value.toString());
    <span class="hljs-keyword">const</span> eventType = message.headers[<span class="hljs-string">'event-type'</span>]?.toString();

    <span class="hljs-comment">// Determine notification type based on topic and event type</span>
    <span class="hljs-keyword">let</span> notificationType;
    <span class="hljs-keyword">let</span> notificationMessage;

    <span class="hljs-keyword">switch</span> (topic) {
      <span class="hljs-keyword">case</span> <span class="hljs-string">'new-orders'</span>:
        notificationType = <span class="hljs-string">'ORDER_CREATED'</span>;
        notificationMessage = <span class="hljs-string">`New order created with ID: <span class="hljs-subst">${data.id}</span>`</span>;
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">'payments'</span>:
        <span class="hljs-keyword">if</span> (data.status === <span class="hljs-string">'paid'</span>) {
          notificationType = <span class="hljs-string">'PAYMENT_SUCCESSFUL'</span>;
          notificationMessage = <span class="hljs-string">`Payment successful for order: <span class="hljs-subst">${data.orderId}</span>`</span>;
        } <span class="hljs-keyword">else</span> {
          notificationType = <span class="hljs-string">'PAYMENT_FAILED'</span>;
          notificationMessage = <span class="hljs-string">`Payment failed for order: <span class="hljs-subst">${data.orderId}</span>`</span>;
        }
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-string">'shipping'</span>:
        <span class="hljs-keyword">if</span> (data.status === <span class="hljs-string">'shipped'</span>) {
          notificationType = <span class="hljs-string">'ORDER_SHIPPED'</span>;
          notificationMessage = <span class="hljs-string">`Order shipped: <span class="hljs-subst">${data.orderId}</span>. Tracking number: <span class="hljs-subst">${data.trackingNumber}</span>`</span>;
        } <span class="hljs-keyword">else</span> {
          notificationType = <span class="hljs-string">'SHIPPING_FAILED'</span>;
          notificationMessage = <span class="hljs-string">`Shipping failed for order: <span class="hljs-subst">${data.orderId}</span>`</span>;
        }
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">default</span>:
        notificationType = <span class="hljs-string">'UNKNOWN'</span>;
        notificationMessage = <span class="hljs-string">`Unknown event for order: <span class="hljs-subst">${data.id || data.orderId}</span>`</span>;
    }

    <span class="hljs-comment">// Send notification (in a real system, this would send an email, SMS, push notification, etc.)</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'NOTIFICATION SENT:'</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Type: <span class="hljs-subst">${notificationType}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Message: <span class="hljs-subst">${notificationMessage}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Timestamp: <span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString()}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'-'</span>.repeat(<span class="hljs-number">50</span>));
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error processing notification: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};

<span class="hljs-comment">// Start the service</span>
<span class="hljs-keyword">const</span> start = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> connectToKafka();
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Notification service is running'</span>);
};

<span class="hljs-comment">// Handle graceful shutdown</span>
<span class="hljs-keyword">const</span> shutdown = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Notification service disconnected from Kafka'</span>);
    process.exit(<span class="hljs-number">0</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error during shutdown: <span class="hljs-subst">${error.message}</span>`</span>);
    process.exit(<span class="hljs-number">1</span>);
  }
};

process.on(<span class="hljs-string">'SIGINT'</span>, shutdown);
process.on(<span class="hljs-string">'SIGTERM'</span>, shutdown);

<span class="hljs-comment">// Start the service</span>
start().catch(<span class="hljs-built_in">console</span>.error);
</code></pre>
<h2 id="heading-running-the-example">Running the Example</h2>
<ol>
<li><p>First, make sure Kafka is running (from the setup in section 1)</p>
</li>
<li><p>Create the required topics:</p>
</li>
</ol>
<pre><code class="lang-bash">docker compose -f ../01-setup/docker-compose.yml <span class="hljs-built_in">exec</span> kafka kafka-topics --create --topic new-orders --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1
dockercompose -f ../01-setup/docker-compose.yml <span class="hljs-built_in">exec</span> kafka kafka-topics --create --topic payments --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1
docker-compose -f ../01-setup/docker-compose.yml <span class="hljs-built_in">exec</span> kafka kafka-topics --create --topic shipping --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1
</code></pre>
<ol start="3">
<li>Install dependencies for all services:</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> 05-real-world
npm run install-all
</code></pre>
<ol start="4">
<li>Start each service in a separate terminal:</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-comment"># Terminal 1</span>
npm run notification

<span class="hljs-comment"># Terminal 2</span>
npm run payment

<span class="hljs-comment"># Terminal 3</span>
npm run shipping

<span class="hljs-comment"># Terminal 4</span>
npm run order
</code></pre>
<ol start="5">
<li>Create a new order using curl or any API client:</li>
</ol>
<pre><code class="lang-bash">curl -X POST http://localhost:3000/orders \
  -H <span class="hljs-string">"Content-Type: application/json"</span> \
  -d <span class="hljs-string">'{
    "customerId": "customer-123",
    "items": [
      {"id": "item-1", "name": "Product 1", "quantity": 2, "price": 10.99},
      {"id": "item-2", "name": "Product 2", "quantity": 1, "price": 24.99}
    ],
    "totalAmount": 46.97
  }'</span>
</code></pre>
<ol start="6">
<li>Watch the flow of messages through the system:</li>
</ol>
<ul>
<li><p>The Order Service creates a new order and sends it to the <code>new-orders</code> topic</p>
</li>
<li><p>The Payment Service consumes from <code>new-orders</code>, processes the payment, and sends the result to the <code>payments</code> topic</p>
</li>
<li><p>The Shipping Service consumes from <code>payments</code>, processes shipping for paid orders, and sends the result to the <code>shipping</code> topic</p>
</li>
<li><p>The Notification Service consumes from all topics and sends notifications for each event</p>
</li>
</ul>
<h2 id="heading-understanding-the-architecture">Understanding the Architecture</h2>
<p>This example demonstrates a common pattern in event-driven microservices:</p>
<ol>
<li><p><strong>Event Sourcing</strong>: Each service publishes events about what has happened</p>
</li>
<li><p><strong>Command-Query Responsibility Segregation (CQRS)</strong>: Services are separated by their responsibilities</p>
</li>
<li><p><strong>Choreography</strong>: Services react to events rather than being directly commanded</p>
</li>
</ol>
<p>The benefits of this architecture include:</p>
<ul>
<li><p><strong>Loose Coupling</strong>: Services don't need to know about each other directly</p>
</li>
<li><p><strong>Scalability</strong>: Each service can scale independently</p>
</li>
<li><p><strong>Resilience</strong>: If one service fails, others can continue working</p>
</li>
<li><p><strong>Auditability</strong>: All events are recorded in Kafka, providing a complete history</p>
</li>
</ul>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Congratulations! You've now learned the basics of Kafka and seen how it can be used in a real-world scenario. Here are some ideas for further exploration:</p>
<ol>
<li><p><strong>Add Error Handling</strong>: Implement retry logic and dead-letter queues</p>
</li>
<li><p><strong>Add Monitoring</strong>: Use Kafka's metrics to monitor performance</p>
</li>
<li><p><strong>Implement Exactly-Once Semantics</strong>: Use transactions to ensure messages are processed exactly once</p>
</li>
<li><p><strong>Explore Kafka Streams</strong>: For more complex stream processing</p>
</li>
<li><p><strong>Implement Schema Registry</strong>: To manage and evolve message schemas</p>
</li>
</ol>
<p>Happy Kafka-ing!</p>
]]></content:encoded></item><item><title><![CDATA[Learning Kafka - Kafka Consumers]]></title><description><![CDATA[Now that we've created a producer that sends messages to Kafka, let's create a consumer that reads those messages. A consumer is an application that subscribes to Kafka topics and processes the messages.
Setting Up the Project
First, let's set up our...]]></description><link>https://blog.yuvraj.tech/learning-kafka-kafka-consumers</link><guid isPermaLink="true">https://blog.yuvraj.tech/learning-kafka-kafka-consumers</guid><category><![CDATA[kafka]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 14 Mar 2025 16:03:16 GMT</pubDate><content:encoded><![CDATA[<p>Now that we've created a producer that sends messages to Kafka, let's create a consumer that reads those messages. A consumer is an application that subscribes to Kafka topics and processes the messages.</p>
<h2 id="heading-setting-up-the-project">Setting Up the Project</h2>
<p>First, let's set up our Node.js project:</p>
<ol>
<li>Create a <code>package.json</code> file in the <code>04-consumer</code> directory:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"kafka-consumer-example"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"A simple Kafka consumer example"</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"consumer.js"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"module"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node consumer.js"</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"kafkajs"</span>: <span class="hljs-string">"^2.2.4"</span>,
    <span class="hljs-attr">"dotenv"</span>: <span class="hljs-string">"^16.0.3"</span>
  }
}
</code></pre>
<ol start="2">
<li>Install the dependencies:</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> 04-consumer
npm install
</code></pre>
<h2 id="heading-creating-the-consumer">Creating the Consumer</h2>
<p>Now, let's create our consumer. Create a file named <code>consumer.js</code> in the <code>04-consumer</code> directory:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// consumer.js</span>
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;

<span class="hljs-comment">// Define Kafka configuration</span>
<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'my-consumer'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});

<span class="hljs-comment">// Define the topic to consume messages from</span>
<span class="hljs-keyword">const</span> TOPIC_NAME = <span class="hljs-string">'first-topic'</span>;
<span class="hljs-comment">// Define the consumer group ID</span>
<span class="hljs-keyword">const</span> GROUP_ID = <span class="hljs-string">'my-group'</span>;

<span class="hljs-comment">// Create a consumer instance</span>
<span class="hljs-keyword">const</span> consumer = kafka.consumer({ <span class="hljs-attr">groupId</span>: GROUP_ID });

<span class="hljs-comment">/**
 * Process a message from Kafka
 * @param {Object} message - The message to process
 */</span>
<span class="hljs-keyword">const</span> processMessage = <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Parse the message value</span>
    <span class="hljs-keyword">const</span> value = <span class="hljs-built_in">JSON</span>.parse(message.value.toString());

    <span class="hljs-comment">// Print message details</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Received message:'</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Partition: <span class="hljs-subst">${message.partition}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Offset: <span class="hljs-subst">${message.offset}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Key: <span class="hljs-subst">${message.key || <span class="hljs-string">'null'</span>}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Value: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(value)}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'-'</span>.repeat(<span class="hljs-number">50</span>));

    <span class="hljs-comment">// Here you would typically do something with the message</span>
    <span class="hljs-comment">// For example, save it to a database, trigger an action, etc.</span>
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error processing message: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};

<span class="hljs-comment">/**
 * Main function to run the consumer
 */</span>
<span class="hljs-keyword">const</span> main = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Connect to the Kafka broker</span>
    <span class="hljs-keyword">await</span> consumer.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Consumer connected to Kafka'</span>);

    <span class="hljs-comment">// Subscribe to the topic</span>
    <span class="hljs-keyword">await</span> consumer.subscribe({ 
      <span class="hljs-attr">topic</span>: TOPIC_NAME, 
      <span class="hljs-attr">fromBeginning</span>: <span class="hljs-literal">true</span>  <span class="hljs-comment">// Read from the beginning of the topic</span>
    });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Subscribed to topic: <span class="hljs-subst">${TOPIC_NAME}</span>`</span>);

    <span class="hljs-comment">// Start consuming messages</span>
    <span class="hljs-keyword">await</span> consumer.run({
      <span class="hljs-attr">eachMessage</span>: <span class="hljs-keyword">async</span> ({ topic, partition, message }) =&gt; {
        processMessage(message);
      },
    });

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Consumer started. Waiting for messages...'</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Press Ctrl+C to exit'</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Consumer error: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};

<span class="hljs-comment">// Handle graceful shutdown</span>
<span class="hljs-keyword">const</span> shutdown = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Consumer disconnected'</span>);
    process.exit(<span class="hljs-number">0</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error during shutdown: <span class="hljs-subst">${error.message}</span>`</span>);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-comment">// Listen for termination signals</span>
process.on(<span class="hljs-string">'SIGINT'</span>, shutdown);
process.on(<span class="hljs-string">'SIGTERM'</span>, shutdown);

<span class="hljs-comment">// Run the consumer</span>
main().catch(<span class="hljs-built_in">console</span>.error);
</code></pre>
<h2 id="heading-understanding-the-code">Understanding the Code</h2>
<p>Let's break down what this code does:</p>
<h3 id="heading-1-importing-the-kafka-client">1. Importing the Kafka Client</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;
</code></pre>
<p>Just like with the producer, we import the Kafka client from the kafkajs package.</p>
<h3 id="heading-2-configuring-kafka">2. Configuring Kafka</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'my-consumer'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});
</code></pre>
<p>We create a Kafka client with:</p>
<ul>
<li><p><code>clientId</code>: A name for our consumer application</p>
</li>
<li><p><code>brokers</code>: The addresses of the Kafka servers to connect to</p>
</li>
</ul>
<h3 id="heading-3-creating-a-consumer">3. Creating a Consumer</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> consumer = kafka.consumer({ <span class="hljs-attr">groupId</span>: GROUP_ID });
</code></pre>
<p>This creates a consumer instance with a specific consumer group ID. The group ID is important because:</p>
<ul>
<li><p>It identifies which consumer group this consumer belongs to</p>
</li>
<li><p>Kafka uses it to manage which consumers read from which partitions</p>
</li>
<li><p>If multiple consumers have the same group ID, they'll share the workload</p>
</li>
</ul>
<h3 id="heading-4-subscribing-to-a-topic">4. Subscribing to a Topic</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> consumer.subscribe({ 
  <span class="hljs-attr">topic</span>: TOPIC_NAME, 
  <span class="hljs-attr">fromBeginning</span>: <span class="hljs-literal">true</span>  <span class="hljs-comment">// Read from the beginning of the topic</span>
});
</code></pre>
<p>This subscribes our consumer to the topic. The <code>fromBeginning: true</code> option means we want to read all messages in the topic, even those that were sent before our consumer started.</p>
<h3 id="heading-5-processing-messages">5. Processing Messages</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> consumer.run({
  <span class="hljs-attr">eachMessage</span>: <span class="hljs-keyword">async</span> ({ topic, partition, message }) =&gt; {
    processMessage(message);
  },
});
</code></pre>
<p>This starts the consumer running and defines what happens when a message is received. For each message, we call our <code>processMessage</code> function.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> processMessage = <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Parse the message value</span>
    <span class="hljs-keyword">const</span> value = <span class="hljs-built_in">JSON</span>.parse(message.value.toString());

    <span class="hljs-comment">// Print message details</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Received message:'</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Partition: <span class="hljs-subst">${message.partition}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Offset: <span class="hljs-subst">${message.offset}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Key: <span class="hljs-subst">${message.key || <span class="hljs-string">'null'</span>}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`  Value: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(value)}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'-'</span>.repeat(<span class="hljs-number">50</span>));

    <span class="hljs-comment">// Here you would typically do something with the message</span>
    <span class="hljs-comment">// For example, save it to a database, trigger an action, etc.</span>
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error processing message: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};
</code></pre>
<p>This function:</p>
<ol>
<li><p>Parses the message value (converting it from a JSON string back to a JavaScript object)</p>
</li>
<li><p>Logs details about the message</p>
</li>
<li><p>Would typically do something useful with the message (in a real application)</p>
</li>
</ol>
<h3 id="heading-6-graceful-shutdown">6. Graceful Shutdown</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> shutdown = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Consumer disconnected'</span>);
    process.exit(<span class="hljs-number">0</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error during shutdown: <span class="hljs-subst">${error.message}</span>`</span>);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-comment">// Listen for termination signals</span>
process.on(<span class="hljs-string">'SIGINT'</span>, shutdown);
process.on(<span class="hljs-string">'SIGTERM'</span>, shutdown);
</code></pre>
<p>This code ensures that when the application is stopped (e.g., by pressing Ctrl+C), it properly disconnects from Kafka before exiting.</p>
<h2 id="heading-running-the-consumer">Running the Consumer</h2>
<p>Make sure Kafka is running (from the setup in section 1), then run:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> 04-consumer
npm start
</code></pre>
<p>You should see output like:</p>
<pre><code class="lang-plaintext">Consumer connected to Kafka
Subscribed to topic: first-topic
Consumer started. Waiting for messages...
Press Ctrl+C to exit
</code></pre>
<p>If you've already run the producer from the previous section, you should see the messages it sent:</p>
<pre><code class="lang-plaintext">Received message:
  Partition: 0
  Offset: 0
  Key: null
  Value: {"id":1,"text":"This is message #1","source":"nodejs-producer","timestamp":"2023-05-10T12:34:56.789Z"}
--------------------------------------------------
Received message:
  Partition: 0
  Offset: 1
  Key: null
  Value: {"id":2,"text":"This is message #2","source":"nodejs-producer","timestamp":"2023-05-10T12:34:57.789Z"}
--------------------------------------------------
...
</code></pre>
<p>If you run the producer again while the consumer is running, you'll see new messages appear in real-time.</p>
<h2 id="heading-advanced-consumer-options">Advanced Consumer Options</h2>
<p>Our example is simple, but KafkaJS consumers have many options for advanced use cases:</p>
<h3 id="heading-controlling-offsets">Controlling Offsets</h3>
<p>You can manually control which messages you've processed:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> consumer.run({
  <span class="hljs-attr">eachMessage</span>: <span class="hljs-keyword">async</span> ({ topic, partition, message }) =&gt; {
    processMessage(message);

    <span class="hljs-comment">// Manually commit the offset</span>
    <span class="hljs-keyword">await</span> consumer.commitOffsets([
      { topic, partition, <span class="hljs-attr">offset</span>: (<span class="hljs-built_in">parseInt</span>(message.offset) + <span class="hljs-number">1</span>).toString() }
    ]);
  },
});
</code></pre>
<p>This is useful if you want to ensure a message is fully processed before marking it as consumed.</p>
<h3 id="heading-batch-processing">Batch Processing</h3>
<p>Instead of processing one message at a time, you can process messages in batches:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> consumer.run({
  <span class="hljs-attr">eachBatch</span>: <span class="hljs-keyword">async</span> ({ batch, resolveOffset, heartbeat, isRunning, isStale }) =&gt; {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> message <span class="hljs-keyword">of</span> batch.messages) {
      <span class="hljs-keyword">if</span> (!isRunning() || isStale()) <span class="hljs-keyword">break</span>;

      processMessage(message);
      resolveOffset(message.offset);
      <span class="hljs-keyword">await</span> heartbeat();
    }
  },
});
</code></pre>
<p>This can be more efficient for high-volume processing.</p>
<h3 id="heading-multiple-topics">Multiple Topics</h3>
<p>You can subscribe to multiple topics:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> consumer.subscribe({ <span class="hljs-attr">topic</span>: <span class="hljs-string">'topic1'</span> });
<span class="hljs-keyword">await</span> consumer.subscribe({ <span class="hljs-attr">topic</span>: <span class="hljs-string">'topic2'</span> });
<span class="hljs-keyword">await</span> consumer.subscribe({ <span class="hljs-attr">topic</span>: <span class="hljs-string">'topic3'</span> });
</code></pre>
<h3 id="heading-consumer-groups-and-rebalancing">Consumer Groups and Rebalancing</h3>
<p>When you have multiple consumers in the same group, Kafka will distribute partitions among them. If a consumer joins or leaves the group, Kafka will "rebalance" the partitions.</p>
<p>You can listen for these events:</p>
<pre><code class="lang-javascript">consumer.on(consumer.events.GROUP_JOIN, <span class="hljs-function">(<span class="hljs-params">{ payload }</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Consumer joined group: <span class="hljs-subst">${payload.groupId}</span>`</span>);
});

consumer.on(consumer.events.REBALANCE, <span class="hljs-function">(<span class="hljs-params">{ payload }</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Rebalancing: <span class="hljs-subst">${payload.type}</span>`</span>);
});
</code></pre>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that we've created both a producer and a consumer, let's build a more realistic example that shows how Kafka can be used in a real-world scenario.</p>
<p><a target="_blank" href="../05-real-world/README.md">Next: Real-world Example</a></p>
]]></content:encoded></item><item><title><![CDATA[Learning Kafka - Kafka Producers]]></title><description><![CDATA[Now that we understand the basic concepts of Kafka, let's create our first producer. A producer is an application that sends messages to Kafka topics.
Setting Up the Project
First, let's set up our Node.js project:

Create a package.json file in the ...]]></description><link>https://blog.yuvraj.tech/kafka-producers</link><guid isPermaLink="true">https://blog.yuvraj.tech/kafka-producers</guid><category><![CDATA[kafka]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 14 Mar 2025 16:02:28 GMT</pubDate><content:encoded><![CDATA[<p>Now that we understand the basic concepts of Kafka, let's create our first producer. A producer is an application that sends messages to Kafka topics.</p>
<h2 id="heading-setting-up-the-project">Setting Up the Project</h2>
<p>First, let's set up our Node.js project:</p>
<ol>
<li>Create a <code>package.json</code> file in the <code>03-producer</code> directory:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"kafka-producer-example"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"A simple Kafka producer example"</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"producer.js"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"module"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node producer.js"</span>
  },
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"kafkajs"</span>: <span class="hljs-string">"^2.2.4"</span>,
    <span class="hljs-attr">"dotenv"</span>: <span class="hljs-string">"^16.0.3"</span>
  }
}
</code></pre>
<p>Notice the <code>"type": "module"</code> line - this enables ES6 module syntax.</p>
<ol start="2">
<li>Install the dependencies:</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> 03-producer
npm install
</code></pre>
<h2 id="heading-creating-the-producer">Creating the Producer</h2>
<p>Now, let's create our producer. Create a file named <code>producer.js</code> in the <code>03-producer</code> directory:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// producer.js</span>
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;

<span class="hljs-comment">// Define Kafka configuration</span>
<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'my-producer'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});

<span class="hljs-comment">// Create a producer instance</span>
<span class="hljs-keyword">const</span> producer = kafka.producer();

<span class="hljs-comment">// Define the topic to produce messages to</span>
<span class="hljs-keyword">const</span> TOPIC_NAME = <span class="hljs-string">'first-topic'</span>;

<span class="hljs-comment">/**
 * Send a message to the Kafka topic
 * @param {Object} message - The message to send
 */</span>
<span class="hljs-keyword">const</span> sendMessage = <span class="hljs-keyword">async</span> (message) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Add a timestamp to the message</span>
    message.timestamp = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString();

    <span class="hljs-comment">// Send the message to the topic</span>
    <span class="hljs-keyword">await</span> producer.send({
      <span class="hljs-attr">topic</span>: TOPIC_NAME,
      <span class="hljs-attr">messages</span>: [
        { <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(message) }
      ],
    });

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message sent: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(message)}</span>`</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error sending message: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};

<span class="hljs-comment">/**
 * Main function to run the producer
 */</span>
<span class="hljs-keyword">const</span> main = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Connect to the Kafka broker</span>
    <span class="hljs-keyword">await</span> producer.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Producer connected to Kafka'</span>);

    <span class="hljs-comment">// Send 5 messages</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">5</span>; i++) {
      <span class="hljs-keyword">const</span> message = {
        <span class="hljs-attr">id</span>: i,
        <span class="hljs-attr">text</span>: <span class="hljs-string">`This is message #<span class="hljs-subst">${i}</span>`</span>,
        <span class="hljs-attr">source</span>: <span class="hljs-string">'nodejs-producer'</span>
      };

      <span class="hljs-keyword">await</span> sendMessage(message);

      <span class="hljs-comment">// Wait for 1 second between messages</span>
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Producer error: <span class="hljs-subst">${error.message}</span>`</span>);
  } <span class="hljs-keyword">finally</span> {
    <span class="hljs-comment">// Disconnect the producer</span>
    <span class="hljs-keyword">await</span> producer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Producer disconnected'</span>);
  }
};

<span class="hljs-comment">// Run the producer</span>
main().catch(<span class="hljs-built_in">console</span>.error);
</code></pre>
<h2 id="heading-understanding-the-code">Understanding the Code</h2>
<p>Let's break down what this code does:</p>
<h3 id="heading-1-importing-the-kafka-client">1. Importing the Kafka Client</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'kafkajs'</span>;
</code></pre>
<p>We're using ES6 import syntax to import the Kafka client from the kafkajs package.</p>
<h3 id="heading-2-configuring-kafka">2. Configuring Kafka</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">'my-producer'</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">'localhost:9092'</span>]
});
</code></pre>
<p>We create a Kafka client with:</p>
<ul>
<li><p><code>clientId</code>: A name for our application</p>
</li>
<li><p><code>brokers</code>: The addresses of the Kafka servers to connect to</p>
</li>
</ul>
<h3 id="heading-3-creating-a-producer">3. Creating a Producer</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> producer = kafka.producer();
</code></pre>
<p>This creates a producer instance that we'll use to send messages.</p>
<h3 id="heading-4-sending-messages">4. Sending Messages</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> sendMessage = <span class="hljs-keyword">async</span> (message) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Add a timestamp to the message</span>
    message.timestamp = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString();

    <span class="hljs-comment">// Send the message to the topic</span>
    <span class="hljs-keyword">await</span> producer.send({
      <span class="hljs-attr">topic</span>: TOPIC_NAME,
      <span class="hljs-attr">messages</span>: [
        { <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(message) }
      ],
    });

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message sent: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(message)}</span>`</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Error sending message: <span class="hljs-subst">${error.message}</span>`</span>);
  }
};
</code></pre>
<p>This function:</p>
<ol>
<li><p>Adds a timestamp to the message</p>
</li>
<li><p>Sends the message to our topic</p>
</li>
<li><p>Logs the result or any errors</p>
</li>
</ol>
<p>Note that we're converting our message to a JSON string using <code>JSON.stringify()</code>. Kafka messages are sent as binary data, so we need to serialize our JavaScript objects.</p>
<h3 id="heading-5-main-function">5. Main Function</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> main = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Connect to the Kafka broker</span>
    <span class="hljs-keyword">await</span> producer.connect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Producer connected to Kafka'</span>);

    <span class="hljs-comment">// Send 5 messages</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">5</span>; i++) {
      <span class="hljs-keyword">const</span> message = {
        <span class="hljs-attr">id</span>: i,
        <span class="hljs-attr">text</span>: <span class="hljs-string">`This is message #<span class="hljs-subst">${i}</span>`</span>,
        <span class="hljs-attr">source</span>: <span class="hljs-string">'nodejs-producer'</span>
      };

      <span class="hljs-keyword">await</span> sendMessage(message);

      <span class="hljs-comment">// Wait for 1 second between messages</span>
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">`Producer error: <span class="hljs-subst">${error.message}</span>`</span>);
  } <span class="hljs-keyword">finally</span> {
    <span class="hljs-comment">// Disconnect the producer</span>
    <span class="hljs-keyword">await</span> producer.disconnect();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Producer disconnected'</span>);
  }
};
</code></pre>
<p>This function:</p>
<ol>
<li><p>Connects to Kafka</p>
</li>
<li><p>Sends 5 messages, waiting 1 second between each</p>
</li>
<li><p>Disconnects from Kafka when done</p>
</li>
</ol>
<h2 id="heading-running-the-producer">Running the Producer</h2>
<p>Make sure Kafka is running (from the setup in section 1), then run:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> 03-producer
npm start
</code></pre>
<p>You should see output like:</p>
<pre><code class="lang-plaintext">Producer connected to Kafka
Message sent: {"id":1,"text":"This is message #1","source":"nodejs-producer","timestamp":"2023-05-10T12:34:56.789Z"}
Message sent: {"id":2,"text":"This is message #2","source":"nodejs-producer","timestamp":"2023-05-10T12:34:57.789Z"}
Message sent: {"id":3,"text":"This is message #3","source":"nodejs-producer","timestamp":"2023-05-10T12:34:58.789Z"}
Message sent: {"id":4,"text":"This is message #4","source":"nodejs-producer","timestamp":"2023-05-10T12:34:59.789Z"}
Message sent: {"id":5,"text":"This is message #5","source":"nodejs-producer","timestamp":"2023-05-10T12:35:00.789Z"}
Producer disconnected
</code></pre>
<h2 id="heading-advanced-producer-options">Advanced Producer Options</h2>
<p>Our example is simple, but KafkaJS producers have many options for advanced use cases:</p>
<h3 id="heading-message-keys">Message Keys</h3>
<p>You can add a key to your messages:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> producer.send({
  <span class="hljs-attr">topic</span>: TOPIC_NAME,
  <span class="hljs-attr">messages</span>: [
    { 
      <span class="hljs-attr">key</span>: <span class="hljs-string">'user-123'</span>,  <span class="hljs-comment">// Add a key</span>
      <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(message) 
    }
  ],
});
</code></pre>
<p>Messages with the same key always go to the same partition. This is useful for ensuring order for related messages.</p>
<h3 id="heading-batching-messages">Batching Messages</h3>
<p>You can send multiple messages at once:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> producer.send({
  <span class="hljs-attr">topic</span>: TOPIC_NAME,
  <span class="hljs-attr">messages</span>: [
    { <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(message1) },
    { <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(message2) },
    { <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify(message3) }
  ],
});
</code></pre>
<h3 id="heading-compression">Compression</h3>
<p>You can compress messages to save bandwidth:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> producer = kafka.producer({
  <span class="hljs-attr">allowAutoTopicCreation</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">transactionTimeout</span>: <span class="hljs-number">30000</span>,
  <span class="hljs-attr">compression</span>: <span class="hljs-string">'gzip'</span>  <span class="hljs-comment">// Use gzip compression</span>
});
</code></pre>
<h3 id="heading-acknowledgment-levels">Acknowledgment Levels</h3>
<p>You can control when the producer considers a message "sent":</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> producer = kafka.producer({
  <span class="hljs-attr">acks</span>: <span class="hljs-number">1</span>  <span class="hljs-comment">// 0 = no ack, 1 = leader ack, -1 = all acks</span>
});
</code></pre>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that we've created a producer, let's create a consumer to read the messages we've sent.</p>
<p><a target="_blank" href="../04-consumer/README.md">Next: Your First Consumer</a></p>
]]></content:encoded></item><item><title><![CDATA[Learning Kafka - Kafka Fundamentals]]></title><description><![CDATA[Kafka Basic Concepts
Now that we have Kafka running, let's understand the key concepts that make Kafka work. I'll explain these in simple terms without jargon.
The Big Picture
Kafka is a system that lets different parts of your application talk to ea...]]></description><link>https://blog.yuvraj.tech/learning-kafka-kafka-fundamentals</link><guid isPermaLink="true">https://blog.yuvraj.tech/learning-kafka-kafka-fundamentals</guid><category><![CDATA[kafka]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 14 Mar 2025 16:00:18 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-kafka-basic-concepts">Kafka Basic Concepts</h1>
<p>Now that we have Kafka running, let's understand the key concepts that make Kafka work. I'll explain these in simple terms without jargon.</p>
<h2 id="heading-the-big-picture">The Big Picture</h2>
<p>Kafka is a system that lets different parts of your application talk to each other by passing messages. It's designed to handle huge amounts of data reliably.</p>
<p>Here's how it works at a high level:</p>
<ol>
<li><p><strong>Producers</strong> send messages to Kafka</p>
</li>
<li><p>Kafka stores these messages in <strong>Topics</strong></p>
</li>
<li><p><strong>Consumers</strong> read messages from Topics</p>
</li>
</ol>
<p>Let's dive into each concept:</p>
<h2 id="heading-topics-the-message-categories">Topics: The Message Categories</h2>
<p>A <strong>Topic</strong> is like a category or channel for your messages. Think of it like:</p>
<ul>
<li><p>A folder where related messages are stored</p>
</li>
<li><p>A TV channel that broadcasts specific content</p>
</li>
<li><p>A mailbox for a specific type of mail</p>
</li>
</ul>
<p>For example, you might have topics like:</p>
<ul>
<li><p><code>user-signups</code> for new user registrations</p>
</li>
<li><p><code>order-placed</code> for new orders</p>
</li>
<li><p><code>payment-processed</code> for payment confirmations</p>
</li>
</ul>
<p>Topics have these important characteristics:</p>
<ul>
<li><p>They have a name (like "first-topic")</p>
</li>
<li><p>They can be split into multiple <strong>Partitions</strong> (more on this below)</p>
</li>
<li><p>They store messages in an ordered sequence</p>
</li>
</ul>
<h2 id="heading-partitions-splitting-up-topics-for-scale">Partitions: Splitting Up Topics for Scale</h2>
<p>A <strong>Partition</strong> is a way to divide a topic into multiple parts. This is important because:</p>
<ol>
<li><p>It allows Kafka to store more data than can fit on a single server</p>
</li>
<li><p>It enables parallel processing of messages</p>
</li>
</ol>
<p>Think of partitions like:</p>
<ul>
<li><p>Multiple checkout lines at a grocery store</p>
</li>
<li><p>Multiple lanes on a highway</p>
</li>
<li><p>Multiple workers in an assembly line</p>
</li>
</ul>
<p>Each partition:</p>
<ul>
<li><p>Is an ordered sequence of messages</p>
</li>
<li><p>Is stored on a single server (called a broker)</p>
</li>
<li><p>Can be replicated to other servers for fault tolerance</p>
</li>
<li><p>Has messages identified by their position (called an offset)</p>
</li>
</ul>
<h2 id="heading-messages-the-data-being-sent">Messages: The Data Being Sent</h2>
<p>A <strong>Message</strong> is the basic unit of data in Kafka. It's what producers send and consumers read.</p>
<p>A message consists of:</p>
<ul>
<li><p>A <strong>key</strong> (optional): Helps determine which partition the message goes to</p>
</li>
<li><p>A <strong>value</strong>: The actual data being sent (can be text, JSON, binary, etc.)</p>
</li>
<li><p>A <strong>timestamp</strong>: When the message was created</p>
</li>
<li><p><strong>Headers</strong> (optional): Additional metadata</p>
</li>
</ul>
<p>Messages are immutable - once they're written to Kafka, they don't change.</p>
<h2 id="heading-producers-sending-messages">Producers: Sending Messages</h2>
<p>A <strong>Producer</strong> is an application that sends messages to Kafka topics.</p>
<p>Producers:</p>
<ul>
<li><p>Connect to Kafka brokers</p>
</li>
<li><p>Serialize messages (convert them to a format that can be transmitted)</p>
</li>
<li><p>Can choose which partition to send messages to (or let Kafka decide)</p>
</li>
<li><p>Can wait for acknowledgment that messages were received</p>
</li>
</ul>
<h2 id="heading-consumers-reading-messages">Consumers: Reading Messages</h2>
<p>A <strong>Consumer</strong> is an application that reads messages from Kafka topics.</p>
<p>Consumers:</p>
<ul>
<li><p>Connect to Kafka brokers</p>
</li>
<li><p>Subscribe to one or more topics</p>
</li>
<li><p>Deserialize messages (convert them back from transmission format)</p>
</li>
<li><p>Keep track of which messages they've read using offsets</p>
</li>
</ul>
<h2 id="heading-consumer-groups-scaling-consumption">Consumer Groups: Scaling Consumption</h2>
<p>A <strong>Consumer Group</strong> is a set of consumers that work together to process messages from topics.</p>
<p>Consumer groups allow you to:</p>
<ul>
<li><p>Process messages in parallel (each consumer handles a subset of partitions)</p>
</li>
<li><p>Scale processing by adding more consumers</p>
</li>
<li><p>Provide fault tolerance (if one consumer fails, others take over)</p>
</li>
</ul>
<p>The key rule: <strong>Each partition is consumed by only one consumer in a group</strong></p>
<p>This means:</p>
<ul>
<li><p>If you have more consumers than partitions, some consumers will be idle</p>
</li>
<li><p>If you have fewer consumers than partitions, some consumers will handle multiple partitions</p>
</li>
</ul>
<h2 id="heading-brokers-the-kafka-servers">Brokers: The Kafka Servers</h2>
<p>A <strong>Broker</strong> is a Kafka server that:</p>
<ul>
<li><p>Stores partitions</p>
</li>
<li><p>Handles producer and consumer requests</p>
</li>
<li><p>Manages replication of partitions</p>
</li>
</ul>
<p>A Kafka cluster consists of multiple brokers working together.</p>
<h2 id="heading-zookeeper-the-coordinator">ZooKeeper: The Coordinator</h2>
<p><strong>ZooKeeper</strong> is a service that helps coordinate the Kafka cluster:</p>
<ul>
<li><p>Keeps track of which brokers are alive</p>
</li>
<li><p>Helps elect a controller (a broker that manages the cluster)</p>
</li>
<li><p>Stores configuration information</p>
</li>
</ul>
<h2 id="heading-putting-it-all-together">Putting It All Together</h2>
<p>Here's how all these concepts work together:</p>
<ol>
<li><p>Producers send messages to topics</p>
</li>
<li><p>Topics are divided into partitions for scalability</p>
</li>
<li><p>Partitions are stored on brokers (Kafka servers)</p>
</li>
<li><p>Consumers read messages from topics</p>
</li>
<li><p>Consumer groups allow parallel processing</p>
</li>
<li><p>ZooKeeper coordinates the whole system</p>
</li>
</ol>
<h2 id="heading-visual-representation">Visual Representation</h2>
<pre><code class="lang-plaintext">┌─────────────┐     ┌───────────────────────────────────┐     ┌─────────────┐
│             │     │             KAFKA                 │     │             │
│  Producers  │────▶│  ┌─────────┐  ┌─────────┐         │     │  Consumers  │
│             │     │  │ Topic A │  │ Topic B │         │     │             │
└─────────────┘     │  │ Part 1  │  │ Part 1  │         │     └─────────────┘
                    │  │ Part 2  │  │ Part 2  │         │           ▲
                    │  │ Part 3  │  │ Part 3  │         │           │
                    │  └─────────┘  └─────────┘         │           │
                    │                                   │           │
                    └───────────────────────────────────┘           │
                                    │                               │
                                    │                               │
                                    ▼                               │
                    ┌───────────────────────────────────┐           │
                    │           ZooKeeper               │           │
                    │  (Coordinates Kafka Brokers)      │           │
                    └───────────────────────────────────┘           │
                                                                    │
                    ┌───────────────────────────────────┐           │
                    │         Consumer Group            │───────────┘
                    │  (Distributes work among          │
                    │   multiple consumers)             │
                    └───────────────────────────────────┘
</code></pre>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that you understand the basic concepts, let's create our first Kafka producer in the next section.</p>
<p><a target="_blank" href="../03-producer/README.md">Next: Your First Producer</a></p>
]]></content:encoded></item><item><title><![CDATA[Learning Kafka: Set Up]]></title><description><![CDATA[Setting Up Kafka
Before we can start using Kafka, we need to set it up on your computer. The easiest way to do this is using Docker, which lets us run Kafka without installing it directly on your system.
What is Docker?
Docker is like a lightweight v...]]></description><link>https://blog.yuvraj.tech/kafka-setup</link><guid isPermaLink="true">https://blog.yuvraj.tech/kafka-setup</guid><category><![CDATA[kafka]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 14 Mar 2025 15:57:23 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-setting-up-kafka">Setting Up Kafka</h1>
<p>Before we can start using Kafka, we need to set it up on your computer. The easiest way to do this is using Docker, which lets us run Kafka without installing it directly on your system.</p>
<h2 id="heading-what-is-docker">What is Docker?</h2>
<p>Docker is like a lightweight virtual machine that runs apps in containers. Think of containers as isolated boxes that have everything an app needs to run.</p>
<h2 id="heading-step-1-install-docker">Step 1: Install Docker</h2>
<p>If you don't have Docker installed:</p>
<ul>
<li><p>For Mac: Download and install <a target="_blank" href="https://www.docker.com/products/docker-desktop">Docker Desktop for Mac</a></p>
</li>
<li><p>For Windows: Download and install <a target="_blank" href="https://www.docker.com/products/docker-desktop">Docker Desktop for Windows</a></p>
</li>
<li><p>For Linux: Follow the <a target="_blank" href="https://docs.docker.com/engine/install/">installation instructions</a> for your distribution</p>
</li>
</ul>
<h2 id="heading-step-2-create-a-docker-compose-file">Step 2: Create a Docker Compose File</h2>
<p>We'll use Docker Compose to set up Kafka and its dependency, ZooKeeper. Docker Compose lets us define and run multiple containers together.</p>
<p>Create a file named <code>docker-compose.yml</code> in the <code>01-setup</code> directory with the following content:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-attr">zookeeper:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">confluentinc/cp-zookeeper:7.3.0</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">zookeeper</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">ZOOKEEPER_CLIENT_PORT:</span> <span class="hljs-number">2181</span>
      <span class="hljs-attr">ZOOKEEPER_TICK_TIME:</span> <span class="hljs-number">2000</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"2181:2181"</span>

  <span class="hljs-attr">kafka:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">confluentinc/cp-kafka:7.3.0</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">kafka</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">zookeeper</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"9092:9092"</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">KAFKA_BROKER_ID:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">KAFKA_ZOOKEEPER_CONNECT:</span> <span class="hljs-string">zookeeper:2181</span>
      <span class="hljs-attr">KAFKA_ADVERTISED_LISTENERS:</span> <span class="hljs-string">PLAINTEXT://localhost:9092</span>
      <span class="hljs-attr">KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">KAFKA_TRANSACTION_STATE_LOG_MIN_ISR:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR:</span> <span class="hljs-number">1</span>
</code></pre>
<h2 id="heading-whats-in-this-file">What's in this file?</h2>
<p>Let's break down what this file does:</p>
<ol>
<li><p><strong>ZooKeeper Container</strong>:</p>
<ul>
<li><p>ZooKeeper is a service that Kafka uses to keep track of which servers are up and running</p>
</li>
<li><p>It helps coordinate the Kafka servers (called brokers)</p>
</li>
<li><p>We're exposing port 2181, which is the default port for ZooKeeper</p>
</li>
</ul>
</li>
<li><p><strong>Kafka Container</strong>:</p>
<ul>
<li><p>This is the actual Kafka server</p>
</li>
<li><p>It depends on ZooKeeper, so Docker will start ZooKeeper first</p>
</li>
<li><p>We're exposing port 9092, which is the default port for Kafka</p>
</li>
<li><p>The environment variables configure Kafka:</p>
<ul>
<li><p><code>KAFKA_BROKER_ID</code>: A unique ID for this Kafka server</p>
</li>
<li><p><code>KAFKA_ZOOKEEPER_CONNECT</code>: Tells Kafka how to connect to ZooKeeper</p>
</li>
<li><p><code>KAFKA_ADVERTISED_LISTENERS</code>: The address that producers and consumers will use to connect to Kafka</p>
</li>
<li><p>The other settings are for a single-node setup (we're keeping it simple)</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="heading-step-3-start-kafka">Step 3: Start Kafka</h2>
<p>Now let's start Kafka using Docker Compose:</p>
<ol>
<li><p>Open a terminal</p>
</li>
<li><p>Navigate to the directory containing your <code>docker-compose.yml</code> file</p>
</li>
<li><p>Run the following command:</p>
</li>
</ol>
<pre><code class="lang-bash">docker compose up -d
</code></pre>
<p>The <code>-d</code> flag runs the containers in the background.</p>
<h2 id="heading-step-4-verify-kafka-is-running">Step 4: Verify Kafka is Running</h2>
<p>To check if Kafka is running:</p>
<pre><code class="lang-bash">docker compose ps
</code></pre>
<p>You should see both ZooKeeper and Kafka containers running.</p>
<h2 id="heading-step-5-create-a-kafka-topic">Step 5: Create a Kafka Topic</h2>
<p>A topic is like a category or feed name to which messages are published. Let's create our first topic:</p>
<pre><code class="lang-bash">docker compose <span class="hljs-built_in">exec</span> kafka kafka-topics --create --topic first-topic --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1
</code></pre>
<p>This creates a topic named "first-topic" with 1 partition and 1 replica.</p>
<h2 id="heading-whats-a-partition">What's a Partition?</h2>
<p>A partition is a way to split a topic into multiple parts. This allows Kafka to:</p>
<ul>
<li><p>Store more data than can fit on a single server</p>
</li>
<li><p>Process messages in parallel</p>
</li>
</ul>
<p>For now, we're keeping it simple with just 1 partition.</p>
<h2 id="heading-step-6-list-kafka-topics">Step 6: List Kafka Topics</h2>
<p>To see the topic we just created:</p>
<pre><code class="lang-bash">docker compose <span class="hljs-built_in">exec</span> kafka kafka-topics --list --bootstrap-server localhost:9092
</code></pre>
<p>You should see "first-topic" in the list.</p>
<h2 id="heading-step-7-install-nodejs-dependencies">Step 7: Install Node.js Dependencies</h2>
<p>We'll be using Node.js to interact with Kafka. Let's set up a package.json file:</p>
<pre><code class="lang-bash">npm init -y
npm install kafkajs dotenv
</code></pre>
<p>This installs:</p>
<ul>
<li><p><code>kafkajs</code>: A modern Kafka client for Node.js</p>
</li>
<li><p><code>dotenv</code>: For loading environment variables from a .env file</p>
</li>
</ul>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that we have Kafka running, let's learn about the basic concepts in the next section.</p>
<p><a target="_blank" href="../02-concepts/README.md">Next: Basic Concepts</a></p>
]]></content:encoded></item><item><title><![CDATA[Learning Kafka: A Step-by-Step Guide]]></title><description><![CDATA[What is Kafka?
Think of Kafka as a super-powered message system. It's like a central hub where different parts of your application can send messages to each other without needing to know about each other directly.
Imagine it like a post office:

Some...]]></description><link>https://blog.yuvraj.tech/learning-kafka-a-step-by-step-guide</link><guid isPermaLink="true">https://blog.yuvraj.tech/learning-kafka-a-step-by-step-guide</guid><category><![CDATA[kafka]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 14 Mar 2025 15:55:15 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-kafka">What is Kafka?</h2>
<p>Think of Kafka as a super-powered message system. It's like a central hub where different parts of your application can send messages to each other without needing to know about each other directly.</p>
<p>Imagine it like a post office:</p>
<ul>
<li><p>Some people (producers) drop off letters (messages)</p>
</li>
<li><p>The post office (Kafka) organizes these letters into different mailboxes (topics)</p>
</li>
<li><p>Other people (consumers) come and pick up the letters from their mailboxes</p>
</li>
</ul>
<p>The cool thing is that:</p>
<ul>
<li><p>The post office keeps the letters for a while, so people can pick them up when they're ready</p>
</li>
<li><p>Multiple people can read the same letter</p>
</li>
<li><p>The system can handle millions of letters per second without breaking a sweat</p>
</li>
</ul>
<h2 id="heading-why-use-kafka">Why Use Kafka?</h2>
<ul>
<li><p><strong>Decoupling</strong>: Your apps don't need to know about each other directly</p>
</li>
<li><p><strong>Scalability</strong>: Can handle huge amounts of data</p>
</li>
<li><p><strong>Reliability</strong>: Doesn't lose messages even if parts of the system fail</p>
</li>
<li><p><strong>Flexibility</strong>: Can be used for many different purposes (logging, tracking, connecting systems)</p>
</li>
</ul>
<h2 id="heading-how-well-learn">How We'll Learn</h2>
<p>We'll learn Kafka by building and understanding simple examples using NodeJS with ES6 imports. Our learning path will be:</p>
<ol>
<li><p><strong>Setup</strong>: Getting Kafka running on your computer using Docker</p>
</li>
<li><p><strong>Basic Concepts</strong>: Understanding the core ideas of Kafka</p>
</li>
<li><p><strong>Simple Producer</strong>: Creating an app that sends messages to Kafka</p>
</li>
<li><p><strong>Simple Consumer</strong>: Creating an app that reads messages from Kafka</p>
</li>
<li><p><strong>Real-world Example</strong>: Building a mini-project that shows Kafka in action</p>
</li>
</ol>
<p>Let's get started with the setup!</p>
<h2 id="heading-learning-path">Learning Path</h2>
<p>Follow these guides in order:</p>
<ol>
<li><p><a target="_blank" href="./01-setup/README.md">Setup Guide</a></p>
</li>
<li><p><a target="_blank" href="./02-concepts/README.md">Basic Concepts</a></p>
</li>
<li><p><a target="_blank" href="./03-producer/README.md">Your First Producer</a></p>
</li>
<li><p><a target="_blank" href="./04-consumer/README.md">Your First Consumer</a></p>
</li>
<li><p><a target="_blank" href="./05-real-world/README.md">Real-world Example</a></p>
</li>
</ol>
<h2 id="heading-key-concepts">Key Concepts</h2>
<ol>
<li><p><strong>Topics</strong>: A category or feed name to which records are published</p>
</li>
<li><p><strong>Partitions</strong>: Topics are split into partitions for scalability</p>
</li>
<li><p><strong>Producers</strong>: Applications that publish data to Kafka topics</p>
</li>
<li><p><strong>Consumers</strong>: Applications that subscribe to topics and process the feed of published records</p>
</li>
<li><p><strong>Consumer Groups</strong>: A group of consumers that together consume a topic</p>
</li>
<li><p><strong>Brokers</strong>: Kafka servers that store the data</p>
</li>
<li><p><strong>Zookeeper</strong>: Used for managing and coordinating Kafka brokers</p>
</li>
</ol>
<h2 id="heading-project-structure">Project Structure</h2>
<ul>
<li><p><code>docker-compose.yml</code>: Sets up Kafka and Zookeeper locally</p>
</li>
<li><p><code>python/</code>: Python examples for Kafka producers and consumers</p>
</li>
<li><p><code>nodejs/</code>: Node.js examples for Kafka producers and consumers</p>
</li>
<li><p><code>examples/</code>: Various use case examples</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Docker and Docker Compose</p>
</li>
<li><p>Node.js 14+ (for Node.js examples)</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Docker Compose Commands: Understanding 'up -d' vs 'up --build']]></title><description><![CDATA[As developers, we often work with Docker to containerize our applications. Docker Compose is a tool that helps us define and manage multi-container Docker applications. In this post, we'll explore two common Docker Compose commands and their use case...]]></description><link>https://blog.yuvraj.tech/docker-compose-commands-understanding-up-d-vs-up-build</link><guid isPermaLink="true">https://blog.yuvraj.tech/docker-compose-commands-understanding-up-d-vs-up-build</guid><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Thu, 15 Aug 2024 18:05:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/RYyr-k3Ysqg/upload/a7b72d3413b8663de5df0f91c16aad69.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As developers, we often work with Docker to containerize our applications. Docker Compose is a tool that helps us define and manage multi-container Docker applications. In this post, we'll explore two common Docker Compose commands and their use cases: <code>docker-compose up -d</code> and <code>docker-compose up --build</code>.</p>
<h2 id="heading-the-basics-what-these-commands-do">The Basics: What These Commands Do</h2>
<p>Before we dive into the details, let's quickly outline what these commands do:</p>
<ol>
<li><p><code>docker-compose up -d</code>: Starts containers in detached mode</p>
</li>
<li><p><code>docker-compose up --build</code>: Rebuilds images before starting containers</p>
</li>
</ol>
<p>Now, let's break down each command and explore when to use them.</p>
<h2 id="heading-docker-compose-up-d-quick-starts-in-the-background">docker-compose up -d: Quick Starts in the Background</h2>
<p>The <code>-d</code> flag in <code>docker-compose up -d</code> stands for "detached" mode. Here's what you need to know:</p>
<ul>
<li><p><strong>Background Operation</strong>: This command starts your containers in the background, freeing up your terminal for other tasks.</p>
</li>
<li><p><strong>Uses Existing Images</strong>: It uses pre-built images if they're available locally.</p>
</li>
<li><p><strong>Pulls if Necessary</strong>: If an image isn't found locally, it pulls from the registry.</p>
</li>
<li><p><strong>No Rebuilding</strong>: It doesn't rebuild images, even if their Dockerfiles have changed.</p>
</li>
</ul>
<p><strong>When to Use It:</strong></p>
<ul>
<li><p>When you want to quickly start your services without any changes</p>
</li>
<li><p>For production environments where images are pre-built</p>
</li>
<li><p>When you need to run services in the background</p>
</li>
</ul>
<h2 id="heading-docker-compose-up-build-ensuring-fresh-builds">docker-compose up --build: Ensuring Fresh Builds</h2>
<p>The <code>--build</code> flag forces Docker Compose to rebuild your images. Key points:</p>
<ul>
<li><p><strong>Forced Rebuild</strong>: It rebuilds all images defined with a <code>build</code> context in your docker-compose.yml file.</p>
</li>
<li><p><strong>Foreground Operation</strong>: By default, this runs in the foreground (attached mode).</p>
</li>
<li><p><strong>Incorporates Changes</strong>: Ensures your containers use the latest version of your code and Dockerfile instructions.</p>
</li>
</ul>
<p><strong>When to Use It:</strong></p>
<ul>
<li><p>After making changes to your Dockerfile</p>
</li>
<li><p>When you've updated your application code</p>
</li>
<li><p>In development environments where you frequently iterate on your containers</p>
</li>
</ul>
<h2 id="heading-combining-the-commands">Combining the Commands</h2>
<p>You're not limited to using these flags separately. You can combine them for different effects:</p>
<pre><code class="lang-plaintext">docker-compose up -d --build
</code></pre>
<p>This command rebuilds your images and then starts the containers in detached mode. It's useful when you want to ensure you're running the latest version of your services in the background.</p>
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p><strong>Development Workflows</strong>: Use <code>--build</code> frequently in development to ensure you're testing the latest changes.</p>
</li>
<li><p><strong>CI/CD Pipelines</strong>: Incorporate <code>--build</code> in your continuous integration processes to catch build issues early.</p>
</li>
<li><p><strong>Production Deployments</strong>: Use <code>-d</code> for production deployments where images are pre-built and validated.</p>
</li>
<li><p><strong>Documentation</strong>: Clearly document in your project README which command developers should use and when.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Understanding the nuances between <code>docker-compose up -d</code> and <code>docker-compose up --build</code> can significantly improve your Docker workflow. By choosing the right command for your situation, you can save time, ensure consistency, and avoid potential issues caused by outdated images.</p>
<p>Remember, the key is to use <code>-d</code> when you need quick, background starts of existing services, and <code>--build</code> when you need to incorporate recent changes into your containers.</p>
<p>What's your experience with these Docker Compose commands? Do you have any tips or tricks to share? Let us know in the comments below!</p>
]]></content:encoded></item><item><title><![CDATA[How to Fix "Docker: No Space Left on Device" Error]]></title><description><![CDATA[The "Docker: No Space Left on Device" error is a common roadblock for developers using Docker containers. This error occurs when Docker runs out of available disk space, halting your containerization efforts. Let's dive into the causes of this error ...]]></description><link>https://blog.yuvraj.tech/docker-no-space-left-on-device</link><guid isPermaLink="true">https://blog.yuvraj.tech/docker-no-space-left-on-device</guid><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Tue, 30 Jul 2024 16:44:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/l70397AVgCI/upload/e734733d12a111ad5720385029b1f85e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The "Docker: No Space Left on Device" error is a common roadblock for developers using Docker containers. This error occurs when Docker runs out of available disk space, halting your containerization efforts. Let's dive into the causes of this error and explore effective solutions to get your Docker environment back on track.</p>
<h2 id="heading-understanding-the-no-space-left-on-device-error-in-docker">Understanding the "No Space Left on Device" Error in Docker</h2>
<p>The "No Space Left on Device" error in Docker indicates that the filesystem where Docker stores its data has run out of free space. Docker uses disk space to store images, containers, volumes, and other data in the <code>/var/lib/docker</code> directory by default. When this directory fills up, Docker operations—such as pulling images, creating containers, or writing to volumes—fail.</p>
<p>Docker's space usage can quickly balloon due to:</p>
<ul>
<li><p>Accumulated unused images and containers</p>
</li>
<li><p>Orphaned volumes</p>
</li>
<li><p>Build cache from image creation</p>
</li>
<li><p>Logs and other operational data</p>
</li>
</ul>
<p>This error significantly impacts Docker operations, preventing you from creating new containers, pulling images, or even running existing containers in some cases.</p>
<h2 id="heading-quick-fix-freeing-up-space-in-docker">Quick Fix: Freeing Up Space in Docker</h2>
<p>To quickly resolve the "No Space Left on Device" error, use these commands to clean up Docker resources:</p>
<ol>
<li>Remove unused Docker objects:</li>
</ol>
<pre><code class="lang-bash">docker system prune
</code></pre>
<p>This command removes all stopped containers, unused networks, dangling images, and build cache.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fsvbc4mg60yctxfzcpy.png" alt="Image description" /></p>
<ol start="2">
<li>Remove unused images:</li>
</ol>
<pre><code class="lang-bash">docker image prune
</code></pre>
<ol start="3">
<li>Clean up volumes:</li>
</ol>
<pre><code class="lang-bash">docker volume prune
</code></pre>
<p>After running these commands, restart the Docker service:</p>
<pre><code class="lang-bash">sudo systemctl restart docker
</code></pre>
<h3 id="heading-monitoring-docker-disk-usage">Monitoring Docker Disk Usage</h3>
<p>To prevent future space issues, regularly monitor your Docker disk usage:</p>
<ol>
<li>Check overall disk space:</li>
</ol>
<pre><code class="lang-bash">df -h
</code></pre>
<ol start="2">
<li>View Docker-specific usage:</li>
</ol>
<pre><code class="lang-bash">docker system df
</code></pre>
<p>Set up alerts for low disk space and implement a regular maintenance schedule to keep your Docker environment healthy.</p>
<h2 id="heading-root-causes-of-docker-space-issues">Root Causes of Docker Space Issues</h2>
<p>Understanding the root causes helps in long-term prevention:</p>
<ol>
<li><p><strong>Accumulation of unused resources</strong>: Over time, unused images, containers, and volumes consume significant space.</p>
</li>
<li><p><strong>Large or numerous Docker volumes</strong>: Data-heavy applications can quickly fill up volumes.</p>
</li>
<li><p><strong>Default storage location limitations</strong>: The partition containing <code>/var/lib/docker</code> may be too small.</p>
</li>
<li><p><strong>System-wide disk space shortage</strong>: Your entire system might be running low on space, affecting Docker operations.</p>
</li>
</ol>
<h2 id="heading-advanced-solutions-for-docker-space-management">Advanced Solutions for Docker Space Management</h2>
<p>For more robust space management:</p>
<ol>
<li><p><strong>Configure a different storage driver</strong>: Some drivers are more space-efficient. Research options like overlay2 or devicemapper.</p>
</li>
<li><p><strong>Move Docker's data directory</strong>: Relocate to a larger partition:</p>
<pre><code class="lang-bash"> <span class="hljs-comment"># Stop Docker</span>
 sudo systemctl stop docker

 <span class="hljs-comment"># Move the data</span>
 sudo mv /var/lib/docker /path/to/new/location

 <span class="hljs-comment"># Update Docker's configuration</span>
 sudo nano /etc/docker/daemon.json
 <span class="hljs-comment"># Add: {"data-root": "/path/to/new/location"}</span>

 <span class="hljs-comment"># Restart Docker</span>
 sudo systemctl start docker
</code></pre>
</li>
<li><p><strong>Implement image lifecycle policies</strong>: Automatically remove old or unused images based on age or usage patterns.</p>
</li>
<li><p><strong>Use Docker Compose</strong>: Better manage resources across multiple containers and services.</p>
</li>
</ol>
<h3 id="heading-optimizing-dockerfiles-for-space-efficiency">Optimizing Dockerfiles for Space Efficiency</h3>
<p>Efficient Dockerfiles lead to smaller images and reduced space usage:</p>
<ol>
<li><p><strong>Use multi-stage builds</strong>: Separate build-time dependencies from runtime dependencies.</p>
</li>
<li><p><strong>Minimize layer size</strong>:</p>
<ul>
<li><p>Combine RUN commands</p>
</li>
<li><p>Clean up in the same layer where files are added</p>
</li>
</ul>
</li>
<li><p><strong>Leverage .dockerignore</strong>: Exclude unnecessary files from the build context.</p>
</li>
<li><p><strong>Choose appropriate base images</strong>: Use slim or alpine versions when possible.</p>
</li>
</ol>
<h2 id="heading-preventing-future-no-space-left-errors">Preventing Future "No Space Left" Errors</h2>
<p>Implement these strategies to avoid recurring space issues:</p>
<ol>
<li><p><strong>Set up regular cleanup cron jobs</strong>:</p>
<pre><code class="lang-bash"> 0 0 * * * docker system prune -af --volumes
</code></pre>
</li>
<li><p><strong>Use disk space monitoring tools</strong>: Consider tools like Prometheus with node_exporter for comprehensive monitoring.</p>
</li>
<li><p><strong>Educate team members</strong>: Share Docker best practices across your development team.</p>
</li>
<li><p><strong>Consider container orchestration</strong>: Solutions like Kubernetes can help with resource allocation and management.</p>
</li>
</ol>
<h2 id="heading-key-takeaways">Key Takeaways</h2>
<ul>
<li><p>The "No Space Left on Device" error often stems from Docker's storage management.</p>
</li>
<li><p>Regular cleanup and monitoring are crucial for preventing space issues.</p>
</li>
<li><p>Advanced solutions involve reconfiguring Docker's storage setup.</p>
</li>
<li><p>Optimizing Dockerfiles and implementing best practices can significantly reduce space usage.</p>
</li>
</ul>
<h2 id="heading-faqs">FAQs</h2>
<h3 id="heading-how-often-should-i-run-docker-cleanup-commands">How often should I run Docker cleanup commands?</h3>
<p>Run cleanup commands weekly or bi-weekly, depending on your Docker usage. For high-traffic environments, daily cleanups might be necessary.</p>
<h3 id="heading-can-i-move-dockers-data-directory-without-losing-my-containers-and-images">Can I move Docker's data directory without losing my containers and images?</h3>
<p>Yes, if you follow the correct procedure of stopping Docker, moving the data, updating the configuration, and restarting Docker.</p>
<h3 id="heading-whats-the-difference-between-docker-system-prune-and-docker-image-prune">What's the difference between docker system prune and docker image prune?</h3>
<p><code>docker system prune</code> removes unused data including stopped containers, unused networks, dangling images, and build cache. <code>docker image prune</code> only removes dangling images.</p>
<h3 id="heading-how-do-i-increase-dockers-default-storage-limit-on-windows">How do I increase Docker's default storage limit on Windows?</h3>
<p>On Windows, you can increase Docker's storage limit through the Docker Desktop settings. Navigate to Settings &gt; Resources &gt; Advanced and adjust the "Disk image size" slider.</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a target="_blank" href="https://docs.docker.com/config/pruning/">Docker official documentation on disk space issues</a></p>
</li>
<li><p><a target="_blank" href="https://docs.docker.com/storage/storagedriver/select-storage-driver/">Advanced Docker storage driver configuration guide</a></p>
</li>
<li><p><a target="_blank" href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/">Best practices for writing Dockerfiles</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Enabling Hot Reloading for Next.js in Docker]]></title><description><![CDATA[As developers, we're always looking for ways to streamline our workflow and boost productivity. One of the most powerful tools in our arsenal is hot reloading - the ability to see our changes reflected in real-time without manually restarting our app...]]></description><link>https://blog.yuvraj.tech/enabling-hot-reloading-for-nextjs-in-docker</link><guid isPermaLink="true">https://blog.yuvraj.tech/enabling-hot-reloading-for-nextjs-in-docker</guid><category><![CDATA[Next.js]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 19 Jul 2024 17:02:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/imgCpfIMoRw/upload/65adaee16b835bb28f2423b238c145c3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As developers, we're always looking for ways to streamline our workflow and boost productivity. One of the most powerful tools in our arsenal is hot reloading - the ability to see our changes reflected in real-time without manually restarting our application. But what happens when we throw Docker into the mix? In this post, we'll walk through the process of enabling hot reloading for a Next.js application running inside a Docker container.</p>
<h2 id="heading-why-docker">Why Docker?</h2>
<p>Docker has become an essential tool in modern web development. It allows us to create consistent development environments, simplify deployment processes, and ensure that our application runs the same way across different machines. However, running a Next.js application in Docker can sometimes feel like we're sacrificing the rapid feedback loop we're used to in local development.</p>
<h2 id="heading-the-challenge">The Challenge</h2>
<p>By default, when you run a Next.js application in a Docker container, changes to your local files aren't automatically reflected in the running application. This is because the container is isolated from your local file system. To bridge this gap and enable hot reloading, we need to make some specific configurations.</p>
<h2 id="heading-the-solution">The Solution</h2>
<p>To enable hot reloading for Next.js in Docker, we need to make changes to three key files: the Dockerfile, the Docker Compose file, and the Next.js configuration file. Let's break down each of these changes.</p>
<h3 id="heading-1-updating-the-dockerfile">1. Updating the Dockerfile</h3>
<p>First, we need to modify our Dockerfile to run Next.js in development mode:</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> node:<span class="hljs-number">18</span>-alpine

<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>

<span class="hljs-keyword">COPY</span><span class="bash"> package.json package-lock.json ./</span>
<span class="hljs-keyword">RUN</span><span class="bash"> npm ci</span>

<span class="hljs-keyword">COPY</span><span class="bash"> . .</span>
<span class="hljs-keyword">COPY</span><span class="bash"> next.config.mjs ./next.config.mjs</span>

<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">3000</span>

<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"npm"</span>, <span class="hljs-string">"run"</span>, <span class="hljs-string">"dev"</span>]</span>
</code></pre>
<p>The key changes here are:</p>
<ul>
<li><p>We're not running <code>npm run build</code> anymore.</p>
</li>
<li><p>We've changed the CMD to <code>npm run dev</code> to start Next.js in development mode.</p>
</li>
</ul>
<h3 id="heading-2-modifying-the-docker-compose-file">2. Modifying the Docker Compose File</h3>
<p>Next, we need to update our Docker Compose file to enable volume mounting:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-comment"># ... other services ...</span>

  <span class="hljs-attr">frontend:</span>
    <span class="hljs-attr">build:</span>
      <span class="hljs-attr">context:</span> <span class="hljs-string">./frontend</span>
      <span class="hljs-attr">dockerfile:</span> <span class="hljs-string">Dockerfile</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"3000:3000"</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">BACKEND_URL=http://backend:8000</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./frontend:/app</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">/app/node_modules</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">backend</span>
</code></pre>
<p>The crucial additions here are:</p>
<ul>
<li><p>We've added <code>volumes</code> to mount the local <code>frontend</code> directory to <code>/app</code> in the container.</p>
</li>
<li><p>We've included a volume for <code>node_modules</code> to prevent it from being overwritten by the local mount.</p>
</li>
</ul>
<h3 id="heading-3-adjusting-the-nextjs-configuration">3. Adjusting the Next.js Configuration</h3>
<p>Finally, we need to modify our Next.js configuration to enable file watching in Docker:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('next').NextConfig}</span> </span>*/</span>
<span class="hljs-keyword">const</span> nextConfig = {
  <span class="hljs-comment">// ... other configurations ...</span>

  <span class="hljs-attr">webpackDevMiddleware</span>: <span class="hljs-function"><span class="hljs-params">config</span> =&gt;</span> {
    config.watchOptions = {
      <span class="hljs-attr">poll</span>: <span class="hljs-number">1000</span>,
      <span class="hljs-attr">aggregateTimeout</span>: <span class="hljs-number">300</span>,
    }
    <span class="hljs-keyword">return</span> config
  },
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> nextConfig;
</code></pre>
<p>The added <code>webpackDevMiddleware</code> configuration enables polling for file changes, which is necessary for hot reloading to work in Docker.</p>
<h2 id="heading-putting-it-all-together">Putting It All Together</h2>
<p>With these changes in place, you can now run your Docker setup with hot reloading enabled. Use the following command to start your containers:</p>
<pre><code class="lang-plaintext">docker-compose up --build
</code></pre>
<p>Now, when you make changes to your Next.js application code, you should see those changes reflected almost immediately in your browser, just as if you were running Next.js directly on your host machine.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Enabling hot reloading for Next.js in Docker might seem like a small change, but it can significantly improve your development experience. It combines the consistency and isolation of Docker with the rapid feedback loop we've come to expect in modern web development.</p>
<p>Remember, the first time you run this setup, it might take a while to install all the dependencies. Subsequent runs should be much faster.</p>
<p>By following this guide, you've supercharged your Next.js development environment in Docker. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Is it Possible to Use Grafana Without Prometheus?]]></title><description><![CDATA[Grafana is widely known for its powerful data visualization capabilities, often used in conjunction with Prometheus for monitoring and metrics collection. However, many users wonder if it is possible to use Grafana without Prometheus. The answer is y...]]></description><link>https://blog.yuvraj.tech/is-it-possible-to-use-grafana-without-prometheus</link><guid isPermaLink="true">https://blog.yuvraj.tech/is-it-possible-to-use-grafana-without-prometheus</guid><category><![CDATA[#prometheus]]></category><category><![CDATA[Grafana]]></category><category><![CDATA[Devops]]></category><category><![CDATA[observability]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Mon, 10 Jun 2024 18:11:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/fPkvU7RDmCo/upload/b9c1f4faf39bca03320c83451d401b14.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Grafana is widely known for its powerful data visualization capabilities, often used in conjunction with Prometheus for monitoring and metrics collection. However, many users wonder if it is possible to use Grafana without Prometheus. The answer is yes! Grafana's versatility allows it to support a wide range of data sources, making it a flexible tool for various use cases.</p>
<p>In this article, we will explore the possibility and benefits of using Grafana without Prometheus, and provide a step-by-step guide on setting up Grafana with MySQL as the data source.</p>
<h2 id="heading-understanding-grafana">Understanding Grafana</h2>
<p>Grafana is an open-source platform for monitoring and observability that excels in visualizing data from a variety of sources. It offers a highly customizable dashboarding experience, allowing users to create, explore, and share dashboards that display data from different systems.</p>
<h2 id="heading-common-data-sources-supported-by-grafana">Common Data Sources Supported by Grafana</h2>
<p>Grafana supports numerous data sources out-of-the-box, including:</p>
<ul>
<li><p>MySQL</p>
</li>
<li><p>InfluxDB</p>
</li>
<li><p>Elasticsearch</p>
</li>
<li><p>PostgreSQL</p>
</li>
<li><p>Prometheus</p>
</li>
<li><p>Graphite</p>
</li>
<li><p>Cloudwatch</p>
</li>
<li><p>Azure Monitor</p>
</li>
</ul>
<p>These integrations enable users to visualize data from various databases and services, making Grafana a versatile tool for many applications.</p>
<h2 id="heading-benefits-of-using-grafana-without-prometheus">Benefits of Using Grafana Without Prometheus</h2>
<ul>
<li><p><strong>Flexibility in Data Source Selection</strong>: Grafana's support for multiple data sources means you can choose the one that best fits your needs, whether it's a SQL database, a time-series database, or a cloud service.</p>
</li>
<li><p><strong>Simplified Architecture</strong>: By using Grafana with a data source like MySQL, you can simplify your monitoring architecture, which might be beneficial for specific use cases.</p>
</li>
<li><p><strong>Cost Savings</strong>: Depending on your requirements, using a single data source can reduce complexity and costs associated with managing multiple monitoring tools.</p>
</li>
</ul>
<h2 id="heading-practical-example-setting-up-grafana-with-mysql">Practical Example: Setting Up Grafana with MySQL</h2>
<p>Let's dive into a practical example of setting up Grafana with MySQL as the data source.</p>
<p><strong>Step 1: Install Grafana</strong></p>
<p>Download and install Grafana from the <a target="_blank" href="https://grafana.com/docs/grafana/latest/setup-grafana/installation/mac/">official website</a>. Follow the installation instructions for your operating system.</p>
<p><strong>Step 2: Set Up MySQL and Create a Sample Database</strong></p>
<p>Install MySQL on your system if it's not already installed. Create a sample database and table for storing your data:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DATABASE</span> sample_db;
<span class="hljs-keyword">USE</span> sample_db;
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> metrics (
  <span class="hljs-keyword">id</span> <span class="hljs-built_in">INT</span> AUTO_INCREMENT PRIMARY <span class="hljs-keyword">KEY</span>,
  metric_name <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-keyword">value</span> <span class="hljs-built_in">FLOAT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-built_in">timestamp</span> DATETIME <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CURRENT_TIMESTAMP</span>
);
<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> metrics (metric_name, <span class="hljs-keyword">value</span>) <span class="hljs-keyword">VALUES</span> (<span class="hljs-string">'cpu_usage'</span>, <span class="hljs-number">23.5</span>), (<span class="hljs-string">'memory_usage'</span>, <span class="hljs-number">55.1</span>);
</code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2na013acwcrj3iynn0bn.png" alt="Image description" /></p>
<p><strong>Step 3: Configure Grafana to Connect to MySQL</strong></p>
<ul>
<li><p>Open Grafana in your browser (default URL is <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>).</p>
</li>
<li><p>Log in with the default credentials (admin/admin, you an read detailed guide to login <a target="_blank" href="https://grafana.com/docs/grafana/latest/setup-grafana/sign-in-to-grafana/">here</a>).</p>
</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/90qwgjcims7mir2g0dlh.png" alt="Image description" /></p>
<ul>
<li>Navigate to Configuration &gt; Data Sources and click Add data source.</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/he4h6m4azsdsjmy6coeq.png" alt="Image description" /></p>
<ul>
<li><p>Select MySQL from the list of data sources.</p>
</li>
<li><p>Enter the necessary connection details (e.g., host, database name, user, and password) and click Save &amp; Test to verify the connection.</p>
<ul>
<li><p>Host URL will be likely <a target="_blank" href="http://localhost:3306"><code>localhost:3306</code></a></p>
</li>
<li><p>Database Name: <code>sample_db</code></p>
</li>
<li><p>Add your database username and password in the authentication.</p>
</li>
</ul>
</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zj6oms2h77myam778jwk.png" alt="Image description" /></p>
<p><strong>Step 4: Create a Simple Dashboard Using MySQL Data</strong></p>
<ul>
<li>Navigate to Create &gt; Dashboard and click Add new panel.</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4fhl8y9xx6czmo3eldht.png" alt="Image description" /></p>
<ul>
<li><p>Select your MySQL data source.</p>
</li>
<li><p>Write a simple SQL query to fetch data from your sample table:</p>
</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span>
  <span class="hljs-keyword">UNIX_TIMESTAMP</span>(<span class="hljs-built_in">timestamp</span>) <span class="hljs-keyword">as</span> time_sec,
  <span class="hljs-keyword">value</span> <span class="hljs-keyword">as</span> <span class="hljs-keyword">value</span>,
  metric_name <span class="hljs-keyword">as</span> metric
<span class="hljs-keyword">FROM</span> metrics
</code></pre>
<p>Customize the visualization as needed and save your dashboard.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xywfgnehxs8tcpdo46po.png" alt="Image description" /></p>
<h2 id="heading-real-world-use-cases">Real-World Use Cases</h2>
<p>Many organizations leverage Grafana with data sources other than Prometheus to meet specific needs:</p>
<ul>
<li><p>Web Application Monitoring: Using MySQL or PostgreSQL to track user interactions and performance metrics.</p>
</li>
<li><p>Business Analytics: Visualizing data from SQL databases to monitor KPIs and other business metrics.</p>
</li>
<li><p>IoT Data Visualization: Utilizing InfluxDB to collect and visualize sensor data.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Grafana is a versatile tool that can be used with a variety of data sources beyond Prometheus. This flexibility allows users to tailor their monitoring and visualization setup to their specific needs, simplifying architecture and potentially reducing costs.</p>
<p>For a deeper comparison between Prometheus and Grafana, you can check out this <a target="_blank" href="https://signoz.io/comparisons/prometheus-vs-grafana/">comprehensive article</a>.</p>
<p>Have you used Grafana with a data source other than Prometheus? Share your experiences and questions in the comments below.</p>
]]></content:encoded></item><item><title><![CDATA[How I Solved Integer to Roman Problem on Leetcode (Python)]]></title><description><![CDATA[Problem
The problem is simple to understand, we are given an integer and we need to convert it into a Roman numeral.
Difficulty: Medium
Roman numerals are represented by seven different symbols: I, V, X, L, C, D, and M.
Conversion Table




SymbolVal...]]></description><link>https://blog.yuvraj.tech/how-i-solved-integer-to-roman-problem-on-leetcode-python</link><guid isPermaLink="true">https://blog.yuvraj.tech/how-i-solved-integer-to-roman-problem-on-leetcode-python</guid><category><![CDATA[problem solving skills]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Wed, 29 Dec 2021 18:09:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1640801354163/ZM-r6aG4V.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-problem">Problem</h2>
<p>The problem is simple to understand, we are given an integer and we need to convert it into a Roman numeral.</p>
<p><strong>Difficulty</strong>: Medium</p>
<p>Roman numerals are represented by seven different symbols: I, V, X, L, C, D, and M.</p>
<p><strong>Conversion Table</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Symbol</td><td>Value</td></tr>
</thead>
<tbody>
<tr>
<td>I</td><td>1</td></tr>
<tr>
<td>V</td><td>5</td></tr>
<tr>
<td>X</td><td>10</td></tr>
<tr>
<td>L</td><td>50</td></tr>
<tr>
<td>C</td><td>100</td></tr>
<tr>
<td>D</td><td>500</td></tr>
<tr>
<td>M</td><td>1000</td></tr>
</tbody>
</table>
</div><p>For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.</p>
<p>Roman numerals are usually written from largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:</p>
<ul>
<li>I can be placed before V (5) and X (10) to make 4 and 9. </li>
<li>X can be placed before L (50) and C (100) to make 40 and 90. </li>
<li>C can be placed before D (500) and M (1000) to make 400 and 900.</li>
</ul>
<p><strong>Given an integer, convert it to a roman numeral.</strong></p>
<h2 id="heading-example">Example</h2>
<h4 id="heading-example-1">Example 1:</h4>
<pre><code><span class="hljs-attr">Input:</span> <span class="hljs-string">num</span> <span class="hljs-string">=</span> <span class="hljs-number">3</span>
<span class="hljs-attr">Output:</span> <span class="hljs-string">"III"</span>
<span class="hljs-attr">Explanation:</span> <span class="hljs-number">3</span> <span class="hljs-string">is</span> <span class="hljs-string">represented</span> <span class="hljs-string">as</span> <span class="hljs-number">3</span> <span class="hljs-string">ones.</span>
</code></pre><h4 id="heading-example-2">Example 2:</h4>
<pre><code><span class="hljs-attr">Input:</span> <span class="hljs-string">num</span> <span class="hljs-string">=</span> <span class="hljs-number">58</span>
<span class="hljs-attr">Output:</span> <span class="hljs-string">"LVIII"</span>
<span class="hljs-attr">Explanation:</span> <span class="hljs-string">L</span> <span class="hljs-string">=</span> <span class="hljs-number">50</span><span class="hljs-string">,</span> <span class="hljs-string">V</span> <span class="hljs-string">=</span> <span class="hljs-number">5</span><span class="hljs-string">,</span> <span class="hljs-string">III</span> <span class="hljs-string">=</span> <span class="hljs-number">3</span><span class="hljs-string">.</span>
</code></pre><h4 id="heading-example-3">Example 3:</h4>
<pre><code><span class="hljs-attr">Input:</span> <span class="hljs-string">num</span> <span class="hljs-string">=</span> <span class="hljs-number">1994</span>
<span class="hljs-attr">Output:</span> <span class="hljs-string">"MCMXCIV"</span>
<span class="hljs-attr">Explanation:</span> <span class="hljs-string">M</span> <span class="hljs-string">=</span> <span class="hljs-number">1000</span><span class="hljs-string">,</span> <span class="hljs-string">CM</span> <span class="hljs-string">=</span> <span class="hljs-number">900</span><span class="hljs-string">,</span> <span class="hljs-string">XC</span> <span class="hljs-string">=</span> <span class="hljs-number">90</span> <span class="hljs-string">and</span> <span class="hljs-string">IV</span> <span class="hljs-string">=</span> <span class="hljs-number">4</span><span class="hljs-string">.</span>
</code></pre><h2 id="heading-constraints">Constraints</h2>
<ul>
<li><code>1 &lt;= num &lt;= 3999</code></li>
</ul>
<h2 id="heading-solution-template">Solution Template</h2>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">intToRoman</span>(<span class="hljs-params">self, num: int</span>) -&gt; str:</span>
        <span class="hljs-keyword">pass</span>  <span class="hljs-comment"># Write your solution here</span>
</code></pre><p>We have to implement the <code>intToRoman</code> function that accepts a <code>num</code> integer and returns <code>str</code>.</p>
<h2 id="heading-finding-the-solution">Finding the Solution</h2>
<h3 id="heading-first-thought">First Thought</h3>
<p>On reading the question, the first thing that came to my mind was the solution must involve some repeated division and modulus. 
Why?
Check out the following figure:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640786210361/PCl6DILNe.png" alt="convert 12 to Roman numeral illustration" /></p>
<p>Let's understand, what does this image means.
We have to convert 12 to its Roman numeral equivalent. Firstly, we selected the biggest number that is smaller than 12 and whose conversion is already present in the table given above. 
That is the number 10. We divided 12 by 10 and the quotient is how many times we need to repeat 10 to get as close to 12 as possible (In our case, it is just 1).
Now, we repeat the same process for what remains that is the remainder.
Until we got 0, then we add all the strings to get the final roman numeral.</p>
<p><strong>Algorithm:</strong></p>
<ol>
<li>Let <code>roman</code> be the final result we want. Set <code>roman = ""</code>.</li>
<li>Find the biggest small number in the conversion table than <code>num</code>. Name it <code>base_value</code>. </li>
<li>Divide <code>num</code> by <code>base_value</code>.</li>
<li><code>roman</code> += Roman Numeral for Base Value * Quotient.</li>
<li>Repeat steps 2 to 4 for the remainder until the remainder becomes 0.</li>
</ol>
<p>Also make sure that:</p>
<ul>
<li>If the number is 0, then directly return the empty string <code>""</code> (There is no zero in Roman numerals).</li>
<li>If the number is present in the conversion table, directly return the corresponding value. For example, return <code>X</code> for 10.</li>
</ul>
<h2 id="heading-implementing-the-recursive-solution">Implementing the Recursive Solution</h2>
<p>Let's now implement the solution. Start by creating a dictionary for the conversion table:</p>
<pre><code>conversion_table = {
            1:      <span class="hljs-string">"I"</span>,
            5:      <span class="hljs-string">"V"</span>,
            10:     <span class="hljs-string">"X"</span>,
            50:     <span class="hljs-string">"L"</span>,
            100:    <span class="hljs-string">"C"</span>,
            500:    <span class="hljs-string">"D"</span>,
            1000:   <span class="hljs-string">"M"</span>,
            4:      <span class="hljs-string">"IV"</span>,
            9:      <span class="hljs-string">"IX"</span>,
            40:     <span class="hljs-string">"XL"</span>,
            90:     <span class="hljs-string">"XC"</span>,
            400:    <span class="hljs-string">"CD"</span>,
            900:    <span class="hljs-string">"CM"</span>,
        }
</code></pre><p><strong>Notice</strong>, we are also including the conversions for exceptional numbers like 4, 9, 40, 90, and so on. </p>
<p>Now, handle the base cases:</p>
<pre><code><span class="hljs-keyword">if</span> <span class="hljs-built_in">num</span> == <span class="hljs-number">0</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>

<span class="hljs-keyword">if</span> <span class="hljs-built_in">num</span> <span class="hljs-keyword">in</span> conversion_table:
    <span class="hljs-keyword">return</span> conversion_table[<span class="hljs-built_in">num</span>]
</code></pre><p>Now, we will find the <code>base_value</code>, which is the biggest smaller value than the <code>num</code>:</p>
<pre><code>base_value <span class="hljs-operator">=</span> <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> value in conversion_table:
    <span class="hljs-keyword">if</span> base_value <span class="hljs-operator">&lt;</span> value <span class="hljs-operator">&lt;</span> num:
        base_value <span class="hljs-operator">=</span> value
</code></pre><p>Now, just add a recursive call with the formula we constructed before:</p>
<pre><code><span class="hljs-keyword">return</span> ((num <span class="hljs-comment">// base_value) * conversion_table[base_value]) + self.intToRoman(num % base_value)</span>
</code></pre><h3 id="heading-complete-recursive-solution-code">Complete Recursive Solution Code</h3>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:
    <span class="hljs-title">def</span> <span class="hljs-title">intToRoman</span>(<span class="hljs-title">self</span>, <span class="hljs-title">num</span>: <span class="hljs-title">int</span>) -&gt; <span class="hljs-title">str</span>:
        <span class="hljs-title">conversion_table</span> = </span>{
            <span class="hljs-number">1</span>:      <span class="hljs-string">"I"</span>,
            <span class="hljs-number">5</span>:      <span class="hljs-string">"V"</span>,
            <span class="hljs-number">10</span>:     <span class="hljs-string">"X"</span>,
            <span class="hljs-number">50</span>:     <span class="hljs-string">"L"</span>,
            <span class="hljs-number">100</span>:    <span class="hljs-string">"C"</span>,
            <span class="hljs-number">500</span>:    <span class="hljs-string">"D"</span>,
            <span class="hljs-number">1000</span>:   <span class="hljs-string">"M"</span>,
            <span class="hljs-number">4</span>:      <span class="hljs-string">"IV"</span>,
            <span class="hljs-number">9</span>:      <span class="hljs-string">"IX"</span>,
            <span class="hljs-number">40</span>:     <span class="hljs-string">"XL"</span>,
            <span class="hljs-number">90</span>:     <span class="hljs-string">"XC"</span>,
            <span class="hljs-number">400</span>:    <span class="hljs-string">"CD"</span>,
            <span class="hljs-number">900</span>:    <span class="hljs-string">"CM"</span>,
        }

        <span class="hljs-keyword">if</span> <span class="hljs-built_in">num</span> == <span class="hljs-number">0</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>

        <span class="hljs-keyword">if</span> <span class="hljs-built_in">num</span> <span class="hljs-keyword">in</span> conversion_table:
            <span class="hljs-keyword">return</span> conversion_table[<span class="hljs-built_in">num</span>]

        # base_value = biggest smaller value than <span class="hljs-built_in">num</span>
        base_value = <span class="hljs-number">0</span>
        <span class="hljs-keyword">for</span> value <span class="hljs-keyword">in</span> conversion_table:
            <span class="hljs-keyword">if</span> base_value &lt; value &lt; <span class="hljs-built_in">num</span>:
                base_value = value

        <span class="hljs-keyword">return</span> ((<span class="hljs-built_in">num</span> <span class="hljs-comment">// base_value) * conversion_table[base_value]) + self.intToRoman(num % base_value)</span>
</code></pre><h3 id="heading-output">Output</h3>
<pre><code><span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span> Solution().intToRoman(<span class="hljs-number">12</span>)
<span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span> `XII`
<span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span> Solution().intToRoman(<span class="hljs-number">1234</span>)
<span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&gt;</span> `MCCXXXIV`
</code></pre><h2 id="heading-non-recursive-solution-using-a-while-loop">Non-Recursive Solution (Using a While Loop)</h2>
<p>Here's a non-recursive solution using the same algorithm:</p>
<pre><code>class Solution:
    def intToRoman(<span class="hljs-built_in">self</span>, num: <span class="hljs-keyword">int</span>) <span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span> str:
        conversion_table <span class="hljs-operator">=</span> {
            <span class="hljs-number">1</span>:      <span class="hljs-string">"I"</span>,
            <span class="hljs-number">5</span>:      <span class="hljs-string">"V"</span>,
            <span class="hljs-number">10</span>:     <span class="hljs-string">"X"</span>,
            <span class="hljs-number">50</span>:     <span class="hljs-string">"L"</span>,
            <span class="hljs-number">100</span>:    <span class="hljs-string">"C"</span>,
            <span class="hljs-number">500</span>:    <span class="hljs-string">"D"</span>,
            <span class="hljs-number">1000</span>:   <span class="hljs-string">"M"</span>,
            <span class="hljs-number">4</span>:      <span class="hljs-string">"IV"</span>,
            <span class="hljs-number">9</span>:      <span class="hljs-string">"IX"</span>,
            <span class="hljs-number">40</span>:     <span class="hljs-string">"XL"</span>,
            <span class="hljs-number">90</span>:     <span class="hljs-string">"XC"</span>,
            <span class="hljs-number">400</span>:    <span class="hljs-string">"CD"</span>,
            <span class="hljs-number">900</span>:    <span class="hljs-string">"CM"</span>,
        }


        roman <span class="hljs-operator">=</span> <span class="hljs-string">""</span>    

        <span class="hljs-keyword">while</span> num:

            <span class="hljs-keyword">if</span> num <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>:
                <span class="hljs-keyword">return</span> roman

            <span class="hljs-keyword">if</span> num in conversion_table:
                <span class="hljs-keyword">return</span> roman <span class="hljs-operator">+</span> conversion_table[num]


            base_value <span class="hljs-operator">=</span> <span class="hljs-number">0</span>
            <span class="hljs-keyword">for</span> value in conversion_table:
                <span class="hljs-keyword">if</span> base_value <span class="hljs-operator">&lt;</span> value <span class="hljs-operator">&lt;</span> num:
                    base_value <span class="hljs-operator">=</span> value

            roman <span class="hljs-operator">+</span><span class="hljs-operator">=</span> ((num <span class="hljs-comment">// base_value) * conversion_table[base_value])</span>
            num <span class="hljs-operator">=</span> num <span class="hljs-operator">%</span> base_value


        <span class="hljs-keyword">return</span>  roman
</code></pre><h2 id="heading-result">Result</h2>
<p>The solution is accepted on Leetcode:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640799638452/Gb5nJLzuZ.png" alt="result" /></p>
<h2 id="heading-try-it-out">Try it Out</h2>
<iframe style="max-width:100%;border:none" height="375" width="700" src="https://www.interviewbit.com/embed/snippet/c17de0136e0c0275450a">

<h2 id="heading-conclusion">Conclusion</h2>
<ul>
<li>We converted an integer to a roman numeral using a recursive and a non-recursive solution.</li>
<li>We developed the algorithm using the division and modulus operator.</li>
</ul>
<p>Note: This is not supposed to be the "best" solution to this problem. This is just what I thought of. 
If you have a better solution or some feedback to improve this solution, please let me know in the comments.</p>
<p>Like and follow for more such articles.
Connect with me on <a target="_blank" href="https://twitter.com/yuvraajsj18">Twitter</a>, <a target="_blank" href="https://github.com/yuvraajsj18">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/yuvraajsj18/">LinkedIn</a>.</p>
</iframe>]]></content:encoded></item><item><title><![CDATA[How to Use Python Dictionaries]]></title><description><![CDATA[Introduction
In this article, we will cover different ways of defining a dictionary, how to access and update values of a dictionary, the dictionary’s built-in methods, and how to use dict comprehension. 
We will also learn about restrictions on keys...]]></description><link>https://blog.yuvraj.tech/how-to-use-python-dictionaries</link><guid isPermaLink="true">https://blog.yuvraj.tech/how-to-use-python-dictionaries</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[data structures]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Mon, 25 Oct 2021 08:39:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635151110648/1h01yP7IF.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1>
<p>In this article, we will cover different ways of defining a dictionary, how to access and update values of a dictionary, the dictionary’s built-in methods, and how to use dict comprehension. </p>
<p>We will also learn about restrictions on keys of a dictionary, membership operators, pretty-printing a dictionary, and making a shallow copy vs deep copy of a dictionary. </p>
<h1 id="what-is-a-dictionary-in-python">What is a dictionary in Python?</h1>
<p>Python provides several useful data types built-in, Dictionary is one such data structure.</p>
<p><em>A dictionary is a collection of key: value pairs where each value is accessed using a unique key.</em></p>
<p>This is in contrast to the <em>list</em> where elements are accessed using their indexes.</p>
<p>We can think of a dictionary as a table with two columns:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635149690035/ReQ8RT05H.png" alt="image.png" /></p>
<blockquote>
<p>Highlights:</p>
<ul>
<li>A dictionary is a collection of key: value pairs where each value is accessed using a unique key.</li>
</ul>
</blockquote>
<h1 id="how-to-define-a-dictionary">How to define a dictionary?</h1>
<p>We can define a dictionary in three different ways. Let's see each one of them by converting the above pictorial representation of the dictionary into a real python one.</p>
<h3 id="using-curly-braces">Using curly braces <code>{}</code></h3>
<p>We can use the curly braces to define a dictionary by providing key-value pairs separated by a '<strong>:'</strong> as <code>key: value</code>:</p>
<pre><code class="lang-python">harry_info = {
    <span class="hljs-string">"name"</span>: <span class="hljs-string">"Harry"</span>,
    <span class="hljs-string">"age"</span>: <span class="hljs-number">11</span>,
    <span class="hljs-string">"house"</span>: <span class="hljs-string">"Gryffindor"</span>,
}

print(harry_info)
print(type(harry_info))  <span class="hljs-comment"># &lt;class 'dict'&gt;</span>
</code></pre>
<p>Notice that a dictionary can have values of different types.</p>
<p>We can also create an empty dictionary using <code>{}</code> as: <code>empty_dict = {}</code>.</p>
<h3 id="using-dict-function">Using <code>dict()</code> function</h3>
<p>We can create a dictionary by passing a list of tuples to the <em>dict</em> function:</p>
<pre><code class="lang-python">harry_info = dict([
                   (<span class="hljs-string">"name"</span>, <span class="hljs-string">"Harry"</span>),
                   (<span class="hljs-string">"age"</span>, <span class="hljs-number">11</span>),
                   (<span class="hljs-string">"house"</span>, <span class="hljs-string">"Gryffindor"</span>)
])

print(harry_info)
</code></pre>
<h3 id="using-keyword-arguments-in-dict">Using keyword arguments in <code>dict()</code></h3>
<p>We can provide keyword arguments to the <em>dict</em> function when all keys are <em>string</em>:</p>
<pre><code class="lang-python">harry_info = dict(
    name = <span class="hljs-string">"Harry"</span>,
    age = <span class="hljs-number">11</span>,
    house = <span class="hljs-string">"Gryffindor"</span>
)

print(harry_info)
</code></pre>
<h2 id="values-in-a-dictionary">Values in a dictionary</h2>
<p>A dictionary can store any type of value including another dictionary. Let's change the <em>harry_info</em> dictionary to contain a nested dictionary <em>house</em> and a list of <em>friends:</em></p>
<pre><code class="lang-python">harry_info = {
    <span class="hljs-string">"name"</span>: <span class="hljs-string">"Harry"</span>,
    <span class="hljs-string">"age"</span>: <span class="hljs-number">11</span>,
    <span class="hljs-string">"house"</span>: {
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"Gryffindor"</span>,
      <span class="hljs-string">"Animal"</span>: <span class="hljs-string">"Lion"</span>,
      <span class="hljs-string">"Element"</span>: <span class="hljs-string">"Fire"</span>   
    },
    <span class="hljs-string">"friends"</span>: [<span class="hljs-string">"Ron"</span>, <span class="hljs-string">"Hermione"</span>]
}

print(harry_info)
</code></pre>
<p><strong>Tip</strong> 💡</p>
<p>When we print the above dictionary the output would not be very readable, we can use the <code>pprint</code> function to pretty print a dictionary:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pprint <span class="hljs-keyword">import</span> pprint

pprint(harry_info)
</code></pre>
<p>Output:</p>
<pre><code class="lang-python">{<span class="hljs-string">'age'</span>: <span class="hljs-number">11</span>,
 <span class="hljs-string">'friends'</span>: [<span class="hljs-string">'Ron'</span>, <span class="hljs-string">'Hermione'</span>],
 <span class="hljs-string">'house'</span>: {<span class="hljs-string">'Animal'</span>: <span class="hljs-string">'Lion'</span>, <span class="hljs-string">'Element'</span>: <span class="hljs-string">'Fire'</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'Gryffindor'</span>},
 <span class="hljs-string">'name'</span>: <span class="hljs-string">'Harry'</span>}
</code></pre>
<h2 id="restrictions-on-keys">Restrictions on keys</h2>
<p>There are two restrictions we need to know when defining keys:</p>
<ol>
<li><p><strong>Duplicate keys are not allowed</strong></p>
<p> If we define the same key twice, the second occurrence will override the first one:</p>
<pre><code class="lang-python"> duplicate_dict = {
     <span class="hljs-string">"first"</span>: <span class="hljs-number">0</span>,
     <span class="hljs-string">"second"</span>: <span class="hljs-number">2</span>,
     <span class="hljs-string">"first"</span>:<span class="hljs-number">1</span>
 }

 print(duplicate_dict)
</code></pre>
<p> This will print:</p>
<p>  <code>{'first': 1, 'second': 2}</code> ✅</p>
<p> and not</p>
<p> <code>{'first': 0, 'second': 2}</code> ❌</p>
<p> <code>{'first': 0, 'second': 2, 'first': 1}</code> ❌</p>
</li>
<li><p><strong>Keys must be immutable</strong></p>
<p> Keys must have a type that is immutable, which means any type whose value doesn't change once created like <em>int, bool, str, float, etc.</em></p>
<p> That's why we can have a <em>tuple</em> as a key but not a <em>list:</em></p>
<pre><code class="lang-python"> example_dict = {
     (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>): <span class="hljs-string">"Tuple"</span>,  <span class="hljs-comment"># Okay to use</span>
     <span class="hljs-literal">False</span>: <span class="hljs-string">"Bool"</span>,    <span class="hljs-comment"># Okay to use</span>
     <span class="hljs-number">1</span>: <span class="hljs-string">"int"</span>,         <span class="hljs-comment"># Okay to use</span>
     [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]: <span class="hljs-string">"list"</span>,   <span class="hljs-comment"># raises TypeError</span>
 }
</code></pre>
<p> Using a list as a key raises <em>TypeError: unhashable type: 'list'</em> because it is a mutable object. </p>
<p> Technically, a key requires a <em>hashable</em> value which means that Python's built-in hash() function should return a <em>unique hash value</em> for that object and all immutable types satisfy this condition.</p>
</li>
</ol>
<blockquote>
<p>Highlights:</p>
<ul>
<li>We can define a dictionary using:<ul>
<li>Key-value pairs in curly braces.</li>
<li>Using dict function</li>
</ul>
</li>
<li>A dictionary can have any type of value.</li>
<li>Key cannot be:<ul>
<li>Duplicated</li>
<li>Mutable (more precisely unhashable)</li>
</ul>
</li>
</ul>
</blockquote>
<h1 id="how-to-access-values-in-a-dictionary">How to access values in a dictionary?</h1>
<p>We can access a value from a dictionary by using the square brackets <code>[]</code>.</p>
<p> So <code>dict_name[key]</code> will return the corresponding <em>value.</em></p>
<p>Let's try to retrieve some values from the <em>harry_info</em> dictionary:</p>
<p><code>print(harry_info["name"])</code></p>
<p>Output: "Harry"</p>
<p><code>print(harry_info["friends"])</code></p>
<p>Output: ['Ron', 'Hermione']</p>
<p><strong>What if we try to retrieve a value using a key that doesn't exist?</strong></p>
<p>Let's try that too:</p>
<p><code>print(harry_info["enemies"])</code></p>
<p>Output: KeyError: 'enemies'</p>
<p>We got a key error which means that <em>we can not retrieve keys that don't exist using the square bracket syntax.</em></p>
<h3 id="adding-a-new-key-value-pair-to-the-dictionary">Adding a new key-value pair to the dictionary</h3>
<p>As <em>dictionaries are mutable structures</em>, we can add new members by assigning values to new keys using the same square bracket operator:</p>
<p>Syntax: <code>dict_name[new_key] = value</code></p>
<pre><code class="lang-python">harry_info[<span class="hljs-string">"enemies"</span>] = [<span class="hljs-string">"Voldemort"</span>, <span class="hljs-string">"Death Eaters"</span>]
</code></pre>
<h3 id="updating-existing-key-value-pair-of-a-dictionary">Updating existing key-value pair of a dictionary</h3>
<p>We can also update the key's values similarly using the square brackets:</p>
<p>Syntax: <code>dict_name[key] = new_value</code></p>
<pre><code class="lang-python">harry_info[<span class="hljs-string">"age"</span>] = <span class="hljs-number">17</span>
</code></pre>
<p>This will update the <em>age</em> key from 11 to 17.</p>
<h3 id="using-membership-operator-with-dictionaries">Using Membership operator with dictionaries</h3>
<p>We can use the <code>in</code> and <code>not in</code> operators to check whether a key exists in the dictionary or not:</p>
<pre><code class="lang-python">print(<span class="hljs-string">'name'</span> <span class="hljs-keyword">in</span> harry_info)     <span class="hljs-comment"># Output: True</span>

print(<span class="hljs-string">'name'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> harry_info) <span class="hljs-comment"># Output: False</span>

print(<span class="hljs-string">'year'</span> <span class="hljs-keyword">in</span> harry_info)     <span class="hljs-comment"># Output: False</span>

print(<span class="hljs-string">'year'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> harry_info) <span class="hljs-comment"># Output: True</span>
</code></pre>
<h3 id="get-the-number-of-key-value-pairs">Get the number of key-value pairs</h3>
<p>Use the built-in <em>len</em> function to get the number of key-value pairs in a dictionary:</p>
<pre><code class="lang-python">print(len(harry_info))  <span class="hljs-comment"># Output: 5</span>
</code></pre>
<blockquote>
<p>Highlights:</p>
<ul>
<li>Access values using dict_name[key] syntax.</li>
<li>Add a new value using dict_name[new_key] = value.</li>
<li>Update a value using the same syntax as (2).</li>
<li>Use in and not in operator to check for key existence in a dictionary.</li>
<li>Use the len function to get the number of key-value pairs.</li>
</ul>
</blockquote>
<h1 id="built-in-dictionary-methods">Built-in Dictionary Methods</h1>
<h3 id="getkey-defaultnone">get(key, default=None)</h3>
<p>This is an alternative to the <code>[]</code> for accessing the values using a key from a dictionary. The difference is that we can provide a default value to return when a key doesn't exist instead of raising a key error.</p>
<pre><code class="lang-python">print(harry_info.get(<span class="hljs-string">"name"</span>))     <span class="hljs-comment"># Output: Harry</span>
print(harry_info.get(<span class="hljs-string">"year"</span>))     <span class="hljs-comment"># Output: None</span>
print(harry_info.get(<span class="hljs-string">"year"</span>, <span class="hljs-number">7</span>))  <span class="hljs-comment"># Output: 7</span>
</code></pre>
<h3 id="items">items()</h3>
<p>Returns a list of tuples containing the key-value pairs of a dictionary.</p>
<pre><code class="lang-python">print(list(harry_info.items()))
</code></pre>
<p>Output:</p>
<pre><code class="lang-python">[(<span class="hljs-string">'name'</span>, <span class="hljs-string">'Harry'</span>), (<span class="hljs-string">'age'</span>, <span class="hljs-number">17</span>), (<span class="hljs-string">'house'</span>, {<span class="hljs-string">'name'</span>: <span class="hljs-string">'Gryffindor'</span>, <span class="hljs-string">'Animal'</span>: <span class="hljs-string">'Lion'</span>, <span class="hljs-string">'Element'</span>: <span class="hljs-string">'Fire'</span>}), (<span class="hljs-string">'friends'</span>, [<span class="hljs-string">'Ron'</span>, <span class="hljs-string">'Hermione'</span>]), (<span class="hljs-string">'enemies'</span>, [<span class="hljs-string">'Voldemort'</span>, <span class="hljs-string">'Death Eaters'</span>])]
</code></pre>
<p>We can use the <em>items</em> method to loop through a dictionary:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> harry_info.items():
  print(key, <span class="hljs-string">'is'</span>, value)
</code></pre>
<p>Output:</p>
<pre><code class="lang-python">name <span class="hljs-keyword">is</span> Harry
age <span class="hljs-keyword">is</span> <span class="hljs-number">17</span>
house <span class="hljs-keyword">is</span> {<span class="hljs-string">'name'</span>: <span class="hljs-string">'Gryffindor'</span>, <span class="hljs-string">'Animal'</span>: <span class="hljs-string">'Lion'</span>, <span class="hljs-string">'Element'</span>: <span class="hljs-string">'Fire'</span>}
friends <span class="hljs-keyword">is</span> [<span class="hljs-string">'Ron'</span>, <span class="hljs-string">'Hermione'</span>]
enemies <span class="hljs-keyword">is</span> [<span class="hljs-string">'Voldemort'</span>, <span class="hljs-string">'Death Eaters'</span>]
</code></pre>
<h3 id="keys">keys()</h3>
<p>Returns the list of all keys of a dictionary.</p>
<pre><code class="lang-python">print(list(harry_info.keys()))
</code></pre>
<p>Output: <code>['name', 'age', 'house', 'friends', 'enemies']</code></p>
<h3 id="values">values()</h3>
<p>Returns the list of all values of a dictionary.</p>
<pre><code class="lang-python">print(list(harry_info.values()))
</code></pre>
<p>Output: <code>['Harry', 17, {'name': 'Gryffindor', 'Animal': 'Lion', 'Element': 'Fire'}, ['Ron', 'Hermione'], ['Voldemort', 'Death Eaters']]</code></p>
<h3 id="popkey-default">pop(key[, default])</h3>
<p>Remove the specified key and return the corresponding value.</p>
<p>If the key is not found, d is returned if given, otherwise KeyError is raised.</p>
<pre><code class="lang-python">print(harry_info.pop(<span class="hljs-string">'enemies'</span>))    <span class="hljs-comment"># enemies will be removed</span>
print(harry_info.pop(<span class="hljs-string">'invalid_key'</span>, <span class="hljs-string">"Invalid Key"</span>))
print(harry_info.pop(<span class="hljs-string">'invalid_key'</span>))
</code></pre>
<p>Output:</p>
<pre><code class="lang-python">[<span class="hljs-string">'Voldemort'</span>, <span class="hljs-string">'Death Eaters'</span>]
Invalid Key
KeyError: <span class="hljs-string">'invalid_key'</span>
</code></pre>
<h3 id="popitem">popitem()</h3>
<p>Remove and return the last (key, value) pair as a tuple, but raise KeyError if dictionary is empty.</p>
<pre><code class="lang-python">print(harry_info.popitem())
</code></pre>
<p>Output: <code>('friends', ['Ron', 'Hermione'])</code></p>
<h3 id="updateiterable">update(iterable)</h3>
<p>Merges a dictionary with another dictionary or with an iterable of key-value pairs.</p>
<p>If the dictionary or iterable passed has the same key as the original dictionary then the value of that key is overridden.</p>
<p><strong>When iterable is a dictionary</strong></p>
<pre><code class="lang-python">d1 = {<span class="hljs-string">'a'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'b'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'c'</span>: <span class="hljs-number">3</span>}
d2 = {<span class="hljs-string">'b'</span>: <span class="hljs-number">200</span>, <span class="hljs-string">'d'</span>: <span class="hljs-number">4</span>}

d1.update(d2)

print(d1)
</code></pre>
<p>Output: <code>{'a': 1, 'b': 200, 'c': 3, 'd': 4}</code></p>
<p>Notice how 'b' is updated and 'd' is added.</p>
<p><strong>When iterable is a list of tuples</strong></p>
<pre><code class="lang-python">d1 = {<span class="hljs-string">'a'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'b'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'c'</span>: <span class="hljs-number">3</span>}

d1.update([(<span class="hljs-string">'b'</span>, <span class="hljs-number">200</span>), (<span class="hljs-string">'d'</span>, <span class="hljs-number">4</span>)])

print(d1)
</code></pre>
<p>Output: <code>{'a': 1, 'b': 200, 'c': 3, 'd': 4}</code></p>
<p>We can also provide a keyword arguments to update and the result will be the same:</p>
<pre><code class="lang-python">d1 = {<span class="hljs-string">'a'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'b'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'c'</span>: <span class="hljs-number">3</span>}

d1.update(b=<span class="hljs-number">200</span>, d=<span class="hljs-number">4</span>)

print(d1)
</code></pre>
<p>Output: <code>{'a': 1, 'b': 200, 'c': 3, 'd': 4}</code></p>
<h3 id="fromkeysiterable-valuenone">fromkeys(iterable, value=None)</h3>
<p>Create a new dictionary with keys from iterable and all values set to value.</p>
<pre><code class="lang-python">keys = (<span class="hljs-string">"key1"</span>, <span class="hljs-string">"key2"</span>, <span class="hljs-string">"key3"</span>)
example_dict = dict.fromkeys(keys, <span class="hljs-string">"default value"</span>)
print(example_dict)
</code></pre>
<p>Output: <code>{'key1': 'default value', 'key2': 'default value', 'key3': 'default value'}</code></p>
<h3 id="setdefaultkey-defaultnone">setdefault(key, default=None)</h3>
<p>Return the value for key if key is in the dictionary, otherwise insert that key with a value of default and return default.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Returns value for 'name'</span>
print(harry_info.setdefault(<span class="hljs-string">"name"</span>))   
<span class="hljs-comment"># Returns value for 'name', default is ignored</span>
print(harry_info.setdefault(<span class="hljs-string">"name"</span>, <span class="hljs-string">"Harry Potter"</span>))
<span class="hljs-comment"># Adds key 'last_name' and return its value 'Potter'</span>
print(harry_info.setdefault(<span class="hljs-string">"last_name"</span>, <span class="hljs-string">"Potter"</span>))
</code></pre>
<p> Output:</p>
<pre><code class="lang-python">Harry
Harry
Potter
</code></pre>
<h3 id="copy">copy()</h3>
<p>Performs a shallow copy of the dictionary.</p>
<pre><code class="lang-python">harry_copy = harry_info.copy()
print(harry_copy)
</code></pre>
<p><strong>Shallow copy vs deep copy</strong></p>
<p>With a shallow copy if the original dictionary contains mutable values they won't be copied, therefore changing the copied dictionary will change the original one.</p>
<p>We can use <em>copy.deepcopy</em> method to perform a deepcopy as shown below:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> copy <span class="hljs-keyword">import</span> deepcopy

d = {
    <span class="hljs-string">'number'</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">'list'</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
}

d_shallow = d.copy()
d_shallow[<span class="hljs-string">'list'</span>].append(<span class="hljs-number">3</span>)
print(<span class="hljs-string">"shallow copy"</span>, d_shallow)
print(<span class="hljs-string">"original dict"</span>, d)     <span class="hljs-comment"># d is also changed</span>

d_deep = deepcopy(d)
d_deep[<span class="hljs-string">'list'</span>].append(<span class="hljs-number">4</span>)
print(<span class="hljs-string">"deep copy"</span>, d_deep)
print(<span class="hljs-string">"original dict"</span>, d)    <span class="hljs-comment"># d is unchanged</span>
</code></pre>
<p>Output:</p>
<pre><code><span class="hljs-string">shallow</span> <span class="hljs-string">copy</span> {<span class="hljs-attr">'number':</span> <span class="hljs-number">1</span>, <span class="hljs-attr">'list':</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]}
<span class="hljs-string">original</span> <span class="hljs-string">dict</span> {<span class="hljs-attr">'number':</span> <span class="hljs-number">1</span>, <span class="hljs-attr">'list':</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]}
<span class="hljs-string">deep</span> <span class="hljs-string">copy</span> {<span class="hljs-attr">'number':</span> <span class="hljs-number">1</span>, <span class="hljs-attr">'list':</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]}
<span class="hljs-string">original</span> <span class="hljs-string">dict</span> {<span class="hljs-attr">'number':</span> <span class="hljs-number">1</span>, <span class="hljs-attr">'list':</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]}
</code></pre><h3 id="clear">clear()</h3>
<p>Remove all items from a dictionary</p>
<pre><code class="lang-python">harry_info.clear()
print(harry_info)
</code></pre>
<p>Output: <code>{}</code></p>
<blockquote>
<p>Highlights:</p>
<ul>
<li>Dictionary provides several methods to access, update, remove, and copy key-value pairs.</li>
</ul>
</blockquote>
<h1 id="dict-comprehension">Dict Comprehension</h1>
<p>You may be familiar with list comprehensions, it is an alternative to for loop and a concise notation to perform some operations for a collection of elements.</p>
<p>You can also write comprehension for a dictionary using the following syntax:</p>
<p><code>example_dict = {key:value for key, value in iterable}</code></p>
<p>where the iterable is a list of key-value tuples.</p>
<pre><code class="lang-python">d1 = dict((k, v) <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> enumerate(<span class="hljs-string">"Hello"</span>, <span class="hljs-number">1</span>))
print(d1)    <span class="hljs-comment"># {1: 'H', 2: 'e', 3: 'l', 4: 'l', 5: 'o'}</span>
d2 = {k: v <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> enumerate(<span class="hljs-string">"Bye"</span>, <span class="hljs-number">1</span>)}
print(d2)    <span class="hljs-comment"># {1: 'B', 2: 'y', 3: 'e'}</span>
</code></pre>
<p><strong>Enumerate</strong> function returns a key: value pair using the iterable passed to it and the start value.</p>
<p>You can learn more about comprehensions in Python in this article: <a target="_blank" href="https://blog.yuvraj.tech/comprehensions-in-python-explained">Comprehension in Python: Explained</a>.</p>
<blockquote>
<p>Highlights:</p>
<ul>
<li>Use dict comprehension to perform operations on key-value pairs of a dictionary in a concise way.</li>
</ul>
</blockquote>
<h1 id="summary">Summary</h1>
<ul>
<li>Dictionary is a mutable data structure to store key: value pairs.</li>
<li>Define a dictionary using curly braces or dict function.</li>
<li>Access or update values of a dictionary using square brackets.</li>
<li>Dictionary provides built-in methods to add, update, remove, and copy key-value pairs.</li>
<li>Use dict comprehensions to perform operations on dict in a concise way.</li>
</ul>
<h2 id="thanks-for-reading">Thanks for reading.</h2>
<p>If you found this article helpful, please like and share! Feedbacks are welcome in the comments.</p>
<hr />
<p>You may also like:</p>
<ul>
<li><a target="_blank" href="https://blog.yuvraj.tech/the-mutable-default-argument-mess-in-python">The Mutable Default Argument Mess in Python</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/comprehensions-in-python-explained">Comprehensions in Python: Explained</a></li>
<li><a target="_blank" href="https://blog.yuvraj.tech/local-storage-in-javascript">How to Save User's Data Persistently in Web Browser Using Local Storage</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/linux-commands-reference-with-examples">Linux Commands Reference With Examples</a></li>
</ul>
<p>Connect with me on <a target="_blank" href="https://twitter.com/yuvraajsj18">Twitter</a>, <a target="_blank" href="https://github.com/yuvraajsj18">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/yuvraajsj18/">LinkedIn</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to Save User's Data Persistently in Web Browser Using Local Storage]]></title><description><![CDATA[In this article, we will learn how to use Local Storage to save data persistently in the browser using Local Storage.
Prerequisite
You will just need familiarity with basic JavaScript and HTML.
The best way to go through the article is to open your c...]]></description><link>https://blog.yuvraj.tech/local-storage-in-javascript</link><guid isPermaLink="true">https://blog.yuvraj.tech/local-storage-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[ES6]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Wed, 20 Oct 2021 09:10:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634720911715/j1hi4FRCo.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we will learn how to use Local Storage to save data persistently in the browser using Local Storage.</p>
<h3 id="prerequisite">Prerequisite</h3>
<p>You will just need familiarity with basic JavaScript and HTML.</p>
<p>The best way to go through the article is to open your code editor and code along with me.</p>
<p>So, let's start!</p>
<h1 id="what-is-local-storage">What is Local Storage?</h1>
<p><em>LocalStorage</em> is a property of <em>windows</em> object, it allows us to store key-value pairs in a web browser.</p>
<p>The localStorage's data has no expiration date. </p>
<p>The data will not be deleted when the browser is closed and will be available whenever you open the same web page.</p>
<p>Each Protocol-Domain combination will have different local storage, which means, <code>[http://example.com](http://example.com)</code> and <code>[https://example.com](https://example.com)</code> will not share their local storage property.</p>
<h2 id="why-use-local-storage">Why use Local Storage?</h2>
<p>LocalStorage is generally used to save a user's preferences, theme settings, login information, auth tokens. You can store any kind of information you want.</p>
<h1 id="using-local-storage">Using Local Storage</h1>
<p>Let's start by creating a simple web page with a button and a heading 💻</p>
<pre><code class="lang-jsx">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;Local Storage&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;button id="count-btn"&gt;Count&lt;/button&gt;
    &lt;h1 id="clicks-count"&gt;0&lt;/h1&gt;

    &lt;script src="main.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>We have given both <code>button</code> and <code>h1</code> tags an id to access them in the JavaScript <em>**</em>file.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634715001482/GlKC7N_Rv.png" alt="image.png" /></p>
<p>This is how our web page looks, we want to increase the number by 1 each time the <strong>Count</strong> button is pressed.</p>
<p>Let's create a JavaScript file <em>main.js</em> and the following code **to implement this behavior:</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#count-btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> countElement = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#clicks-count'</span>);
    <span class="hljs-keyword">const</span> count = <span class="hljs-built_in">Number</span>(countElement.innerText) + <span class="hljs-number">1</span>;
    <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#count-btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> countElement = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#clicks-count'</span>);
    <span class="hljs-keyword">const</span> count = <span class="hljs-built_in">Number</span>(countElement.innerText) + <span class="hljs-number">1</span>;
    <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'count'</span>, count);
    countElement.innerText = count;
});
    countElement.innerText = count;
});
</code></pre>
<p>We added an event listener for the <strong>click</strong> action on the button, whenever the button is clicked we access the value of <strong>h1</strong>, increment it by 1, and then update the <strong>h1</strong> again.</p>
<p>Now, the page is behaving the way we want:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634715050804/wz8eVIRNE.png" alt="image.png" /></p>
<p>But there's a problem! Try refreshing the page and the count resets to 0.</p>
<p>Now we will use local storage to save this count so that we start from the same number we reached before refreshing or closing the browser.</p>
<p><strong>Setting count in LocalStorage</strong></p>
<p>Use the <code>localStorage.setItem(key, value);</code> in the event listener we created before:</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#count-btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> countElement = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#clicks-count'</span>);
    <span class="hljs-keyword">const</span> count = <span class="hljs-built_in">Number</span>(countElement.innerText) + <span class="hljs-number">1</span>;
    <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'count'</span>, count);
    countElement.innerText = count;
});
</code></pre>
<p>This will set a key <code>count</code> in the local storage and update it each time we press the button.</p>
<p>You can check it by opening the inspect element (Control+Shift+I on windows, Command + Shift + I on mac) and going into the application tab, and selecting Local Storage from the left menu:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634715073540/CNRMESjl-.png" alt="image.png" /></p>
<p>Try refreshing the page again, it still starts from 0, that's because we have saved the value but we also need to set the previous value of count to the initial value when the page loads:</p>
<p>We will use the <code>localStorage.getItem(key);</code> to access a value of a key from localStorage.</p>
<p>Edit the <em>main.js</em> to use <code>getItem</code> function:</p>
<pre><code class="lang-jsx"><span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#clicks-count'</span>).innerText = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'count'</span>) ?? <span class="hljs-number">0</span>;

<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#count-btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> countElement = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#clicks-count'</span>);
    <span class="hljs-keyword">const</span> count = <span class="hljs-built_in">Number</span>(countElement.innerText) + <span class="hljs-number">1</span>;
    <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'count'</span>, count);
    countElement.innerText = count;
});
</code></pre>
<p>The first line checks if a key 'count' exists in the local storage, if true it sets the heading to that number otherwise it set it to 0.</p>
<p>You could also have used an <code>if</code> condition for this but here we are using the more succinct <code>??</code> operator.</p>
<p><code>??</code> - The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator">nullish coalescing operator (??)</a> is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined and otherwise returns its left-hand side operand.</p>
<p>And with this, we are done with our web page. Try refreshing or closing the browser and the count will still start from the last value.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634715091682/8gfEysWyn.png" alt="image.png" /></p>
<h1 id="local-storage-methods-summary">Local Storage Methods Summary</h1>
<ul>
<li><p><strong><code>localStorage.setItem(key, value);</code></strong></p>
<p>  Adds a key and value pair to local storage.</p>
</li>
<li><p><code>**const cat = localStorage.getItem(key);**</code></p>
<p>  Gets a value for a key from the local storage.</p>
</li>
<li><p><code>**localStorage.removeItem(key);**</code></p>
<p>  Deletes a key-value pair from the local storage.</p>
</li>
<li><p><strong><code>localStorage.clear();</code></strong></p>
<p>  Deletes all key-value pairs from the local storage.</p>
</li>
</ul>
<h1 id="conclusion">Conclusion</h1>
<p>Now that you know how to use localStorage, try using it in your next project.</p>
<p>Here are a few project ideas for beginners to try out localStorage:</p>
<ul>
<li>Todo App</li>
<li>Notes App</li>
<li>Shopping List App</li>
</ul>
<p>Note: Just because you can store any information in local storage doesn't mean you should. Never store sensitive data in local storage as any third party js code would be able to access it, increasing the security risk. (Thanks to <a target="_blank" href="https://hashnode.com/@apoorvtyagi">@apoorvtyagi</a> for questioning about the security of local storage)</p>
<p>I hope you found this article helpful! Thanks for reading.</p>
]]></content:encoded></item><item><title><![CDATA[Create Your Own API Using Python's FastAPI Web Framework]]></title><description><![CDATA[Note: This is an article I wrote in 2021 and never published for three years. Some part of it might not work today but it still is helpful for anyone looking to go from knowing just the fundamentals of Python to building an end-to-end API in fastAPI....]]></description><link>https://blog.yuvraj.tech/create-your-own-api-using-pythons-fastapi-web-framework</link><guid isPermaLink="true">https://blog.yuvraj.tech/create-your-own-api-using-pythons-fastapi-web-framework</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[FastAPI]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 01 Oct 2021 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/B311mBDkZbo/upload/94e2b86b3305410391f97963976506a4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Note: This is an article I wrote in 2021 and never published for three years. Some part of it might not work today but it still is helpful for anyone looking to go from knowing just the fundamentals of Python to building an end-to-end API in fastAPI.</p>
</blockquote>
<h1 id="heading-introduction">Introduction</h1>
<p>Hey Everyone! In this article, we will go through all the features of FastAPI needed to build an API for a Todo App. We will perform CRUD(create-read-update-delete) operations, add a database and authentication to our API.</p>
<p>We will start by understanding a few prerequisites for the FastAPI app, then we will go through a hello world app for FastAPI and learn its fundamentals, and then finally end by building a todo app with FastAPI.</p>
<blockquote>
<p>The only prerequisite to this article is to have experience coding in Python.</p>
</blockquote>
<p>The best way to go through the article is to open your code editor and code along with me. (Don't copy-paste)</p>
<p>So let us start!</p>
<h1 id="heading-what-is-fastapi">What is FastAPI?</h1>
<p>FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.6+.</p>
<p>But wait, <strong>what is an API?</strong> (feel free to skip if you already know)</p>
<p>API stands for <em>Application programming interface,</em> it is a set of functions that performs a task and can be used by other developers to build their own software without caring about the implementation detail of the API.</p>
<p>One of the most famous analogies of an API is to think of an API as a waiter in a restaurant, when you go to a restaurant a waiter takes your order, delivers it to the kitchen, and then delivers the food.</p>
<p>You may watch this 3 minutes video that explains API in a precise way:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/s7wmiS2mSXY">https://youtu.be/s7wmiS2mSXY</a></div>
<p> </p>
<h1 id="heading-why-use-fastapi-to-build-apis">Why use FastAPI to build APIs?</h1>
<p>The answer is simple: FastAPI is awesome!</p>
<ul>
<li><p>It is <strong>Fast:</strong> FastAPI is a high-performance web framework, on par with NodeJS and Go.</p>
</li>
<li><p>It is <strong>Fast to code:</strong> Increase the speed to develop features by about 200% to 300%.</p>
</li>
<li><p>It is <strong>Intuitive:</strong> Great editor support. Completion everywhere. Less time debugging.</p>
</li>
<li><p>It is <strong>Easy:</strong> Easy to use and learn.</p>
</li>
<li><p>It is <strong>Short:</strong> Minimize code duplication.</p>
</li>
<li><p>It is <strong>Robust:</strong> Get production-ready code. With automatic interactive documentation.</p>
</li>
<li><p>It is <strong>Standard-bases:</strong> Based on (and fully compatible with) the open standards for APIs.</p>
</li>
</ul>
<p>FastAPI uses some of the best libraries available in the Python community to achieve the above features:</p>
<ol>
<li><p><strong>Pydantic:</strong> For data validation, serialization, and documentation.</p>
</li>
<li><p><strong>Starlette:</strong> Starlette is a lightweight ASGI web framework/toolkit.</p>
</li>
<li><p><strong>Uvicorn:</strong> Uvicorn is a lightning-fast ASGI server.</p>
</li>
</ol>
<p>Don't worry if don't understand a few terms here, we will go through all this as needed.</p>
<h1 id="heading-python-type-hints">Python Type Hints</h1>
<p>Before starting development with FastAPI, we also need to make sure we are comfortable using types in Python.</p>
<p>(Feel free to skip this section if you are already familiar with type hints in Python)</p>
<p><em>Type hints are a special syntax that allows declaring the type of a variable.</em></p>
<p>Editors and tools use these types of hints to provide better support like <em>auto-completion</em> and <em>error checks</em>.</p>
<p>FastAPI is based on these types hints and uses them to provide:</p>
<ul>
<li><p>Data validation</p>
</li>
<li><p>Serialization</p>
</li>
<li><p>Documentation support.</p>
</li>
</ul>
<h2 id="heading-using-type-hints">Using type hints</h2>
<p>Type hints are declared using a <code>:</code> after the variable name, see the following example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">num1: int, num2: int</span>):</span>
    <span class="hljs-keyword">return</span> num1 + num2
</code></pre>
<p>You can also use any standard python types: <code>int</code>, <code>float</code>, <code>str</code>, <code>bool</code>, <code>bytes</code></p>
<h2 id="heading-using-the-typing-module">Using the typing module</h2>
<p>For data structures that can contain other values, like <code>dict</code>, <code>list</code>, <code>set</code>, <code>tuple</code> you can use the standard python module <code>typing</code>. These types are called <strong>generic types.</strong></p>
<p>Here's an example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_items</span>(<span class="hljs-params">items: List[str]</span>):</span>
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> items:
        print(item)
</code></pre>
<p><code>List[str]</code>: The type of the values that a list can contain is given in square brackets <code>[]</code>. It is called the type parameter.</p>
<p>That means: "the variable <code>items</code> is a list, and each of the items in this list is an <code>str</code>".</p>
<p><strong>Tuple and Set:</strong> For declaring the type of tuples and sets:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Set, Tuple

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_items</span>(<span class="hljs-params">items_t: Tuple[int, int, str], items_s: Set[bytes]</span>):</span>
    <span class="hljs-keyword">return</span> items_t, items_s
</code></pre>
<p>This means:</p>
<ul>
<li><p>The variable <code>items_t</code> is a <code>tuple</code> with 3 items, an <code>int</code>, another <code>int</code>, and <code>str</code>.</p>
<p>  If you want to declare a tuple with variable length and homogeneous type, you can use literal ellipsis: <code>Tuple[int, ...]</code>.</p>
<p>  If you want to declare a plain tuple: <code>Tuple[Any, ...]</code>.</p>
</li>
<li><p>The variable <code>items_s</code> is a <code>set</code>, and each of its items is of type <code>bytes</code>.</p>
</li>
</ul>
<p><strong>Dicts:</strong></p>
<p>To define a dict, you pass 2 type parameters, separated by commas.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Dict

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_items</span>(<span class="hljs-params">prices: Dict[str, float]</span>):</span>
    <span class="hljs-keyword">for</span> item_name, item_price <span class="hljs-keyword">in</span> prices.items():
        print(item_name)
        print(item_price)
</code></pre>
<p>This means:</p>
<ul>
<li><p>The variable <code>prices</code> is a <code>dict</code>:</p>
<ul>
<li><p>The keys of this <code>dict</code> are of type <code>str</code>.</p>
</li>
<li><p>The values of this <code>dict</code> are of type <code>float</code>.</p>
</li>
</ul>
</li>
</ul>
<p><strong>Optional</strong></p>
<p>You can also use <code>Optional</code> to declare that a variable has a type, like <code>str</code>, but that it is "optional", which means that it could also be <code>None</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">say_hi</span>(<span class="hljs-params">name: Optional[str] = None</span>):</span>
    <span class="hljs-keyword">if</span> name <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        print(<span class="hljs-string">f"Hey <span class="hljs-subst">{name}</span>!"</span>)
    <span class="hljs-keyword">else</span>:
        print(<span class="hljs-string">"Hello, World!"</span>)
</code></pre>
<p>Using <code>Optional[str]</code> instead of just <code>str</code> will let the editor help you detecting errors where you could be assuming that a value is always <code>str</code> when it could actually be <code>None</code> too.</p>
<p><strong>Union</strong></p>
<p>Union types allow combining types: <code>Union[int, str]</code> means either <code>int</code> or <code>str</code>.</p>
<p><strong>Literal</strong></p>
<p>Literal types can be used to indicate that the corresponding variable can have one of the provided literal value: <code>MODE = Literal['r', 'rb', 'w', 'wb']</code>.</p>
<h2 id="heading-using-classes-as-type-hints">Using classes as type hints</h2>
<p>You can also declare a class as the type of a variable.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, name: str</span>):</span>
        self.name = name

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_person_name</span>(<span class="hljs-params">a_person: Person</span>):</span>
    <span class="hljs-keyword">return</span> a_person.name
</code></pre>
<h3 id="heading-note">Note 📝</h3>
<p>Since Python 3.9 you can use built-in collection types such as <code>list</code> and <code>dict</code> as generic types instead of importing the corresponding types (ex. <code>List</code> and <code>Dict</code>) from <code>typing</code> module.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet_all</span>(<span class="hljs-params">names: list[str]</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> names:
        print(<span class="hljs-string">"Hello"</span>, name)
<span class="hljs-comment"># The -&gt; indicate return type although it can be inferred automatically</span>
</code></pre>
<h3 id="heading-tip">Tip 💡</h3>
<p>Install the <code>mypy</code> library to get error checks when using type hints.</p>
<p>Install <code>$ python3 -m pip install mypy</code>.</p>
<p>Setup in VS Code: Open the command palette (<code>Ctrl+Shift+P</code>) and select the Python: Select Linter command and choose <strong>mypy</strong>. Also, make sure you have the pylance and the python extension installed in your vs code for the best experience.</p>
<h1 id="heading-hello-world-with-fastapi">Hello World with FastAPI</h1>
<p>Now, we will create a Hello World app in FastAPI and then discuss a few fundamental features.</p>
<p>Let's start by creating a new project folder:</p>
<pre><code class="lang-bash">$ mkdir hello
$ <span class="hljs-built_in">cd</span> hello
$ touch __init__.py <span class="hljs-comment"># this will create an __init__.py file to make this folder a package</span>
</code></pre>
<p>Now, create a virtual environment and activate it:</p>
<pre><code class="lang-bash">$ python3 -m venv env
$ <span class="hljs-built_in">source</span> env/bin/activate
</code></pre>
<p>Time to <strong>Install</strong> FastAPI:</p>
<pre><code class="lang-bash">$ pip install fastapi[all]
</code></pre>
<h2 id="heading-hello-world">Hello, World!</h2>
<p>Now, create a file <code>[main.py](http://main.py)</code> in the current directory and type the following into it, don't worry we will go over each line.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 1</span>

<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()

<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello, World!"</span>}
</code></pre>
<ul>
<li><p><code>from fastapi import FastAPI</code></p>
<p>  We are importing the <code>FastAPI</code> class from the <code>fastapi</code> module, it will provide all the functionality for our API, and make our app a FastAPI app.</p>
</li>
<li><p><code>app = FastAPI()</code></p>
<p>  This creates an instance of the <code>FastAPI</code> class. We will also refer to this instance when running our API using a server. Also, you can name it anything instead of the <code>app</code>.</p>
</li>
<li><p><code>@app.get("/")</code></p>
<p>  This line creates a <strong>path operation</strong> using a <strong>decorator.</strong></p>
<p>  A <strong>Path</strong> refers to the last part of the URL starting from the first <code>/</code>.</p>
<p>  So, in a URL like: <code>[https://example.com/items/foo](https://example.com/items/foo)</code>, the path would be <code>/items/foo</code>.</p>
<p>  An <strong>operation</strong> refers to one of the HTTP methods:</p>
<ul>
<li><p><code>POST</code>: to create data</p>
</li>
<li><p><code>GET</code>: to read data</p>
</li>
<li><p><code>PUT</code>: to update data</p>
</li>
<li><p><code>DELETE</code>: to delete data</p>
</li>
<li><p>and more...</p>
</li>
</ul>
</li>
</ul>
<p>    You can communicate to each path using one (or more) of these "methods" in the HTTP protocol.</p>
<p>    So, the <code>@app.get("/")</code> decorator (a "decorator" takes the function below and does something with it) tells FastAPI that the function right below is in charge of handling requests that go to:</p>
<ul>
<li><p>The path <code>/</code>.</p>
</li>
<li><p>Using a <code>get</code> operation.</p>
</li>
</ul>
<p>    You can also use the other operations:</p>
<ul>
<li><p><code>@app.post()</code></p>
</li>
<li><p><code>@app.put()</code></p>
</li>
<li><p><code>@app.delete()</code></p>
</li>
</ul>
<ul>
<li><p>The <code>hello()</code> function</p>
<p>  This is a <strong>path operation function,</strong> it is called by FastAPI whenever it receives a request to the URL <code>/</code> using a <code>GET</code> operation. You can use a normal function or an <code>async</code> function.</p>
<p>  This function is <strong>returning</strong> a python dictionary which will be automatically converted to a JSON object by FastAPI.</p>
<ul>
<li><p>JSON stands for <strong>JavaScript Object Notation</strong>.</p>
</li>
<li><p>It is a lightweight format for storing and transporting data.</p>
</li>
<li><p>JSON is often used when data is sent from a server to a web page.</p>
</li>
<li><p>JSON is very similar to a Python dictionary, so if you haven't ever used JSON then don't worry just think of it as a slightly different representation of a python dictionary.</p>
</li>
</ul>
</li>
</ul>
<p>    You can also return other data types like <code>list</code>, <code>str</code>, <code>int</code>, etc.</p>
<h2 id="heading-running-a-fastapi-app">Running a FastAPI app</h2>
<p>Let's run the above hello world app, open your terminal and type the following command:</p>
<pre><code class="lang-bash">$ uvicorn main:app --reload
</code></pre>
<p>This will start our app on <code>[localhost:8000](http://localhost:8000)</code>.</p>
<p><code>main</code> refers to our Python module and <code>app</code> refers to the FastAPI instance we created.</p>
<p><code>--reload</code> is used to restart the server after code changes. Only use for development.</p>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled.png" /></p>
<h2 id="heading-the-autogenerated-docs">The Autogenerated Docs</h2>
<p>FastAPI provides automatic documentation, go to <code>[localhost:8000/docs](http://localhost:8000/docs)</code> and you will be able to see all the path operations and try them out.</p>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%201.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%201.png" /></p>
<h1 id="heading-fastapi-fundamentals">FastAPI Fundamentals</h1>
<p>Now, we will create more path operations in the same hello world app and understand a few important concepts in FastAPI like <strong>path parameters, query parameters, request body, using Pydantic models, response models, and dependencies.</strong></p>
<p>We will learn about <strong>Routers, Databases, and Security</strong> while creating the Todo API in the next Section.</p>
<h3 id="heading-path-parameters"><strong>Path Parameters</strong></h3>
<p>Path parameters are the variable parts of the URL path.</p>
<p>In <code>[https://twitter.com/yuvraajsj18](https://twitter.com/yuvraajsj18)</code>, <code>yuvraajsj18</code> is a path parameter. You can insert any other value: <code>https://twitter.com/{username}</code>.</p>
<p>Let's create our own path with a path parameter:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 2</span>

<span class="hljs-comment"># ... code from snippet 1</span>

items = [
    {
        <span class="hljs-string">"item_id"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"Item 1"</span>,
        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Description for item 1"</span>,
        <span class="hljs-string">"price"</span>: <span class="hljs-number">50.25</span>,
    },
    {
        <span class="hljs-string">"item_id"</span>: <span class="hljs-number">1</span>,
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"Item 2"</span>,
        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Description for item 2"</span>,
        <span class="hljs-string">"price"</span>: <span class="hljs-number">20.00</span>,
        <span class="hljs-string">"tax"</span>: <span class="hljs-number">2.0</span>,
    },
    {
        <span class="hljs-string">"item_id"</span>: <span class="hljs-number">2</span>,
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"Item 3"</span>,
        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Description for item 3"</span>,
        <span class="hljs-string">"price"</span>: <span class="hljs-number">30.00</span>,
        <span class="hljs-string">"tax"</span>: <span class="hljs-number">1.5</span>,
    },
]

**@app.get(<span class="hljs-string">"/items/{item_id}"</span>)
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_item</span>(<span class="hljs-params">item_id: int</span>):</span>
    <span class="hljs-keyword">if</span> item_id &lt; len(items):
        <span class="hljs-keyword">return</span> items[item_id]

    <span class="hljs-keyword">return</span> {<span class="hljs-string">"Error"</span>: <span class="hljs-string">f"item_id <span class="hljs-subst">{item_id}</span> not found."</span>}**
</code></pre>
<p>First we have created a <code>items</code> list to mock a database.</p>
<p>Then we are creating a <code>get</code> path operation at <code>items/{item_id}</code>.</p>
<p><code>{item_id}</code> is the placeholder for our path parameter.</p>
<p>Whatever is passed into the URL will be <strong>automatically converted, validated, and saved</strong> into the <code>int</code> variable <code>item_id</code> declared in the function signature: <code>get_item(item_id: int)</code>.</p>
<p>We can then use it in the definition. Here we retrieve the item and return the corresponding item dictionary if it exists otherwise an error message.</p>
<p>Try running this using the <code>uvicorn</code> server and going to the <code>docs</code> path.</p>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%202.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%202.png" /></p>
<p>Also, try passing a <code>string</code> parameter in the URL like <code>[localhost:8000/items/foo](http://localhost:8000/items/foo)</code> instead of <code>int</code>. You will get the following error:</p>
<pre><code class="lang-python">{<span class="hljs-string">"detail"</span>:[{<span class="hljs-string">"loc"</span>:[<span class="hljs-string">"path"</span>,<span class="hljs-string">"item_id"</span>],<span class="hljs-string">"msg"</span>:<span class="hljs-string">"value is not a valid integer"</span>,<span class="hljs-string">"type"</span>:<span class="hljs-string">"type_error.integer"</span>}]}
</code></pre>
<h3 id="heading-query-parameters"><strong>Query Parameters</strong></h3>
<p>Query Parameters are the key-value pairs that are provided after the <code>?</code> and separated by <code>&amp;</code> in the URL.</p>
<p>In the URL: <a target="_blank" href="https://www.google.com/search?q=cats"><code>https://www.google.com/search?q=cats</code></a>, <code>q=cats</code> is a query parameter, it tells google what "query" is to search.</p>
<p>In FastAPI, When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.</p>
<p>Let's continue with our file written above and add a path operation that accepts query parameters.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 3</span>

<span class="hljs-comment"># ... code from snippet 2</span>

<span class="hljs-meta">@app.get("/items/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>(<span class="hljs-params">skip: int = <span class="hljs-number">0</span>, limit: int = <span class="hljs-number">10</span></span>):</span>
    <span class="hljs-keyword">return</span> items[skip : skip + limit]
</code></pre>
<p>Try going to the <code>[localhost:8000/items/?skip=1&amp;limit=3](http://localhost:8000/items/?skip=1&amp;limit=3)</code>, you will get the <code>items[1: 3]</code> that is the following 2 items:</p>
<pre><code class="lang-python">[{<span class="hljs-string">"item_id"</span>:<span class="hljs-number">1</span>,<span class="hljs-string">"name"</span>:<span class="hljs-string">"Item 2"</span>,<span class="hljs-string">"description"</span>:<span class="hljs-string">"Description for item 2"</span>,<span class="hljs-string">"price"</span>:<span class="hljs-number">20.0</span>,<span class="hljs-string">"tax"</span>:<span class="hljs-number">2.0</span>},
{<span class="hljs-string">"item_id"</span>:<span class="hljs-number">2</span>,<span class="hljs-string">"name"</span>:<span class="hljs-string">"Item 3"</span>,<span class="hljs-string">"description"</span>:<span class="hljs-string">"Description for item 3"</span>,<span class="hljs-string">"price"</span>:<span class="hljs-number">30.0</span>,<span class="hljs-string">"tax"</span>:<span class="hljs-number">1.5</span>}]
</code></pre>
<p>FastAPI receives these query parameters from the URL as string, convert to their declared type, <code>int</code> in this case and store them in the corresponding variable.</p>
<p>As query parameters are not a fixed part of a path, they can be optional and can have default values.</p>
<p>In the example above they have default values of <code>skip=0</code> and <code>limit=10</code>. So, going to <code>[localhost:8000/items](http://localhost:8000/items)</code> is same as going to <code>localhost:8000/items/?skip=0&amp;limit=10</code>.</p>
<p>You can also create optional query parameters using <code>None</code>, let's add a <code>greet</code> function to illustrate:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 4</span>
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional
<span class="hljs-comment"># ... code from snippet 3</span>

<span class="hljs-meta">@app.get("/greet")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name: Optional[str]= None</span>):</span>
    <span class="hljs-keyword">if</span> name:
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>"</span>}
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello, Anonymous!"</span>}
</code></pre>
<p>FastAPI will know that <code>name</code> is optional because of the <code>= None</code>.</p>
<p>The <code>Optional</code> in <code>Optional[str]</code> is not used by FastAPI (FastAPI will only use the <code>str</code> part), but the <code>Optional[str]</code> will let your editor help you find errors in your code.</p>
<p>When you want to make a query parameter required, you can just not declare any default value.</p>
<h3 id="heading-request-body"><strong>Request Body</strong></h3>
<p>When you need to send data from a client (let's say, a browser) to your API, you send it as a <strong>request body</strong>.</p>
<p>A <strong>request</strong> body is data sent by the client to your API.</p>
<p>A <strong>response</strong> body is the data your API sends to the client.</p>
<p>Example: When you fill up a sign-up form on a platform, the data is sent to the back-end using the request body.</p>
<p>To declare a request body, we use <strong>Pydanticmodels.</strong></p>
<p>Let's create a path operation that adds a new item to our list of items:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 5</span>

<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-comment"># ... code from snippet 4</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Item</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    description: Optional[str] = <span class="hljs-literal">None</span>
    price: float
    tax: Optional[float] = <span class="hljs-literal">None</span>

<span class="hljs-comment"># To receive request body, you should use one of: </span>
<span class="hljs-comment"># POST (the more common), PUT, DELETE or PATCH.</span>
<span class="hljs-meta">@app.post("/items/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_item</span>(<span class="hljs-params">item: Item</span>):</span>
    items.append({<span class="hljs-string">"item_id"</span>: len(items), **item.dict()})
    <span class="hljs-keyword">return</span> items[<span class="hljs-number">-1</span>]
</code></pre>
<p>The <code>Item</code> class is a pydantic model that defines the <strong>shape</strong> of an item. When an instance of <code>Item</code> is created, the attributes used will be <strong>validated, parsed, and stored</strong> in the instance.</p>
<p>FastAPI will receive the JSON object from the client, and provide us with the corresponding pydantic model instance, in this case, <code>item</code>.</p>
<p>We can define optional attributes by assigning <code>None</code> to them, as done for the <code>description</code> and <code>tax</code>.</p>
<p>We will then use the <code>item</code> instance to append a new item in the items list. <code>**item.dict()</code> is dictionary unpacking syntax in python. It will return the keyword-value pair. We are also adding an <code>item_id</code> and then finally returning the newly created item.</p>
<p><strong>Try Creating an Item using the /docs path:</strong></p>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%203.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%203.png" /></p>
<p>The new item is created but it will not persist once you restart your app, we will use databases in the Todo API section to make data persistent.</p>
<blockquote>
<p>You can use body, path, query parameters together. FastAPI will recognize each of them and take the data from the correct place.</p>
</blockquote>
<p><strong>Adding additional information and validation to parameters</strong></p>
<p>We can use <code>Query</code>, <code>Path</code>, <code>Field</code>, <code>Body</code> to provide an additional string or numeric validation for our parameters.</p>
<p>Let's add <strong>string validation</strong> to the <code>greet</code> function we have written before:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 4 Modified</span>
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Query  <span class="hljs-comment"># import Query</span>
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional

<span class="hljs-meta">@app.get("/greet")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">
    **name: Optional[str] = Query(<span class="hljs-params">None, min_length=<span class="hljs-number">1</span>, title=<span class="hljs-string">"Name"</span>, alias=<span class="hljs-string">"username"</span></span>)**
</span>):</span>
    <span class="hljs-keyword">if</span> name:
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>"</span>}
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello, Anonymous!"</span>}
</code></pre>
<p>The first value to <code>Query</code> provides the <code>default</code> value for the parameter. It is followed by other optional validations:</p>
<ul>
<li><p><code>min_length</code>: <code>int</code>, specifies the minimum length of the parameter value.</p>
</li>
<li><p><code>max_length</code>: <code>int</code>, specifies the maximum length of the parameter value.</p>
</li>
<li><p><code>regex</code>: <code>str</code>, defines a regular expression that the parameter should match.</p>
</li>
<li><p><code>alias</code>: <code>str</code>, provides an alternate path for the operation, now greet can be called with <code>/greet/?username=Yuvraj</code> instead of <code>/greet/?name=Yuvraj</code>.</p>
</li>
<li><p><code>title</code>: <code>str</code>, provides title to the query in the docs, a metadata argument.</p>
</li>
<li><p><code>description</code>: <code>str</code>, describes the query in the docs, a metadata argument.</p>
</li>
<li><p><code>deprecated</code>: <code>bool</code>, specifies whether the parameter is deprecated or not in the docs, a metadata argument.</p>
</li>
</ul>
<p>When you don't want to provide a default value, you can use <code>Query(..., min_length=1)</code>. <code>...</code> is a special python value called ellipsis.</p>
<p>Now, let's add some <strong>numeric validation</strong> to the <code>read_items</code> function written before:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 2 Modified</span>
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, **Path,** Query

<span class="hljs-meta">@app.get("/items/{item_id}")</span>
**<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_item</span>(<span class="hljs-params">item_id: int = Path(<span class="hljs-params">..., ge=<span class="hljs-number">0</span></span>)</span>):</span>**
    <span class="hljs-keyword">if</span> item_id &lt; len(items):
        <span class="hljs-keyword">return</span> items[item_id]

    <span class="hljs-keyword">return</span> {<span class="hljs-string">"Error"</span>: <span class="hljs-string">f"item_id <span class="hljs-subst">{item_id}</span> not found."</span>}
</code></pre>
<p>As a path parameter is always required, the first argument to <code>Path</code> should always be the<code>...</code> It can be followed by the metadata arguments or the numeric validation arguments:</p>
<ul>
<li><p><code>gt</code>: greater than</p>
</li>
<li><p><code>ge</code>: greater than or equal</p>
</li>
<li><p><code>lt</code>: less than</p>
</li>
<li><p><code>le</code>: less than or equal</p>
</li>
</ul>
<p>Both string and numeric validation and metadata arguments can be used with <code>Query</code> and <code>Path</code>.</p>
<p>There also exists <code>Field</code> to add similar validation to a Pydantic model field and <code>Body</code> to add validation when receiving a singular value from the client instead of a dictionary.</p>
<p>Here is the example of both <code>Field</code> and <code>Body</code></p>
<pre><code class="lang-python"><span class="hljs-comment"># Snippet 5 modified</span>

<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> **Body**, FastAPI, **HTTPException** Path, Query
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel, **Field**

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Item</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    description: Optional[str] = Field(<span class="hljs-literal">None</span>, max_length=<span class="hljs-number">300</span>)
    price: float = Field(..., gt=<span class="hljs-number">0</span>, description=<span class="hljs-string">"The price must be greater than zero"</span>)
    tax: Optional[float] = <span class="hljs-literal">None</span>

<span class="hljs-meta">@app.post("/items/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_item</span>(<span class="hljs-params">item: Item</span>):</span>
    items.append({<span class="hljs-string">"item_id"</span>: len(items), **item.dict()})
    <span class="hljs-keyword">return</span> items[<span class="hljs-number">-1</span>]

<span class="hljs-meta">@app.put("/items/{item_id}")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_item</span>(<span class="hljs-params">item_id: int, add_price: float = Body(<span class="hljs-params">...</span>)</span>):</span>
    <span class="hljs-keyword">if</span> item_id &gt;= len(items):
        **<span class="hljs-keyword">raise</span> HTTPException(status_code=<span class="hljs-number">404</span>, detail=<span class="hljs-string">"Item not found"</span>)**

    item = Item(**items[item_id])
    item.price += add_price

    items[item_id] = item.dict()

    <span class="hljs-keyword">return</span> items[item_id]
</code></pre>
<ul>
<li><code>update_item</code> expect a single value for <code>add_price</code>.</li>
</ul>
<h3 id="heading-handling-exceptions">Handling Exceptions</h3>
<p>In the above code, in function <code>update_item</code> we saw the use of <code>HTTPException</code>.</p>
<p>There are many situations where you need to notify an error to a client that is using your API. We can do it with the help of <code>HTTPException</code> class.</p>
<p><code>HTTPException</code> is a normal Python exception with additional data relevant for APIs.</p>
<p>Because it's a Python exception, you don't <code>return</code> it, you <code>raise</code> it.</p>
<p>This also means that if you are inside a utility function that you are calling inside of your <em>path operation function</em>, and you raise the <code>HTTPException</code> from inside of that utility function, it won't run the rest of the code in the <em>path operation function</em>, it will terminate that request right away and send the HTTP error from the <code>HTTPException</code> to the client.</p>
<p>Following are the status codes to specify the response types:</p>
<ol>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#information_responses">Informational responses</a> (<code>100</code>–<code>199</code>)</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses">Successful responses</a> (<code>200</code>–<code>299</code>)</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages">Redirects</a> (<code>300</code>–<code>399</code>)</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses">Client errors</a> (<code>400</code>–<code>499</code>)</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#server_error_responses">Server errors</a> (<code>500</code>–<code>599</code>)</p>
</li>
</ol>
<h3 id="heading-response-model">Response Model</h3>
<p>We can declare the model used for the response with the <code>response_model</code> in any of the path operations.</p>
<p>Let's modify the <code>create_item</code> operation to include a response model:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.post("/items/", response_model=Item)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_item</span>(<span class="hljs-params">item: Item</span>):</span>
    items.append({<span class="hljs-string">"item_id"</span>: len(items), **item.dict()})
    <span class="hljs-keyword">return</span> items[<span class="hljs-number">-1</span>]
</code></pre>
<p>Now go to the <code>/docs</code> and see the response section of the <code>create_item</code>, you will see the Item model instead of the <code>string</code> that was shown before.</p>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%204.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%204.png" /></p>
<p>FastAPI will use this <code>response_model</code> to:</p>
<ul>
<li><p>Convert the output data to its type declaration.</p>
</li>
<li><p>Validate the data.</p>
</li>
<li><p>Add a JSON Schema for the response, in the OpenAPI <em>path operation</em>.</p>
</li>
<li><p>Will be used by the automatic documentation systems.</p>
</li>
<li><p>Will limit the output data to that of the model.</p>
<p>  This means now when you run this operation, the <code>item_id</code> won't be returned anymore. As it is not included in the <code>Item</code> model. You can create multiple models for the request (input) and response (output), we will see this in detail in the Todo API app.</p>
</li>
</ul>
<h3 id="heading-dependencies">Dependencies</h3>
<p>Okay, one last topic before moving on to creating the Todo API with FastAPI and using databases, routers, and authentication.</p>
<p><strong>Dependency injection</strong> means, that there is a way for our code to declare things that it requires to work and use: "dependencies".</p>
<p>FastAPI will take care of doing whatever is needed to provide your code with those needed dependencies.</p>
<p>This is very useful when you need to:</p>
<ul>
<li><p>Have shared logic (the same code logic again and again).</p>
</li>
<li><p>Share database connections.</p>
</li>
<li><p>Enforce security, authentication, role requirements, etc.</p>
</li>
<li><p>And many other things...</p>
</li>
</ul>
<p>All these, while minimizing code repetition.</p>
<p>Let's implement a dependency in our hello app:</p>
<p>Remember we created a <code>read_items</code> function that takes two parameters <code>skip</code> and <code>limit</code>. Now we will do the same for a <code>users</code> list.</p>
<pre><code class="lang-python">users = [
    {
        <span class="hljs-string">"id"</span>: <span class="hljs-number">0</span>,
        <span class="hljs-string">"username"</span>: <span class="hljs-string">"user1"</span>,
        <span class="hljs-string">"hashed_password"</span>: <span class="hljs-string">"somecrypticpassword1"</span>,
    },
    {
        <span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>,
        <span class="hljs-string">"username"</span>: <span class="hljs-string">"user2"</span>,
        <span class="hljs-string">"hashed_password"</span>: <span class="hljs-string">"somecrypticpassword2"</span>,
    },
    {
        <span class="hljs-string">"id"</span>: <span class="hljs-number">2</span>,
        <span class="hljs-string">"username"</span>: <span class="hljs-string">"user2"</span>,
        <span class="hljs-string">"hashed_password"</span>: <span class="hljs-string">"somecrypticpassword2"</span>,
    },
]

<span class="hljs-meta">@app.get("/users/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_users</span>(<span class="hljs-params">skip: int = <span class="hljs-number">0</span>, limit: int = <span class="hljs-number">10</span></span>):</span>
    <span class="hljs-keyword">return</span> users[skip : skip + limit]
</code></pre>
<p>Now we will use a <strong>dependency</strong> to factor out this common parameter.</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">common_parameters</span>(<span class="hljs-params">skip: int = <span class="hljs-number">0</span>, limit: int = <span class="hljs-number">10</span></span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"skip"</span>: skip, <span class="hljs-string">"limit"</span>: limit}
</code></pre>
<p>See, a dependency is just a function. Here it is taking the same parameter as the path functions.</p>
<p>Now we will use this in our path functions:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> Body, **Depends**, FastAPI, HTTPException, Path, Query

<span class="hljs-meta">@app.get("/items/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>(<span class="hljs-params">commons: dict = Depends(<span class="hljs-params">common_parameters</span>)</span>):</span>
    <span class="hljs-keyword">return</span> items[commons[<span class="hljs-string">"skip"</span>] : commons[<span class="hljs-string">"skip"</span>] + commons[<span class="hljs-string">"limit"</span>]]

<span class="hljs-meta">@app.get("/users/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_users</span>(<span class="hljs-params">commons: dict = Depends(<span class="hljs-params">common_parameters</span>)</span>):</span>
    <span class="hljs-keyword">return</span> users[commons[<span class="hljs-string">"skip"</span>] : commons[<span class="hljs-string">"skip"</span>] + commons[<span class="hljs-string">"limit"</span>]]
</code></pre>
<p>Whenever a new request arrives, <strong>FastAPI</strong> will take care of:</p>
<ul>
<li><p>Calling your dependency ("dependable") function with the correct parameters.</p>
</li>
<li><p>Get the result from your function.</p>
</li>
<li><p>Assign that result to the parameter in your <em>path operation function</em>.</p>
</li>
</ul>
<p>Try running the app using <code>/docs</code>. It still functions the same way as before.</p>
<p>We can also use <strong>classes</strong> as a dependency:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CommonQueryParams</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, skip: int = <span class="hljs-number">0</span>, limit: int = <span class="hljs-number">10</span></span>):</span>
        self.skip = skip
        self.limit = limit

<span class="hljs-meta">@app.get("/items/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>(<span class="hljs-params">**commons: CommonQueryParams = Depends(<span class="hljs-params">CommonQueryParams</span>)**</span>):</span>
    <span class="hljs-keyword">return</span> items[commons.skip : commons.skip + commons.limit]

<span class="hljs-meta">@app.get("/users/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_users</span>(<span class="hljs-params">**commons: CommonQueryParams = Depends(<span class="hljs-params">CommonQueryParams</span>)**</span>):</span>
    <span class="hljs-keyword">return</span> items[commons.skip : commons.skip + commons.limit]
</code></pre>
<ul>
<li><p>Using classes allows your editor to provide code completion.</p>
</li>
<li><p>You can use the following shortcut to avoid typing the <code>type</code> twice when using class dependency:</p>
<pre><code class="lang-python">  commons: CommonQueryParams = Depends()
</code></pre>
</li>
</ul>
<p>Few things to remember while using dependencies:</p>
<ul>
<li><p>You can create dependencies that have sub-dependencies. This means one dependency can be dependent on another.</p>
</li>
<li><p>If one of your dependencies is declared multiple times for the same path operation, for example, multiple dependencies have a common sub-dependency, FastAPI will know to call that sub-dependency only once per request.</p>
</li>
<li><p>When you don't need the return value of a dependency, you can add a <code>dependencies</code> list in the path operation decorator instead of declaring it in the path operation function.</p>
<pre><code class="lang-python"><span class="hljs-meta">  @app.get("/items/", dependencies=[Depends(dependency1), Depends(dependency2)])</span>
  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>():</span>
      <span class="hljs-keyword">return</span> items
</code></pre>
</li>
<li><p>You can add dependencies to all the path operations by creating <strong>global dependencies</strong> on the <code>app</code>:</p>
<pre><code class="lang-python">  app = FastAPI(dependencies=[Depends(dependency1), Depends(dependency2)])
</code></pre>
</li>
<li><p>You can perform extra steps after finishing the dependency using <code>yield</code> instead of <code>return</code>.</p>
<blockquote>
<p>When the Python <code>yield</code> statement is encountered, the program suspends function execution, saves its state, and returns the yielded value to the caller. Whereas <code>return</code> stops function execution completely.</p>
</blockquote>
<p>  You could use this to create a database session and close it after finishing.</p>
<p>  Only the code before and including the <code>yield</code> statement is executed before sending a response:</p>
<pre><code class="lang-python">  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_db</span>():</span>
      db = DBSession()
      <span class="hljs-keyword">try</span>:
          <span class="hljs-keyword">yield</span> db
      <span class="hljs-keyword">finally</span>:
          db.close()
</code></pre>
<p>  <strong>Note</strong>: you cannot raise an <code>HTTPException</code> after the <code>yield</code> statement as the response has already been sent to the user.</p>
</li>
</ul>
<p>We will now put all of this together and use more features like databases, auth, and routing to create a Todo API.</p>
<h1 id="heading-building-the-todo-api">Building the Todo API</h1>
<p>Let's start by creating a new project:</p>
<pre><code class="lang-bash">$ mkdir todo
$ <span class="hljs-built_in">cd</span> todo
$ touch __init__.py
</code></pre>
<p>Then, create and activate a virtual environment:</p>
<pre><code class="lang-bash">$ python3 -m venv env
$ <span class="hljs-built_in">source</span> env/bin/activate
</code></pre>
<p><strong>Install</strong> FastAPI</p>
<pre><code class="lang-bash">$ pip install fastapi[all]
</code></pre>
<p>Now, before going any further, let's define the requirements of our API.</p>
<h2 id="heading-requirements">Requirements:</h2>
<ol>
<li><p>User registration.</p>
</li>
<li><p>User authentication.</p>
</li>
<li><p>Create a new to-do item.</p>
</li>
<li><p>Delete an existing to-do item.</p>
</li>
<li><p>Mark a to-do item as done/not done.</p>
</li>
<li><p>View all to-do items.</p>
</li>
</ol>
<p>Create a directory structure as follows:</p>
<p><strong>todo</strong> ├── app │ ├── crud</p>
<p>│ ├── db │ ├── models │ ├── routers │ └── schemas └── env</p>
<h2 id="heading-authentication">Authentication</h2>
<p>We will use tools provided by FastAPI to build our authentication system using OAuth2.</p>
<p><strong>OAuth2</strong> is a specification that defines several ways to handle authentication and authorization.</p>
<p>Let's see what are the tools provided by FastAPI for authentication(you don't have to code this yet, we will utilize these tools in Todo API later):</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> Depends, FastAPI
<span class="hljs-keyword">from</span> fastapi. security <span class="hljs-keyword">import</span> OAuth2PasswordBearer

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl=<span class="hljs-string">"token"</span>)

<span class="hljs-meta">@app.get("/items/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>(<span class="hljs-params">token: str = Depends(<span class="hljs-params">oauth2_scheme</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"token"</span>: token}
</code></pre>
<p>When we run this and try out the <code>/items</code> operation we will be required to provide the <code>username</code> and <code>password</code>.</p>
<p>This is the <code>password</code> flow defined in OAuth2. In this flow, the API itself is handling the authentication.</p>
<p>This is how everything works in this flow:</p>
<ul>
<li><p>The user types the <code>username</code> and <code>password</code> in the frontend and hits <code>Enter</code>.</p>
</li>
<li><p>The frontend (running in the user's browser) sends that <code>username</code> and <code>password</code> to a specific URL in our API (declared with <code>tokenUrl="token"</code>).</p>
</li>
<li><p>The API checks that <code>username</code> and <code>password</code>, and responds with a "token" (we haven't implemented any of this yet).</p>
<ul>
<li><p>A "token" is just a string with some content that we can use later to verify this user.</p>
</li>
<li><p>Normally, a token is set to expire after some time.</p>
<ul>
<li><p>So, the user will have to log in again at some point later.</p>
</li>
<li><p>And if the token is stolen, the risk is less. It is not like a permanent key that will work forever (in most cases).</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>The front end stores that token temporarily somewhere.</p>
</li>
<li><p>The user clicks in the frontend to go to another section of the frontend web app.</p>
</li>
<li><p>The front end needs to fetch some more data from the API.</p>
<ul>
<li><p>But it needs authentication for that specific endpoint.</p>
</li>
<li><p>So, to authenticate with our API, it sends a header <code>Authorization</code> with a value of <code>Bearer</code> plus the token.</p>
<p>  (a <code>header</code> is just another part of the request sent by the client. Like the <code>body</code>, as we have seen before).</p>
</li>
<li><p>If the token contains <code>foobar</code>, the content of the <code>Authorization</code> header would be <code>Bearer foobar</code>.</p>
</li>
</ul>
</li>
</ul>
<p><strong>FastAPI's OAuth2PasswordBearer</strong></p>
<pre><code class="lang-python">oauth2_scheme = OAuth2PasswordBearer(tokenUrl=<span class="hljs-string">"token"</span>)
</code></pre>
<p>We are creating an instance <code>oauth2_scheme</code> of the class <code>OAuth2PasswordBearer</code> by passing a URL that will receive the <code>username</code> and <code>password</code>. This parameter doesn't create the path operation, we will do it ourselves later.</p>
<p>The instance <code>oauth2_scheme</code> is a callable, so it can be used with <code>Depends</code>.</p>
<p><strong>Using</strong><code>oauth2_scheme</code></p>
<pre><code class="lang-python"><span class="hljs-meta">@app.get("/items")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>(<span class="hljs-params">**token: str = Depends(<span class="hljs-params">oauth2_scheme</span>)**</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"token"</span>: token}
</code></pre>
<p>This dependency will go and look in the request for that Authorization header, check if the value is Bearer plus some token, and return the token as str that will be assigned to <code>token</code> the path operation function.</p>
<p>If it doesn't see an <code>Authorization</code> header, or the value doesn't have a <code>Bearer</code> token, it will respond with a 401 status code error (<code>UNAUTHORIZED</code>) directly.</p>
<p>You don't even have to check if the token exists to return an error. You can be sure that if your function is executed, it will have <code>str</code> in that token.</p>
<p><strong>Using</strong><code>User</code> Model</p>
<p>Let's make the auth system useful by creating a <code>User</code> model. (Again, you don't have to code this right now, we will be creating a better version for Todo API later).</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">BaseModel</span>):</span>
    username: str
    email: Optional[str] = <span class="hljs-literal">None</span>
    full_name: Optional[str] = <span class="hljs-literal">None</span>
</code></pre>
<p>Let's create a dependency <code>get_current_user</code>:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fake_decode_token</span>(<span class="hljs-params">token: str</span>):</span>
    <span class="hljs-keyword">return</span> User(
            username=token + <span class="hljs-string">"fakedecoded"</span>, email=<span class="hljs-string">"john@example.com"</span>, full_name=<span class="hljs-string">"John Doe"</span>
    )

**<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_current_user</span>(<span class="hljs-params">token: str = Depends(<span class="hljs-params">oauth2_scheme</span>)</span>):</span>**
    user = fake_decode_token(token)
    <span class="hljs-keyword">return</span> user
</code></pre>
<p><code>get_current_user</code> is a dependency that has <code>oauth2_scheme</code> as a sub-dependency. We are also using a fake utility function for now to decode tokens.</p>
<p><strong>Inject the current user</strong></p>
<p>Now, we will use <code>get_current_user</code> dependency in a path operation:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.get("/users/me")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_users_me</span>(<span class="hljs-params">current_user: User = Depends(<span class="hljs-params">get_current_user</span>)</span>):</span>
    <span class="hljs-keyword">return</span> current_user
</code></pre>
<p><strong>Getting the</strong><code>username</code> and <code>password</code> from client:</p>
<p>OAuth2 specifies that when using the "password flow" the client/user must send a <code>username</code> and <code>password</code> fields as <em>form data.</em></p>
<p>The fields should also be named like this, <code>email</code> and <code>password</code> won't work. Although we can show the fields to the final users in the frontend as we wish.</p>
<p>Also, database models can use other names too.</p>
<p><strong>Using</strong><code>OAuth2PasswordRequestForm</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi.security <span class="hljs-keyword">import</span> OAuth2PasswordBearer, **OAuth2PasswordRequestForm**

fake_users_db = {
    <span class="hljs-string">"johndoe"</span>: {
        <span class="hljs-string">"username"</span>: <span class="hljs-string">"johndoe"</span>,
        <span class="hljs-string">"full_name"</span>: <span class="hljs-string">"John Doe"</span>,
        <span class="hljs-string">"email"</span>: <span class="hljs-string">"johndoe@example.com"</span>,
        <span class="hljs-string">"hashed_password"</span>: <span class="hljs-string">"fakehashedsecret"</span>,
    },
    <span class="hljs-string">"alice"</span>: {
        <span class="hljs-string">"username"</span>: <span class="hljs-string">"alice"</span>,
        <span class="hljs-string">"full_name"</span>: <span class="hljs-string">"Alice Wonderson"</span>,
        <span class="hljs-string">"email"</span>: <span class="hljs-string">"alice@example.com"</span>,
        <span class="hljs-string">"hashed_password"</span>: <span class="hljs-string">"fakehashedsecret2"</span>,
    },
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserInDB</span>(<span class="hljs-params">User</span>):</span>  <span class="hljs-comment"># User is same as defined before</span>
    hashed_password: str

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fake_hash_password</span>(<span class="hljs-params">password: str</span>):</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"fakehashed"</span> + password

**@app.post(<span class="hljs-string">"/token"</span>)
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">login</span>(<span class="hljs-params">form_data: OAuth2PasswordRequestForm = Depends(<span class="hljs-params"></span>)</span>):</span>**
    user_dict = fake_user_db.get(form_data.username)

    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user_dict:
        <span class="hljs-keyword">raise</span> HTTPException(status_code=<span class="hljs-number">400</span>, detail=<span class="hljs-string">"Incorrect username or password"</span>)

    user = UserInDB(**user_dict)
    hashed_password = fake_hash_password(form_data.password)

    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> hashed_password == user.hashed_password:
        <span class="hljs-keyword">raise</span> HTTPException(status_code=<span class="hljs-number">400</span>, detail=<span class="hljs-string">"Incorrect username or password"</span>)

    <span class="hljs-keyword">return</span> {<span class="hljs-string">"access_token"</span>: user.username, <span class="hljs-string">"token_type"</span>: <span class="hljs-string">"bearer"</span>}
</code></pre>
<p>The <code>OAuth2PasswordRequestForm</code> is a class dependency that provides us<code>ername</code> and <code>password</code> received as form data.</p>
<p>(Form data in fastAPI is received using <code>Form</code>. It's similar to <code>Body</code> or <code>Query</code>. But instead of <code>application/json</code> encoding it uses <code>application/x-www-form-urlencoded</code> encoding. The <code>&lt;form&gt;&lt;/form&gt;</code> tag in HTML uses this encoding. Although you don't have to worry about this much as FastAPI will provide you with data directly just like it did with the <code>body</code>).</p>
<p>Then, we are getting the user data from the fake database using the <code>username</code> field. If no such user is found we are raising an error.</p>
<p>Now, we put the data in the pydantic model <code>UserInDB</code> and check if the hash of the password field matches the user's hashed password. If the passwords don't match, we raise an error.</p>
<p><strong>Password Hashing</strong></p>
<p>"Hashing" means: converting some content (a password in this case) into a sequence of bytes (just a string) that looks like gibberish.</p>
<p>Whenever you pass the same content (the same password) you get the same gibberish.</p>
<p>But you cannot convert from the gibberish back to the password.</p>
<p><strong>Why use password hashing?</strong></p>
<p>If your database is stolen, the thief won't have your users' plaintext passwords, only the hashes.</p>
<p><strong>Returning the token:</strong></p>
<p>The response of the <code>token</code> endpoint must be a JSON object.</p>
<p>It should have a <code>token_type</code>. In our case, as we are using "Bearer" tokens, the token type should be "<code>bearer</code>".</p>
<p>And it should have an <code>access_token</code>, with a string containing our access token.</p>
<p>In this example, we are returning the <code>username</code> as a token that is not secure, we will implement a secure token in the Todo API.</p>
<p><strong>Update the dependencies</strong></p>
<p>We will handle an exception in the previously written <code>get_current_user</code> dependency:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> Depends, FastAPI, HTTPException, **status**

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>(<span class="hljs-params">db, username: str</span>):</span>
    <span class="hljs-keyword">if</span> username <span class="hljs-keyword">in</span> db:
        user_dict = db[username]
        <span class="hljs-keyword">return</span> UserInDB(**user_dict)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fake_decode_token</span>(<span class="hljs-params">token: str</span>):</span>
    user = get_user(fake_users_db, token)
    <span class="hljs-keyword">return</span> user

**<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_current_user</span>(<span class="hljs-params">token: str = Depends(<span class="hljs-params">oauth2_scheme</span>)</span>):</span>**
    user = fake_decode_token(token)
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=<span class="hljs-string">"Invalid authentication credentials"</span>,
            headers={<span class="hljs-string">"WWW-Authenticate"</span>: <span class="hljs-string">"Bearer"</span>},
        )
    <span class="hljs-keyword">return</span> user
</code></pre>
<p>The additional header <code>WWW-Authenticate</code> with value <code>Bearer</code> we are returning here is also part of the spec.</p>
<p>Any HTTP (error) status code 401 "UNAUTHORIZED" is supposed to also return a <code>WWW-Authenticate</code> header.</p>
<p>This is how you implement an insecure authentication, now we will implement a secure version for our Todo API, get ready to code.</p>
<h2 id="heading-adding-authentication-todo-api">Adding Authentication Todo API</h2>
<p>We will use the password flow with hashing for our Todo API and use <strong>JWT</strong> token instead of insecure usernames.</p>
<p>(You can now code along)</p>
<h3 id="heading-jwt">JWT</h3>
<p>JWT means "JSON Web Tokens". It's a standard to codify a JSON object in a long dense string without spaces.</p>
<p>Example: <code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c</code></p>
<p>It is not encrypted, so, anyone could recover the information from the contents.</p>
<p>But it's signed. So, when you receive a token that you emitted, you can verify that you actually emitted it.</p>
<p>That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know that the user is still logged in to your system.</p>
<p>After a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.</p>
<p><strong>Install</strong><code>python-jose</code> to generate and verify the JWT tokens in Python:</p>
<pre><code class="lang-bash">$ pip install python-jose[cryptography]
</code></pre>
<h3 id="heading-password-hashing">Password Hashing</h3>
<p>Install PassLib to handle password hashes.</p>
<p>It supports many secure hashing algorithms and utilities to work with them. The recommended algorithm is "Bcrypt".</p>
<pre><code class="lang-bash">$ pip install passlib[bcrypt]
</code></pre>
<p>Let's create a file <code>security.py</code> inside the <code>app</code> directory:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> passlib.context <span class="hljs-keyword">import</span> CryptContext

pwd_context = CryptContext(schemes=[<span class="hljs-string">"bcrypt"</span>], deprecated=<span class="hljs-string">"auto"</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">verify_password</span>(<span class="hljs-params">plain_password: str, hashed_password: str</span>):</span>
    <span class="hljs-keyword">return</span> pwd_context.verify(plain_password, hashed_password)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_password_hash</span>(<span class="hljs-params">password: str</span>):</span>
    <span class="hljs-keyword">return</span> pwd_context.hash(password)
</code></pre>
<p>We are creating a PassLib "context" that we will use to hash and verify passwords.</p>
<h3 id="heading-handle-jwt-tokens">Handle JWT tokens</h3>
<p>As told before, we are required to send an access token and token type as a response from the <code>/token</code> endpoint. That's why create a file <code>[token.py](http://token.py)</code> inside the <code>schema</code> folder to store the following Pydantic models. <code>Token</code> will be later used in the <code>/token</code> endpoint and <code>TokenData</code> will be used to store the decoded token payload.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Token</span>(<span class="hljs-params">BaseModel</span>):</span>
    access_token: str
    token_type: str

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TokenData</span>(<span class="hljs-params">BaseModel</span>):</span>
    username: Optional[str] = <span class="hljs-literal">None</span>
</code></pre>
<p>Note: Add the following line to <code>__init__.py</code> inside <code>schemas/</code> to simplify imports: <code>from .token import Token, TokenData</code></p>
<p>Now, create a random secret key to sign the JWT tokens, execute the following command in your terminal:</p>
<pre><code class="lang-bash">$ openssl rand -hex 32
</code></pre>
<p>You will get a random key in the output like this:</p>
<pre><code class="lang-bash">939aae726cc09e3338ea836b90b0b0a4dffce9e8ed069ac343754c236244e3d2
</code></pre>
<p>Save this key in an environment variable(don't use this one). You can use a <code>.env</code> file to store it so that you don't have to manually set them every time you start a new shell.</p>
<p>create <code>.env</code> file in <code>app</code> folder:</p>
<pre><code class="lang-plaintext">SECRET_JWT_KEY=939aae726cc09e3338ea836b90b0b0a4dffce9e8ed069ac343754c236244e3d2
</code></pre>
<p>Install the <code>python-dotenv</code> package to import variables from the <code>.env</code> file into the environment: <code>pip install python-dotenv</code>.</p>
<p>Note: if you are using git, make sure to add <code>.env</code> in the <code>.gitignore</code> file as it contains sensitive information.</p>
<p>Let's add functions to handle tokens and authentication in the <code>security.py</code> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime, timedelta
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional

<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> HTTPException, status
<span class="hljs-keyword">from</span> jose <span class="hljs-keyword">import</span> JWTError, jwt

<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> schemas

load_dotenv()  <span class="hljs-comment"># load the variables from .env</span>

SECRET_JWT_TOKEN = str(os.environ[<span class="hljs-string">"SECRET_JWT_KEY"</span>])
ALGORITHM = <span class="hljs-string">"HS256"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_access_token</span>(<span class="hljs-params">data: dict, expires_delta: Optional[timedelta] = None</span>):</span>
    to_encode = data.copy()
    <span class="hljs-keyword">if</span> expires_delta:
        expire = datetime.utcnow() + expires_delta
    <span class="hljs-keyword">else</span>:
        expire = datetime.utcnow() + timedelta(minutes=<span class="hljs-number">15</span>)

    to_encode.update({<span class="hljs-string">"exp"</span>: expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_JWT_TOKEN, algorithm=ALGORITHM)

    <span class="hljs-keyword">return</span> encoded_jwt

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decode_access_token</span>(<span class="hljs-params">token: str</span>):</span>
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail=<span class="hljs-string">"Could not validate credentials"</span>,
        headers={<span class="hljs-string">"WWW-Authenticate"</span>: <span class="hljs-string">"Bearers"</span>},
    )
    <span class="hljs-keyword">try</span>:
        payload = jwt.decode(token, SECRET_JWT_TOKEN, algorithms=[ALGORITHM])
        username: str = payload.get(<span class="hljs-string">"sub"</span>)
        <span class="hljs-keyword">if</span> username <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
            <span class="hljs-keyword">raise</span> credentials_exception
        token_data = schemas.TokenData(username=username)
    <span class="hljs-keyword">except</span> JWTError:
        <span class="hljs-keyword">raise</span> credentials_exception

    <span class="hljs-keyword">return</span> token_data.username
</code></pre>
<p>Here, we are setting the variables for our secret key, algorithm, and expiration for the JWT token.</p>
<p>We are also defining a Pydantic model to use as a response model in the <code>/token</code> endpoint. TokenData model will store the data from the decoded JWT.</p>
<p>Then we finally created a function to generate an access token.</p>
<p>Note: We are using the crud module we haven't created yet, we will implement the CRUD functionality in the database section.</p>
<h3 id="heading-creating-auth-dependencies">Creating auth dependencies</h3>
<p>Create a file <code>[dependency.py](http://dependency.py)</code> in the <code>app</code> directory:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> Depends, HTTPException, status
<span class="hljs-keyword">from</span> fastapi.security <span class="hljs-keyword">import</span> OAuth2PasswordBearer, oauth2
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session

<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> crud
<span class="hljs-keyword">from</span> app.security <span class="hljs-keyword">import</span> decode_access_token

oauth2_scheme = OAuth2PasswordBearer(tokenUrl=<span class="hljs-string">"token"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_current_user</span>(<span class="hljs-params">db: Session = Depends(<span class="hljs-params">get_db</span>), token: str = Depends(<span class="hljs-params">oauth2_scheme</span>)</span>):</span>
    username = decode_access_token(token)
    user = crud.get_user_by_username(db, username)
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=<span class="hljs-string">"Could not validate credentials"</span>,
            headers={<span class="hljs-string">"WWW-Authenticate"</span>: <span class="hljs-string">"Bearer"</span>},
        )

    <span class="hljs-keyword">return</span> user
</code></pre>
<h3 id="heading-token-route">Token Route</h3>
<p>Finally, let's create the endpoint for <code>/token</code> in the <code>[main.py](http://main.py)</code> inside <code>app/</code>:</p>
<p>(The <code>get_db</code> dependency will be created in the database section)</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> timedelta

<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> Depends, FastAPI, HTTPException, status
<span class="hljs-keyword">from</span> fastapi.security <span class="hljs-keyword">import</span> OAuth2PasswordRequestForm
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session

<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> crud, schemas, security
<span class="hljs-keyword">from</span> app.dependency <span class="hljs-keyword">import</span> get_db

app = FastAPI()

<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">root</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"app"</span>: <span class="hljs-string">"Todo API"</span>}

ACCESS_TOKEN_EXPIRE_MINUTES = <span class="hljs-number">30</span>

<span class="hljs-meta">@app.post("/token", response_model=schemas.Token)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">login</span>(<span class="hljs-params">
    db: Session = Depends(<span class="hljs-params">get_db</span>), form_data: OAuth2PasswordRequestForm = Depends(<span class="hljs-params"></span>)
</span>):</span>
    user = crud.authenticate_user(db, form_data.username, form_data.password)

    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=<span class="hljs-string">"Invalid username or password"</span>,
            headers={<span class="hljs-string">"WWW-Authenticate"</span>: <span class="hljs-string">"Bearer"</span>},
        )

    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = security.create_access_token(
        data={<span class="hljs-string">"sub"</span>: user.username}, expires_delta=access_token_expires
    )
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"access_token"</span>: access_token, <span class="hljs-string">"token_type"</span>: <span class="hljs-string">"bearer"</span>}
</code></pre>
<p>Here <code>authenticate_user</code> will be implemented in the next section of CRUD operations. It just checks if the user exists and has the correct password or not and returns a Boolean value.</p>
<p><strong>JWT "subject" sub:</strong> The JWT specification says that there's a key <code>sub</code>, with the subject of the token. It's optional to use it, but that's where you would put the user's identification, so we are using it here.</p>
<p>The "sub" key should have a unique identifier across the entire application, and it should be a string.</p>
<h3 id="heading-adding-endpoints-in-the-user-route">Adding endpoints in the User route</h3>
<p>Create a file <code>[users.py](http://users.py)</code> in the <code>routers</code> folder:</p>
<p>(User schema will be created in the database section)</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> schemas
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> APIRouter
<span class="hljs-keyword">from</span> fastapi.param_functions <span class="hljs-keyword">import</span> Depends
<span class="hljs-keyword">from</span> app.dependency <span class="hljs-keyword">import</span> get_current_user

router = APIRouter(prefix=<span class="hljs-string">"/users"</span>, tags=[<span class="hljs-string">"users"</span>])

<span class="hljs-meta">@router.get("/me", response_model=schemas.User)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_users_me</span>(<span class="hljs-params">current_user: schemas.users.User = Depends(<span class="hljs-params">get_current_user</span>)</span>):</span>
    <span class="hljs-keyword">return</span> current_user
</code></pre>
<p>To organize different path operations, we can use the <code>APIRouter</code>. It's similar to the <code>FastAPI</code> class and supports all the same options like dependencies, tags.</p>
<p>The prefix will be used for all the paths, so <code>/me/</code> will become <code>/users/me/</code>.</p>
<p>We can also add a list of dependencies that will be added to all the path operations in the router and will be executed/solved for each request made to them.</p>
<p>Let's add this router to the <code>[main.py](http://main.py)</code> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.routers <span class="hljs-keyword">import</span> users

app = FastAPI()

app.include_router(users.router)
</code></pre>
<h2 id="heading-database">Database</h2>
<p>We have added the code authentication, but we need a database to store the users and perform operations on it before we can run it.</p>
<p>We will use the SQLite database for this article as Python has integrated support for it, although FastAPI doesn't require you to use a SQL (relational) database. You can use any relational or no SQL database with FastAPI.</p>
<p>(Later, for your production application, you might want to use a database server like PostgreSQL.)</p>
<h3 id="heading-orms"><strong>ORMs</strong></h3>
<p>ORM stands for object-relational mapping, an ORM has tools to convert between <em>objects</em> in code and database <em>tables(relations).</em></p>
<p>With an ORM, we can represent a table in a SQL database using a class. Each attribute of the class represents a column, with a name and a type.</p>
<p>Each instance of the class will represent a row in the table.</p>
<ul>
<li><p>SQL <strong>table</strong> —&gt; ORM <strong>class</strong></p>
</li>
<li><p>SQL <strong>columns</strong> —&gt; ORM <strong>class attribute</strong></p>
</li>
<li><p>SQL <strong>rows</strong> —&gt; ORM <strong>class instances</strong></p>
</li>
</ul>
<p>In this article, we will use <strong>SQLAlchemy ORM.</strong></p>
<p>Install SQLAlchemy by running:</p>
<pre><code class="lang-bash">$ pip install SQLAlchemy
</code></pre>
<h3 id="heading-configuring-sqlalchemy">Configuring SQLAlchemy</h3>
<p>Let's start by configuring SQLAlchemy, create a file <code>[database.py](http://database.py)</code> inside the <code>db</code> folder.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine
<span class="hljs-keyword">from</span> sqlalchemy.ext.declarative <span class="hljs-keyword">import</span> declarative_base
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> sessionmaker

SQLALCHEMY_DATABASE_URL = <span class="hljs-string">"sqlite:///./app/todo_app.db"</span>

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={<span class="hljs-string">"check_same_thread"</span>: <span class="hljs-literal">False</span>}
)

SessionLocal = sessionmaker(autocommit=<span class="hljs-literal">False</span>, autoflush=<span class="hljs-literal">False</span>, bind=engine)

Base = declarative_base()
</code></pre>
<p>We first imported the SQLAlchemy tools and then created a database URL to connect to an SQLite database.</p>
<p>If you want to use a PostgreSQL database, change the URL to:</p>
<pre><code class="lang-python">SQLALCHEMY_DATABASE_URL = <span class="hljs-string">"postgresql://user:password@postgresserver/db"</span>
</code></pre>
<p><strong>SQLAlchemy</strong><code>engine</code></p>
<p>Then we created an engine that is the starting point for any SQLAlchemy application, we will use it later.</p>
<p>Note:</p>
<p>The argument:</p>
<p><code>connect_args={"check_same_thread": False}</code></p>
<p>is needed only for <code>SQLite</code>. It's not needed for other databases.</p>
<p><code>SessionLocal</code> class</p>
<p>Each instance of the <code>SessionLocal</code> class will be a database session. The class itself is not a database session yet.</p>
<p>But once we create an instance of the <code>SessionLocal</code> class, this instance will be the actual database session.</p>
<p><code>Base</code> class</p>
<p>The function <code>declarative_base()</code> returns a class that is used to create each of the database models or classes.</p>
<h3 id="heading-creating-the-database-models-for-user">Creating the database models for User</h3>
<p>The classes used to interact with the databases are called models.</p>
<p>This is different than the previously mentioned Pydantic models which are used for data validation. To avoid confusion we will keep Pydantic models in the <code>schemas</code> folder and database models in the <code>models</code>' folder.</p>
<p>Let's create a file <code>[users.py](http://users.py)</code> inside the <code>models</code>' directory.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.db.database <span class="hljs-keyword">import</span> Base
<span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> Column, Integer, String

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">Base</span>):</span>
    __tablename__ = <span class="hljs-string">"users"</span>
    id = Column(Integer, primary_key=<span class="hljs-literal">True</span>, index=<span class="hljs-literal">True</span>)
    username = Column(String, unique=<span class="hljs-literal">True</span>, nullable=<span class="hljs-literal">False</span>, index=<span class="hljs-literal">True</span>)
    hashed_password = Column(String, nullable=<span class="hljs-literal">False</span>)
</code></pre>
<p>We are using the <code>Base</code> class from <code>[database.py](http://database.py)</code> to create the <code>User</code> model.</p>
<p>The <code>__tablename__</code> attribute tells SQLAlchemy the name of the table to use in the database for each of these models.</p>
<p><strong>Creating model attributes/columns</strong></p>
<p>Then we created the model(class) attributes: <code>id</code>, <code>username</code>, <code>hashed_password</code>.</p>
<p>Each attribute represents a column in the <code>users</code>' table, and the value is given using the <code>Column</code> from SQLAlchemy.</p>
<p>The type of attribute is the first argument in the <code>Column</code>.</p>
<p>Note: Add the following line to <code>__init__.py</code> inside <code>models/</code> to simplify imports: <code>from .users import User</code></p>
<h3 id="heading-creating-the-pydantic-models-for-user"><strong>Creating the Pydantic models for User</strong></h3>
<p>Create a file <code>[users.py](http://users.py)</code> inside the <code>schemas</code> directory:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserBase</span>(<span class="hljs-params">BaseModel</span>):</span>
    username: str

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserCreate</span>(<span class="hljs-params">UserBase</span>):</span>
    password: str

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">UserBase</span>):</span>
    id: int

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span>:</span>
        orm_mode = <span class="hljs-literal">True</span>
</code></pre>
<p>We have created three pydantic models, for the creation (<code>UserCreate</code>), reading(<code>User</code>), and one base(<code>UserBase</code>) that has common attributes.</p>
<p>Password is only required when creating a user and should not be sent in a response.</p>
<p>The reading model <code>User</code> contains an <code>id</code> attribute as we will already know its ID after creation from the database.</p>
<p>The <code>Config</code> class is used to provide configurations to Pydantic. Pydantic's <code>orm_mode</code> will tell the Pydantic model to read the data even if it is not a dict, but an ORM model (or any other arbitrary object with attributes).</p>
<p>This way, instead of only trying to get the <code>id</code> value from a <code>dict</code>, as in:</p>
<p><code>id = data["id"]</code></p>
<p>it will also try to get it from an attribute, as in:</p>
<p><code>id = data.id</code></p>
<p>And with this, the Pydantic <em>model</em> is compatible with ORMs, and you can just declare it in the <code>response_model</code> argument in your <em>path operations</em>.</p>
<p>Note: Add the following line to <code>__init__.py</code> inside <code>schemas/</code> to simplify imports: <code>from .users import User, UserCreate</code></p>
<h3 id="heading-creating-crud-for-user">Creating CRUD for User</h3>
<p>Create a file <code>[users.py](http://users.py)</code> inside the <code>crud</code> folder to define the functions to interact with the database's <code>users</code>' table.</p>
<p>CRUD: Create, Read, Update, and Delete.</p>
<p>For <code>users</code>, we will only implement create and read. Later, for <code>todos</code>, we will implement all four.</p>
<p><strong>Read Users</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> models, schemas
<span class="hljs-keyword">from</span> app.security <span class="hljs-keyword">import</span> get_password_hash, verify_password
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>(<span class="hljs-params">db: Session, user_id: int</span>):</span>
    <span class="hljs-keyword">return</span> db.query(models.User).filter(models.User.id == user_id).first()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user_by_username</span>(<span class="hljs-params">db: Session, username: str</span>):</span>
    <span class="hljs-keyword">return</span> db.query(models.User).filter(models.User.username == username).first()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_users</span>(<span class="hljs-params">db: Session, skip: int = <span class="hljs-number">0</span>, limit: int = <span class="hljs-number">100</span></span>):</span>
    <span class="hljs-keyword">return</span> db.query(models.User).offset(skip).limit(limit).all()
</code></pre>
<p>We imported <code>Session</code> from <code>sqlalchemy.orm</code>, this will allow us to declare the type of the <code>db</code> parameters and have better type checks and completion in your functions.</p>
<p><strong>Create Users</strong></p>
<p>Add the following function to the same file:</p>
<pre><code class="lang-python">  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_user</span>(<span class="hljs-params">db: Session, user: schemas.UserCreate</span>):</span>
    hashed_password = get_password_hash(user.password)
    db_user = models.users.User(username=user.username, hashed_password=hashed_password)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    <span class="hljs-keyword">return</span> db_user
</code></pre>
<ul>
<li><p>Create an SQLAlchemy model <em>instance</em> with your data.</p>
</li>
<li><p><code>add</code> that instance object to your database session.</p>
</li>
<li><p><code>commit</code> the changes to the database (so that they are saved).</p>
</li>
<li><p><code>refresh</code> your instance (so that it contains any new data from the database, like the generated ID).</p>
</li>
</ul>
<p><strong>Authenticate Users</strong></p>
<p>Also, adds the following function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">authenticate_user</span>(<span class="hljs-params">db: Session, username: str, password: str</span>):</span>
    user = get_user_by_username(db, username)
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> verify_password(password, user.hashed_password):
        <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
    <span class="hljs-keyword">return</span> user
</code></pre>
<p>Note: Add the following line to <code>__init__.py</code> inside <code>crud/</code> to simplify imports: <code>from .users import get_user, get_user_by_username, get_users, create_user, authenticate_user</code>.</p>
<h3 id="heading-initializing-the-database-and-setting-migrations-with-alembic">Initializing the database and setting migrations with Alembic</h3>
<p>We have written then needed SQLAlchemy code for the <code>users</code>' table, but we need to convert it into a real database, for this, we use a migration tool.</p>
<p>A "migration" is the set of steps needed whenever we change the structure of our SQLAlchemy models, add a new attribute, etc. to replicate those changes in the database, add a new column, a new table, etc.</p>
<p>We will use <strong>Alembic</strong> for this purpose.</p>
<p>We will cover the necessary parts of alembic in this article. You can learn more in the <a target="_blank" href="https://alembic.sqlalchemy.org/en/latest/tutorial.html#">alembic docs</a>.</p>
<p><strong>Install alembic</strong></p>
<pre><code class="lang-bash">$ pip install alembic
</code></pre>
<p><strong>Create Migrations Environment</strong></p>
<p>Run the following command inside the <code>todo</code> directory:</p>
<pre><code class="lang-bash">$ alembic init alembic
</code></pre>
<p>This will create a migration environment for us.</p>
<p>A migration environment is a directory of scripts:</p>
<pre><code class="lang-plaintext">todo/
    alembic/
        env.py
        README
        script.py.mako
        versions/
</code></pre>
<ul>
<li><p><code>alembic/</code>: home of the migration environment.</p>
</li>
<li><p><code>env.py</code>: a Python script that is run whenever the alembic migration tool is invoked. It configures and generates an SQLAlchemy engine.</p>
</li>
<li><p><code>script.py.mako</code>: a Mako template file to generate new migration scripts inside <code>versions</code>.</p>
</li>
<li><p><code>versions/</code>: This directory holds the individual version scripts.</p>
</li>
</ul>
<p><strong>Configure</strong><code>alembic.ini</code></p>
<p>Alembic created a file <code>alembic.ini</code> in the <code>todo</code> folder. This is a file that the alembic script looks for when invoked.</p>
<p>Edit the following line:</p>
<pre><code class="lang-python">sqlalchemy.url = driver://user:<span class="hljs-keyword">pass</span>@localhost/dbname
</code></pre>
<p>to:</p>
<pre><code class="lang-python">sqlalchemy.url = sqlite:///./app/todo_app.db
</code></pre>
<p><strong>Creating migrations scripts</strong></p>
<p>We can create migration scripts either manually or automatically, here we will use the automatic approach and manually edit the scripts if required.</p>
<p>Alembic can view the status of the database and compare it against the table metadata in the application, generating the “obvious” migrations based on a comparison.</p>
<p>Create a file <em>base.py</em> to contain all the models for alembic to see:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Import all the models, so that Base has them before being</span>
<span class="hljs-comment"># imported by Alembic</span>
from app.db.database import Base
from app.models.users import User
</code></pre>
<p>Open the <code>[env.py](http://env.py)</code> file inside the <code>alembic</code> folder and make the following changes to <code>target_metadata = None</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.db.base <span class="hljs-keyword">import</span> Base

target_metadata = Base.metadata
</code></pre>
<p>Also, make sure the <code>run_migrations_online()</code> function is same as follows:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run_migrations_online</span>():</span>
    connectable = engine_from_config(
        config.get_section(config.config_ini_section),
        prefix=<span class="hljs-string">"sqlalchemy."</span>,
        poolclass=pool.NullPool,
    )

    <span class="hljs-keyword">with</span> connectable.connect() <span class="hljs-keyword">as</span> connection:
        context.configure(
            connection=connection, target_metadata=target_metadata
        )

        <span class="hljs-keyword">with</span> context.begin_transaction():
            context.run_migrations()
</code></pre>
<p>Now, run the <code>alembic revision</code> command with the <code>--autogenerate</code> option to create the script.</p>
<pre><code class="lang-bash">$ alembic revision --autogenerate -m <span class="hljs-string">"Add users table"</span>
</code></pre>
<ul>
<li>The -m flag adds a message to the script.</li>
</ul>
<p>A new script is created inside the <code>versions/</code> folder, we can alter it as needed but it's not required in this case.</p>
<p><strong>Running the migration script</strong></p>
<p>Running the script will reflect the newly made changes in the actual database.</p>
<p>Run the following command to get to the "the most recent" version of database - <code>head</code></p>
<pre><code class="lang-bash">$ alembic upgrade head
</code></pre>
<p>Yay! The database is initialized and we have our table live in the database.</p>
<p><strong>Interact with the database directly</strong></p>
<p>Before interacting with the database through FastAPI, let's do it directly.</p>
<p>Download the <a target="_blank" href="https://sqlitebrowser.org/dl/">SQLiteBrowser</a> and open the todo_app.db file with it:</p>
<pre><code class="lang-bash">$ sqlitebrowser app/todo_app.db <span class="hljs-comment"># Or use the GUI in windows</span>
</code></pre>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%205.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%205.png" /></p>
<h3 id="heading-using-fastapi-to-interact-with-the-database">Using FastAPI to interact with the database</h3>
<p><strong>Creating database dependency</strong></p>
<p>Open the <code>[dependency.py](http://dependency.py)</code> in the <code>app</code> folder and create the following dependency:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.database <span class="hljs-keyword">import</span> SessionLocal

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_db</span>():</span>
    db = SessionLocal()
    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">yield</span> db
    <span class="hljs-keyword">finally</span>:
        db.close()
</code></pre>
<p>We are using the <code>SessionLocal</code> class created in the <code>[databases.py](http://databases.py)</code> file.</p>
<p>We need to have an independent database session/connection (<code>SessionLocal</code>) per request, use the same session through all the requests, and then close it after the request is finished.</p>
<p>And then a new session will be created for the next request.</p>
<p><strong>Creating Path Operations</strong></p>
<p>Now, we will use the dependency created above in the path operations function:</p>
<p>Add the following functions in the <code>[users.py](http://users.py)</code> file inside <code>routers</code>, see how we are using <code>get_current_user</code> dependency to make authentication required for an operation.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List
<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> crud, schemas
<span class="hljs-keyword">from</span> app.dependency <span class="hljs-keyword">import</span> get_current_user, get_db
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> APIRouter, Depends, HTTPException, status
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session

router = APIRouter(prefix=<span class="hljs-string">"/users"</span>, tags=[<span class="hljs-string">"users"</span>])

<span class="hljs-meta">@router.post("/", response_model=schemas.User)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_user</span>(<span class="hljs-params">user: schemas.UserCreate, db: Session = Depends(<span class="hljs-params">get_db</span>)</span>):</span>
    db_user = crud.get_user_by_username(db, username=user.username)
    <span class="hljs-keyword">if</span> db_user:
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail=<span class="hljs-string">"Username already exists"</span>
        )
    <span class="hljs-keyword">return</span> crud.create_user(db, user)

<span class="hljs-meta">@router.get(</span>
    <span class="hljs-string">"/"</span>, response_model=List[schemas.User], dependencies=[Depends(get_current_user)]
)
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_users</span>(<span class="hljs-params">skip: int = <span class="hljs-number">0</span>, limit: int = <span class="hljs-number">100</span>, db: Session = Depends(<span class="hljs-params">get_db</span>)</span>):</span>
    users = crud.get_users(db, skip=skip, limit=limit)
    <span class="hljs-keyword">return</span> users

<span class="hljs-meta">@router.get("/me", response_model=schemas.User)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_users_me</span>(<span class="hljs-params">current_user: schemas.User = Depends(<span class="hljs-params">get_current_user</span>)</span>):</span>
    <span class="hljs-keyword">return</span> current_user

<span class="hljs-meta">@router.get(</span>
    <span class="hljs-string">"/{user_id}"</span>, response_model=schemas.User, dependencies=[Depends(get_current_user)]
)
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_user</span>(<span class="hljs-params">user_id: int, db: Session = Depends(<span class="hljs-params">get_db</span>)</span>):</span>
    db_user = crud.get_user(db, user_id)
    <span class="hljs-keyword">if</span> db_user <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail=<span class="hljs-string">"User not found"</span>
        )
    <span class="hljs-keyword">return</span> db_user
</code></pre>
<p><code>main.py</code></p>
<p>Add the following in <code>main.py</code>, It initializes the tables in the database:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.db.database <span class="hljs-keyword">import</span> engine
<span class="hljs-keyword">from</span> app.db <span class="hljs-keyword">import</span> base

base.Base.metadata.create_all(bind=engine)

app = FastAPI()
</code></pre>
<h3 id="heading-running-the-app-with-auth-and-users">Running the app with Auth and Users</h3>
<p>Let's check our progress till now by running the app:</p>
<pre><code class="lang-bash">$ uvicorn app.main:app --reload
</code></pre>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%206.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%206.png" /></p>
<p>Try creating users, signing in with the credentials of the new user-created, and then retrieving the multiple users or a single one with all the path operations.</p>
<h2 id="heading-creating-todo-items">Creating Todo Items</h2>
<p>Now, we will create CRUD operations for Todo Items</p>
<p><strong>Create Todo Schemas</strong></p>
<p>Let's start by creating Pydantic models for a to-do item.</p>
<p>Create a file <code>[todo.py](http://todos.py)</code> in the <code>schemas/</code> folder:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional

<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoBase</span>(<span class="hljs-params">BaseModel</span>):</span>
    title: str
    description: Optional[str] = <span class="hljs-literal">None</span>
    done: bool = <span class="hljs-literal">False</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoCreate</span>(<span class="hljs-params">TodoBase</span>):</span>
    <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Todo</span>(<span class="hljs-params">TodoBase</span>):</span>
    id: int
    owner_id: int

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span>:</span>
        orm_mode = <span class="hljs-literal">True</span>
</code></pre>
<p>Also, add the following line to <code>__init__.py</code> of <code>schemas/</code>: <code>from .todo import Todo, TodoCreate</code></p>
<p><strong>Create Todo SQLAlchemy Models</strong></p>
<p>Create a file <code>[todo.py](http://todo.py)</code> inside <code>models/</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.db.database <span class="hljs-keyword">import</span> Base
<span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> Boolean, Column, ForeignKey, Integer, String
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> relationship

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Todo</span>(<span class="hljs-params">Base</span>):</span>
    __tablename__ = <span class="hljs-string">"todos"</span>

    id = Column(Integer, primary_key=<span class="hljs-literal">True</span>, index=<span class="hljs-literal">True</span>)
    title = Column(String, nullable=<span class="hljs-literal">False</span>)
    description = Column(String)
    done = Column(Boolean, default=<span class="hljs-literal">False</span>)
    owner_id = Column(Integer, ForeignKey(<span class="hljs-string">"users.id"</span>))

    owner = relationship(<span class="hljs-string">"User"</span>, back_populates=<span class="hljs-string">"todos"</span>)
</code></pre>
<p>You are familiar with most of the things happening here, only the <code>relationship</code> thing is new.</p>
<p>A user and a todo are related to each other by the "owns" relationship such that a user owns a todo, we express this in a database using a foreign key that relates two entities together.</p>
<p>As one user can have multiple todo items but a todo item can have only one user associated with it, we placed this foreign key inside the todo item table.</p>
<p>The real magic lies in how easily we can access which user owns a todo item and all the todo items created by a user.</p>
<p>When accessing the attribute owner in a todo item, it will contain a User model from the users' table. SQLAlchemy will use the <code>owner_id</code> attribute/column with its foreign key to know which record to get from the users' table.</p>
<p>You also have to reflect this relationship inside the <code>User</code> model, so change it as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.db.database <span class="hljs-keyword">import</span> Base
<span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> Column, Integer, String
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> relationship

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">Base</span>):</span>
    __tablename__ = <span class="hljs-string">"users"</span>

    id = Column(Integer, primary_key=<span class="hljs-literal">True</span>, index=<span class="hljs-literal">True</span>)
    username = Column(String, unique=<span class="hljs-literal">True</span>, nullable=<span class="hljs-literal">False</span>, index=<span class="hljs-literal">True</span>)
    hashed_password = Column(String, nullable=<span class="hljs-literal">False</span>)

    todos = relationship(<span class="hljs-string">"Todo"</span>, back_populates=<span class="hljs-string">"owner"</span>)
</code></pre>
<p>Now, accessing <code>user.todos</code> will give you a list of all the todo items created by that <code>user</code>.</p>
<p>Add the following line to <code>__init__.py</code> of <code>models/</code>: <code>from .todo import Todo</code></p>
<p>Finally, update <code>[base.py](http://base.py)</code> in <code>database/</code> to have the <code>Todo</code> model:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.db.database <span class="hljs-keyword">import</span> Base
<span class="hljs-keyword">from</span> app.models.users <span class="hljs-keyword">import</span> User
<span class="hljs-keyword">from</span> app.models.todo <span class="hljs-keyword">import</span> Todo
</code></pre>
<p>Let's create a migration script and run the migrations to reflect the changes in the database:</p>
<pre><code class="lang-bash">$ alembic revision --autogenerate -m <span class="hljs-string">"Add todos table"</span>
</code></pre>
<pre><code class="lang-bash">$ alembic upgrade head
</code></pre>
<p>You can check the database using <code>sqlitebrowser</code>, a new table would have been created for todo items.</p>
<p><strong>Creating CRUD operations</strong></p>
<p>We have to do the following operations on a todo item:</p>
<ol>
<li><p>Create a new to-do item.</p>
</li>
<li><p>View all to-do items.</p>
</li>
<li><p>Mark a to-do item as completed.</p>
</li>
<li><p>Delete an existing to-do item.</p>
</li>
</ol>
<p>Create a file <code>[todo.py](http://todo.py)</code> inside <code>crud/</code>.</p>
<ol>
<li><p><strong>Create Todo Item</strong></p>
<pre><code class="lang-python"> <span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> models, schemas
 <span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_todo</span>(<span class="hljs-params">db: Session, todo: schemas.TodoCreate, user_id: int</span>):</span>
     db_todo = models.Todo(**todo.dict(), owner_id=user_id)
     db.add(db_todo)
     db.commit()
     db.refresh(db_todo)
     <span class="hljs-keyword">return</span> db_todo
</code></pre>
</li>
<li><p><strong>View all to-do items of current user</strong></p>
<pre><code class="lang-python"> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_todos</span>(<span class="hljs-params">db: Session, user_id: int, skip: int = <span class="hljs-number">0</span>, limit: int = <span class="hljs-number">100</span></span>):</span>
     <span class="hljs-keyword">return</span> db.query(models.Todo).filter(models.Todo.owner_id == user_id).offset(skip).limit(limit).all()
</code></pre>
</li>
<li><p><strong>Mark a todo item as completed</strong></p>
<pre><code class="lang-python"> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_todo_complete</span>(<span class="hljs-params">db: Session, todo_id: int, complete: bool, user_id: int</span>):</span>
     db_todo = db.query(models.Todo).get(todo_id)
     <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> db_todo:
         <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
     <span class="hljs-keyword">if</span> db_todo.owner_id != user_id:
         <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"Not authorized"</span>)
     db_todo.done = complete
     db.commit()
     db.refresh(db_todo)
     <span class="hljs-keyword">return</span> db_todo
</code></pre>
</li>
<li><p><strong>Delete an existing to-do item</strong></p>
<pre><code class="lang-python"> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete_todo</span>(<span class="hljs-params">
     db: Session,
     todo_id: int,
     user_id: int,
 </span>):</span>
     db_todo = db.query(models.Todo).get(todo_id)

     <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> db_todo:
         <span class="hljs-keyword">raise</span> KeyError(<span class="hljs-string">"Todo Not found"</span>)

     <span class="hljs-keyword">if</span> db_todo.owner_id != user_id:
         <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"Not authorized"</span>)

     db.delete(db_todo)
     db.commit()
</code></pre>
</li>
</ol>
<p>These are the required four functions, let's add them to <code>__init__.py</code> of <code>crud/</code>: <code>from .todo import create_todo, get_todos, update_todo_complete, delete_todo</code></p>
<p><strong>Creating Router for To-do</strong></p>
<p>It's time to create path operations for to-do items, create a file <code>[todo.py](http://todo.py)</code> inside <code>routers/</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> APIRouter, Depends, HTTPException, status
<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> crud, schemas
<span class="hljs-keyword">from</span> app.dependency <span class="hljs-keyword">import</span> get_db, get_current_user
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session

router = APIRouter(prefix=<span class="hljs-string">"/todos"</span>, tags=[<span class="hljs-string">"todos"</span>])
</code></pre>
<ol>
<li><p><strong>Path for creating to-do</strong></p>
<pre><code class="lang-python"><span class="hljs-meta"> @router.post("/", response_model=schemas.Todo)</span>
 <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_todo</span>(<span class="hljs-params">
     todo: schemas.TodoCreate,
     db: Session = Depends(<span class="hljs-params">get_db</span>),
     current_user: schemas.User = Depends(<span class="hljs-params">get_current_user</span>),
 </span>):</span>
     todo = crud.create_todo(
         db,
         todo,
         current_user.id,
     )
     <span class="hljs-keyword">return</span> todo
</code></pre>
</li>
<li><p><strong>Path for viewing all todos</strong></p>
<pre><code class="lang-python"><span class="hljs-meta"> @router.get("/", response_model=List[schemas.Todo])</span>
 <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_all_todos</span>(<span class="hljs-params">
     skip: int = <span class="hljs-number">0</span>,
     limit: int = <span class="hljs-number">100</span>,
     db: Session = Depends(<span class="hljs-params">get_db</span>),
     current_user: schemas.User = Depends(<span class="hljs-params">get_current_user</span>),
 </span>):</span>
     todos = crud.get_todos(db, current_user.id, skip, limit)
     <span class="hljs-keyword">return</span> todos
</code></pre>
</li>
<li><p><strong>Path for updating a to-do as complete/incomplete</strong></p>
<pre><code class="lang-python"><span class="hljs-meta"> @router.put("/", response_model=schemas.Todo)</span>
 <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_todo_complete</span>(<span class="hljs-params">
     todo_id: int,
     complete: bool,
     db: Session = Depends(<span class="hljs-params">get_db</span>),
     current_user: schemas.User = Depends(<span class="hljs-params">get_current_user</span>),
 </span>):</span>
     <span class="hljs-keyword">try</span>:
         todo = crud.update_todo_complete(
             db,
             todo_id,
             complete,
             current_user.id,
         )
     <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
         <span class="hljs-keyword">raise</span> HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))

     <span class="hljs-keyword">if</span> todo <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
         <span class="hljs-keyword">raise</span> HTTPException(
             status_code=status.HTTP_404_NOT_FOUND, detail=<span class="hljs-string">"Todo not found"</span>
         )
     <span class="hljs-keyword">return</span> todo
</code></pre>
</li>
<li><p><strong>Path for deleting a to-do item</strong></p>
<pre><code class="lang-python"><span class="hljs-meta"> @router.delete("/{todo_id}")</span>
 <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete_todo</span>(<span class="hljs-params">
     todo_id: int,
     db: Session = Depends(<span class="hljs-params">get_db</span>),
     current_user: schemas.User = Depends(<span class="hljs-params">get_current_user</span>),
 </span>):</span>
     <span class="hljs-keyword">try</span>:
         crud.delete_todo(db, todo_id, current_user.id)
     <span class="hljs-keyword">except</span> KeyError <span class="hljs-keyword">as</span> e:
         <span class="hljs-keyword">raise</span> HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
     <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
         <span class="hljs-keyword">raise</span> HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))

     <span class="hljs-keyword">return</span> <span class="hljs-string">"Todo Deleted"</span>
</code></pre>
</li>
</ol>
<p>Let's add the router to <code>main.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.routers <span class="hljs-keyword">import</span> users, todo

base.Base.metadata.create_all(bind=engine)

app = FastAPI()

app.include_router(users.router)
app.include_router(todo.router)
</code></pre>
<p>Let's run the app:</p>
<pre><code class="lang-bash">$ uvicorn app.main:app --reload
</code></pre>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%207.png" alt="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%207.png" /></p>
<h1 id="heading-testing">Testing</h1>
<p>Yay! We have created an API that does what we want. But does it?</p>
<p>Let's write some tests for the CRUD operations and API routes to validate our code.</p>
<h3 id="heading-what-is-testing">What is Testing?</h3>
<p>Testing is the act of making sure everything runs as we expect it to.</p>
<p>Let's see a simple example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">square</span>(<span class="hljs-params">x</span>):</span>
    <span class="hljs-keyword">return</span> x * x
</code></pre>
<p>We can test the above function by using an assert statement:</p>
<pre><code class="lang-python"><span class="hljs-keyword">assert</span> square(<span class="hljs-number">10</span>) == <span class="hljs-number">100</span>
</code></pre>
<p>If the <code>square</code> function we wrote is working properly the assert would do nothing, but if the <code>square</code> function is defined incorrectly then an <code>AssertionError</code> is raised.</p>
<h3 id="heading-testing-in-fastapi">Testing in FastAPI</h3>
<p>For testing our FastAPI app we will use the <code>pytest</code> library to make things easy.</p>
<p>Install the <code>pytest</code> library by executing the following command:</p>
<pre><code class="lang-bash">$ pip install -U pytest
</code></pre>
<p>Create a new folder <code>tests</code> in the <code>app</code> directory.</p>
<p>Now, create a file named <code>[conftest.py](http://conftest.py)</code> inside <code>tests</code>. This file will be used to create a temporary database and fixtures.</p>
<p><strong>What are fixtures?</strong></p>
<p>Fixtures are functions decorated with a <code>@pytest.fixture</code> decorator.</p>
<blockquote>
<p>When pytest goes to run a test, it looks at the parameters in that test function’s signature and then searches for fixtures that have the same names as those parameters. Once pytest finds them, it runs those fixtures, captures what they returned (if anything), and passes those objects into the test function as arguments.</p>
</blockquote>
<ul>
<li><a target="_blank" href="https://docs.pytest.org/en/latest/how-to/fixtures.html">pytest docs</a></li>
</ul>
<p>One use case of a fixture is to clear a database after each test and create a new one before each test.</p>
<p>Let's first create a temporary database for running tests so that we don't accidentally change our actual database.</p>
<p>Add the following in the <code>[conftest.py](http://conftest.py)</code> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest
<span class="hljs-keyword">from</span> app.dependency <span class="hljs-keyword">import</span> get_db
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session, sessionmaker
<span class="hljs-keyword">from</span> app.db.database <span class="hljs-keyword">import</span> Base
<span class="hljs-keyword">from</span> app.main <span class="hljs-keyword">import</span> app

SQLALCHEMY_DATABASE_URL = <span class="hljs-string">"sqlite:///./app/test.db"</span>

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={<span class="hljs-string">"check_same_thread"</span>: <span class="hljs-literal">False</span>}
)
TestingSessionLocal = sessionmaker(autocommit=<span class="hljs-literal">False</span>, autoflush=<span class="hljs-literal">False</span>, bind=engine)

<span class="hljs-meta">@pytest.fixture(scope="session", autouse=True)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">db_setup</span>():</span>
    Base.metadata.create_all(bind=engine)
    <span class="hljs-keyword">yield</span>
    Base.metadata.drop_all(bind=engine)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">override_get_db</span>():</span>
    <span class="hljs-keyword">try</span>:
        db = TestingSessionLocal()
        <span class="hljs-keyword">yield</span> db
    <span class="hljs-keyword">finally</span>:
        db.close()

<span class="hljs-meta">@pytest.fixture(scope="session")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">db</span>() -&gt; Generator:</span>
    <span class="hljs-keyword">yield</span> <span class="hljs-keyword">from</span> override_get_db()

app.dependency_overrides[get_db] = override_get_db
</code></pre>
<p>A lot is going on here, let's break it down:</p>
<ul>
<li><p>First, we created a new database using the same SQLAlchemy function we used before but this time we used a different <code>SQLALCHEMY_DATABASE_URL</code>. This will create a new database file <code>test.db</code> instead of using the previous <code>todo_app.db</code>.</p>
</li>
<li><p>Then, we created a fixture:</p>
<pre><code class="lang-python"><span class="hljs-meta">  @pytest.fixture(scope="session", autouse=True)</span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">db_setup</span>():</span>
      Base.metadata.create_all(bind=engine)
      <span class="hljs-keyword">yield</span>
      Base.metadata.drop_all(bind=engine)
</code></pre>
<ul>
<li><p>The <code>scope</code> of a fixture defines when it will be destroyed. Here are other possible values for scope:</p>
<p>  Fixtures are created when first requested by a test, and are destroyed based on their <code>scope</code>:</p>
<ul>
<li><p><code>function</code>: the default scope, the fixture is destroyed at the end of the test.</p>
</li>
<li><p><code>class</code>: the fixture is destroyed during the teardown of the last test in the class.</p>
</li>
<li><p><code>module</code>: the fixture is destroyed during the teardown of the last test in the module.</p>
</li>
<li><p><code>package</code>: the fixture is destroyed during the teardown of the last test in the package.</p>
</li>
<li><p><code>session</code>: the fixture is destroyed at the end of the test session.</p>
</li>
</ul>
</li>
<li><p>The <code>autouse=True</code> means that this fixture will automatically be used for every test without explicitly mentioning the fixture name, it makes sense because we will use a database for all tests.</p>
</li>
<li><p>Then in the function, the part above <code>yield</code> will be executed before running any test, and the part after will run after all the tests are completed.</p>
<p>  Before <code>yield</code>, we are creating a new database, and after <code>yield</code>, we are clearing that database.</p>
</li>
</ul>
</li>
<li><p>Then we created a new <code>dependency</code> that will use the temporary database. We override the <code>get_db</code> dependency with this one so any function in our app that uses the <code>get_db</code> will now use <code>override_get_db</code>, as a result, using the temporary database. This allowed us to use a new database without changing any code in our app.</p>
</li>
<li><p>We also created another fixture <code>db</code> to access the database directly without the dependencies. This will help write tests for CRUD operations.</p>
</li>
</ul>
<p>These things will be more clear when we use them in our tests.</p>
<p>Let's add three more fixtures to the <code>conftest.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Dict, Generator
<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> models
<span class="hljs-keyword">from</span> fastapi.testclient <span class="hljs-keyword">import</span> TestClient
<span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> utils    <span class="hljs-comment"># utils.py is created next</span>

<span class="hljs-meta">@pytest.fixture(scope="module")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">client</span>() -&gt; Generator:</span>
    <span class="hljs-keyword">with</span> TestClient(app) <span class="hljs-keyword">as</span> c:
        <span class="hljs-keyword">yield</span> c

<span class="hljs-meta">@pytest.fixture(scope="function")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user</span>(<span class="hljs-params">db: Session</span>) -&gt; models.User:</span>
    <span class="hljs-keyword">return</span> utils.create_random_user(db)

<span class="hljs-meta">@pytest.fixture(scope="module")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_token_headers</span>(<span class="hljs-params">client: TestClient, db: Session</span>) -&gt; Dict[str, str]:</span>
    <span class="hljs-keyword">return</span> utils.authentication_token(client=client, db=db)
</code></pre>
<p>Let's go through each fixture:</p>
<ul>
<li><p>The <code>client</code> fixture: We will use this to make API calls from our code like the <code>get</code> and <code>post</code> request. It is based on Python's <em>request</em> library.</p>
</li>
<li><p>The <code>user</code> fixture: It will create random users to test the todo CRUD operations.</p>
</li>
<li><p>the <code>user_token_headers</code> fixture: It is used to provide <code>bearer</code> token while accessing endpoints which needs authentication.</p>
</li>
</ul>
<p>A few fixtures above uses functions from the <code>[utils.py](http://utils.py)</code> file, let's define it in the same <code>tests</code> folder:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random
<span class="hljs-keyword">import</span> string
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Dict
<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> crud, models, schemas

<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session
<span class="hljs-keyword">from</span> fastapi.testclient <span class="hljs-keyword">import</span> TestClient

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">random_lower_string</span>() -&gt; str:</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>.join(random.choices(string.ascii_lowercase, k=random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">32</span>)))

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_random_user</span>(<span class="hljs-params">db: Session</span>) -&gt; models.User:</span>
    username = random_lower_string()
    password = random_lower_string()
    user_in = schemas.UserCreate(username=username, password=password)
    user = crud.create_user(db, user=user_in)
    <span class="hljs-keyword">return</span> user

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_authentication_headers</span>(<span class="hljs-params">
    *, client: TestClient, username: str, password: str
</span>) -&gt; Dict[str, str]:</span>
    data = {<span class="hljs-string">"username"</span>: username, <span class="hljs-string">"password"</span>: password}
    r = client.post(<span class="hljs-string">"/token"</span>, data=data)
    response = r.json()
    auth_token = response[<span class="hljs-string">"access_token"</span>]
    headers = {<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">f"Bearer <span class="hljs-subst">{auth_token}</span>"</span>}
    <span class="hljs-keyword">return</span> headers

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">authentication_token</span>(<span class="hljs-params">*, client: TestClient, db: Session</span>) -&gt; Dict[str, str]:</span>
    username = random_lower_string()
    password = random_lower_string()
    crud.create_user(db, user=schemas.UserCreate(username=username, password=password))
    <span class="hljs-keyword">return</span> user_authentication_headers(
        client=client, username=username, password=password
    )
</code></pre>
<p>Here's what each function is doing:</p>
<ul>
<li><p><code>random_lower_string</code>: Creates a random string of max length 32 to be used in the test to create users and todo items.</p>
</li>
<li><p><code>create_random_user</code>: Creates and returns a random user.</p>
</li>
<li><p><code>user_authentication_headers</code>: Returns the authorization header to be used to authenticate API requests made through tests.</p>
</li>
<li><p><code>authentication_token</code>: Creates a new user and returns its authorization header.</p>
</li>
</ul>
<h3 id="heading-tests-for-crud-operations">Tests for CRUD operations</h3>
<p>We are now done with the setup required to test our code, now we will test the CRUD operations for users and todos.</p>
<p>Create folder <code>crud</code> inside <code>tests</code>.</p>
<p>Create a file called <code>test_user.py</code> inside <code>crud</code>. Remember to prepend the file name by <code>test_</code>, this is how <code>pytest</code> will find test files to execute.</p>
<p>Let's define the test functions for each of the crud operation on <code>user</code> one by one:</p>
<p><strong>Import the necessary modules</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> crud
<span class="hljs-keyword">from</span> app.schemas <span class="hljs-keyword">import</span> UserCreate
<span class="hljs-keyword">from</span> app.tests <span class="hljs-keyword">import</span> utils
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session
<span class="hljs-keyword">from</span> app.tests <span class="hljs-keyword">import</span> utils
<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> models
</code></pre>
<p><strong>Test creating a user</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_create_user</span>(<span class="hljs-params">db: Session</span>):</span>
    username = utils.random_lower_string()
    password = utils.random_lower_string()
    user_in = UserCreate(username=username, password=password)
    user = crud.create_user(db, user=user_in)
    <span class="hljs-keyword">assert</span> user.username == username
    <span class="hljs-keyword">assert</span> hasattr(user, <span class="hljs-string">"hashed_password"</span>)
</code></pre>
<p>This test function corresponds to the <code>create_user</code> function of <code>crud/users.py</code>. We are creating a user and then making sure the created user has the same username as the one used to create that user and has the <code>hashed_password</code> attribute.</p>
<p><strong>Remember</strong> each test function's name <em>must</em> start with <code>test_</code> and a test function's name should be descriptive.</p>
<p><strong>Test authenticating a user</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_authenticate_user</span>(<span class="hljs-params">db: Session</span>):</span>
    username = utils.random_lower_string()
    password = utils.random_lower_string()
    user_in = UserCreate(username=username, password=password)
    user = crud.create_user(db, user=user_in)
    authenticated_user = crud.users.authenticate_user(
        db, username=username, password=password
    )
    <span class="hljs-keyword">assert</span> authenticated_user
    <span class="hljs-keyword">assert</span> authenticated_user.username == user.username
</code></pre>
<p>This function corresponds to the <code>authenticate_user</code> function of the <code>crud/users.py</code>. We are making sure an existing user with the correct credentials is authenticated.</p>
<p><strong>Test not authenticating a user</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_not_authenticate_user</span>(<span class="hljs-params">db: Session</span>):</span>
    username = utils.random_lower_string()
    password = utils.random_lower_string()
    user_in = UserCreate(username=username, password=password)
    user = crud.create_user(db, user=user_in)
    <span class="hljs-keyword">assert</span> <span class="hljs-keyword">not</span> crud.authenticate_user(db, username=username, password=<span class="hljs-string">"wrong"</span>)
    <span class="hljs-keyword">assert</span> <span class="hljs-keyword">not</span> crud.authenticate_user(db, username=<span class="hljs-string">"wrong"</span>, password=password)
    <span class="hljs-keyword">assert</span> <span class="hljs-keyword">not</span> crud.authenticate_user(db, username=<span class="hljs-string">"wrong"</span>, password=<span class="hljs-string">"wrong"</span>)
</code></pre>
<p>This function also corresponds to the <code>authenticate_user</code>, but this time it is checking a different path that is when a user does not exists or enter incorrect credentials.</p>
<p><strong>Test getting a user by id</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_get_user_by_id</span>(<span class="hljs-params">db: Session, user: models.User</span>):</span>
    user_out = crud.get_user(db, user_id=user.id)
    <span class="hljs-keyword">assert</span> user_out
    <span class="hljs-keyword">assert</span> user_out.username == user.username
    <span class="hljs-keyword">assert</span> user_out.hashed_password == user.hashed_password
</code></pre>
<p>We are testing <code>crud.get_user</code> here, first we created a new user and called <code>get_user</code> with its <code>id</code> and checked if we are getting the correct user in output or not.</p>
<p>We also used the <code>user</code><strong>fixture</strong> in the arguments**,** so the user parameter will be provided with a random user by pytest.</p>
<p><strong>Test getting a user by username</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_get_user_by_username</span>(<span class="hljs-params">db: Session, user: models.User</span>):</span>
    user_out = crud.get_user_by_username(db, username=user.username)
    <span class="hljs-keyword">assert</span> user_out
    <span class="hljs-keyword">assert</span> user_out.username == user.username
    <span class="hljs-keyword">assert</span> user_out.hashed_password == user.hashed_password
</code></pre>
<p>This one is similar to the previous one.</p>
<p><strong>Testing getting all users</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_get_users</span>(<span class="hljs-params">db: Session, user: models.User</span>):</span>
    user_out = crud.get_users(db)
    print(user_out)
    <span class="hljs-keyword">assert</span> user_out
    <span class="hljs-keyword">assert</span> user_out[<span class="hljs-number">-1</span>].username == user.username
    <span class="hljs-keyword">assert</span> user_out[<span class="hljs-number">-1</span>].hashed_password == user.hashed_password
</code></pre>
<p>Here, we are creating a new user using the fixture and getting all the users, and finally checking that the new user is the last one in the list or not.</p>
<p>That's it for test for user's crud operation.</p>
<p>Try running them with the following command in the <code>todo</code> directory:</p>
<pre><code class="lang-bash">$ python -m pytest app/tests/crud
</code></pre>
<p>You will get an output like this:</p>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%208.png" alt="Untitled" /></p>
<p>Each green dot represents a single test function and means that the test passed, an 'F' means that the test failed.</p>
<p>Here are the test functions for todo's crud operations(<code>crud/todo.py</code>), you will be able to understand them now:</p>
<p>Create a file <code>test_todo.py</code> in the <code>tests/crud</code> folder and the following tests:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest
<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> crud, models, schemas
<span class="hljs-keyword">from</span> app.tests <span class="hljs-keyword">import</span> utils
<span class="hljs-keyword">from</span> sqlalchemy.orm <span class="hljs-keyword">import</span> Session

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_create_todo</span>(<span class="hljs-params">db: Session, user: models.User</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test creating a todo"""</span>
    todo_in = schemas.TodoCreate(
        title=utils.random_lower_string(),
        description=utils.random_lower_string(),
        done=<span class="hljs-literal">False</span>,
    )
    todo_out = crud.create_todo(db=db, todo=todo_in, user_id=user.id)
    <span class="hljs-keyword">assert</span> todo_out.title == todo_in.title
    <span class="hljs-keyword">assert</span> todo_out.owner_id == user.id

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_get_todos</span>(<span class="hljs-params">db: Session, user: models.User</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test getting all todos"""</span>
    todo_in_1 = schemas.TodoCreate(title=utils.random_lower_string())
    crud.create_todo(db=db, todo=todo_in_1, user_id=user.id)
    todo_in_2 = schemas.TodoCreate(title=utils.random_lower_string())
    crud.create_todo(db=db, todo=todo_in_2, user_id=user.id)
    todos = crud.get_todos(db=db, user_id=user.id)
    <span class="hljs-keyword">assert</span> len(todos) == <span class="hljs-number">2</span>
    <span class="hljs-keyword">assert</span> todos[<span class="hljs-number">0</span>].title == todo_in_1.title
    <span class="hljs-keyword">assert</span> todos[<span class="hljs-number">1</span>].title == todo_in_2.title

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_update_todo_complete</span>(<span class="hljs-params">db: Session, user: models.User</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test updating a todo's complete status"""</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    todo = crud.create_todo(db=db, todo=todo_in, user_id=user.id)
    todo_out = crud.update_todo_complete(
        db=db, todo_id=todo.id, complete=<span class="hljs-literal">True</span>, user_id=user.id
    )
    <span class="hljs-keyword">assert</span> todo_out.done <span class="hljs-keyword">is</span> <span class="hljs-literal">True</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_update_todo_complete_when_todo_does_not_exist</span>(<span class="hljs-params">
    db: Session, user: models.User
</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test updating a todo's complete status when todo doesn't exist"""</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    todo = crud.create_todo(db=db, todo=todo_in, user_id=user.id)
    todo_out = crud.update_todo_complete(
        db=db, todo_id=todo.id + <span class="hljs-number">1</span>, complete=<span class="hljs-literal">True</span>, user_id=user.id
    )
    <span class="hljs-keyword">assert</span> todo_out <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_update_todo_complete_when_todo_is_not_owned</span>(<span class="hljs-params">
    db: Session, user: models.User
</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test updating a todo's complete status when todo is not owned"""</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    todo = crud.create_todo(db=db, todo=todo_in, user_id=user.id)
    <span class="hljs-keyword">with</span> pytest.raises(Exception) <span class="hljs-keyword">as</span> e:
        todo_out = crud.update_todo_complete(
            db=db, todo_id=todo.id, complete=<span class="hljs-literal">True</span>, user_id=user.id + <span class="hljs-number">1</span>
        )

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_delete_todo</span>(<span class="hljs-params">db: Session, user: models.User</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test deleting a todo"""</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    todo = crud.create_todo(db=db, todo=todo_in, user_id=user.id)
    crud.delete_todo(db=db, todo_id=todo.id, user_id=user.id)
    todos = crud.get_todos(db=db, user_id=user.id)
    <span class="hljs-keyword">assert</span> todo <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> todos

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_delete_todo_when_todo_does_not_exist</span>(<span class="hljs-params">db: Session, user: models.User</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test deleting a todo when todo doesn't exist"""</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    todo = crud.create_todo(db=db, todo=todo_in, user_id=user.id)
    <span class="hljs-keyword">with</span> pytest.raises(KeyError) <span class="hljs-keyword">as</span> e:
        crud.delete_todo(db=db, todo_id=todo.id + <span class="hljs-number">1</span>, user_id=user.id)
    todos = crud.get_todos(db=db, user_id=user.id)
    <span class="hljs-keyword">assert</span> todo <span class="hljs-keyword">in</span> todos

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_delete_todo_when_todo_is_not_owned</span>(<span class="hljs-params">db: Session, user: models.User</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-string">"""Test deleting a todo when todo is not owned"""</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    todo = crud.create_todo(db=db, todo=todo_in, user_id=user.id)
    <span class="hljs-keyword">with</span> pytest.raises(Exception) <span class="hljs-keyword">as</span> e:
        crud.delete_todo(db=db, todo_id=todo.id, user_id=user.id + <span class="hljs-number">1</span>)
    todos = crud.get_todos(db=db, user_id=user.id)
    <span class="hljs-keyword">assert</span> todo <span class="hljs-keyword">in</span> todos
</code></pre>
<p>Try running them.</p>
<p>Now we will write and understand test functions for the API.</p>
<h3 id="heading-tests-for-api-endpoints">Tests for API endpoints</h3>
<p>Create folder <code>api</code> inside <code>tests</code> and create a file <code>test_users.py</code>.</p>
<p><strong>Import necessary modules in</strong><code>test_users.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Dict

<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> models, schemas
<span class="hljs-keyword">from</span> fastapi.testclient <span class="hljs-keyword">import</span> TestClient
<span class="hljs-keyword">from</span> app.tests <span class="hljs-keyword">import</span> utils
</code></pre>
<p><strong>Test Create User</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_create_user</span>(<span class="hljs-params">client: TestClient</span>):</span>
    user = schemas.UserCreate(username=<span class="hljs-string">"test"</span>, password=<span class="hljs-string">"test"</span>)
    response = client.post(<span class="hljs-string">"/users/"</span>, json=user.dict())
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>
    created_user = response.json()
    <span class="hljs-keyword">assert</span> created_user[<span class="hljs-string">"username"</span>] == user.username
</code></pre>
<p>Here we are testing the <code>/users/</code> endpoint when accessed with a <code>post</code> request. We are using the <code>client</code> fixture to make the request, the first parameter to <code>[client.post](http://client.post)</code> defines the path and the <code>json</code> parameter includes the json data needed to create a user.</p>
<p>Then we are asserting a successful response and creation of a correct user.</p>
<p>Here are a few ways to send data in a request using the <code>client</code></p>
<ul>
<li><p>To pass a <em>path</em> or <em>query</em> parameter, add it to the URL itself.</p>
</li>
<li><p>To pass a JSON body, pass a Python object (e.g. a <code>dict</code>) to the parameter <code>json</code>.</p>
</li>
<li><p>If you need to send <em>Form Data</em> instead of JSON, use the <code>data</code> parameter instead.</p>
</li>
<li><p>To pass <em>headers</em>, use a <code>dict</code> in the <code>headers</code> parameter.</p>
</li>
<li><p>For <em>cookies</em>, a <code>dict</code> in the <code>cookies</code> parameter.</p>
</li>
</ul>
<p><strong>Remaining test functions for User's endpoint</strong></p>
<p>Similarly, we can create tests for other endpoints:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_create_user_when_exist</span>(<span class="hljs-params">client: TestClient</span>):</span>
    user = schemas.UserCreate(username=<span class="hljs-string">"existing"</span>, password=<span class="hljs-string">"existing"</span>)
    response = client.post(<span class="hljs-string">"/users/"</span>, json=user.dict())
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>
    response = client.post(<span class="hljs-string">"/users/"</span>, json=user.dict())
    <span class="hljs-keyword">assert</span> <span class="hljs-number">400</span> &lt;= response.status_code &lt; <span class="hljs-number">500</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_read_users</span>(<span class="hljs-params">client: TestClient, user_token_headers: Dict[str, str]</span>):</span>
    user1 = schemas.UserCreate(
        username=utils.random_lower_string(), password=utils.random_lower_string()
    )
    response = client.post(<span class="hljs-string">"/users/"</span>, json=user1.dict())
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    user2 = schemas.UserCreate(
        username=utils.random_lower_string(), password=utils.random_lower_string()
    )
    response = client.post(<span class="hljs-string">"/users/"</span>, json=user2.dict())
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    response = client.get(<span class="hljs-string">"/users/"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>
    users = response.json()
    <span class="hljs-keyword">assert</span> len(users) &gt; <span class="hljs-number">0</span>
    <span class="hljs-keyword">assert</span> users[<span class="hljs-number">-1</span>][<span class="hljs-string">"username"</span>] == user2.username

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_read_user_me</span>(<span class="hljs-params">client: TestClient, user_token_headers: Dict[str, str]</span>):</span>
    response = client.get(<span class="hljs-string">"/users/me"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>
    current_user = response.json()
    <span class="hljs-keyword">assert</span> current_user
    <span class="hljs-keyword">assert</span> <span class="hljs-string">"username"</span> <span class="hljs-keyword">in</span> current_user

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_read_user</span>(<span class="hljs-params">
    client: TestClient, user_token_headers: Dict[str, str], user: models.User
</span>):</span>
    user_id = user.id
    response = client.get(<span class="hljs-string">f"/users/<span class="hljs-subst">{user_id}</span>"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>
    existing_user = response.json()
    <span class="hljs-keyword">assert</span> existing_user
    <span class="hljs-keyword">assert</span> existing_user[<span class="hljs-string">"username"</span>] == user.username

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_read_user_when_not_found</span>(<span class="hljs-params">
    client: TestClient, user_token_headers: Dict[str, str], user: models.User
</span>):</span>
    response = client.get(<span class="hljs-string">f"/users/<span class="hljs-subst">{user.id + <span class="hljs-number">1</span>}</span>"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> response.status_code == <span class="hljs-number">404</span>
</code></pre>
<p>Also, create a file <code>test_todos.py</code> in <code>api</code> and add the following tests:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Dict
<span class="hljs-keyword">from</span> app <span class="hljs-keyword">import</span> schemas
<span class="hljs-keyword">from</span> fastapi.testclient <span class="hljs-keyword">import</span> TestClient
<span class="hljs-keyword">from</span> app.tests <span class="hljs-keyword">import</span> utils

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_create_todo</span>(<span class="hljs-params">client: TestClient, user_token_headers: Dict[str, str]</span>):</span>
    todo_in = schemas.TodoCreate(
        title=utils.random_lower_string(), description=utils.random_lower_string()
    )
    response = client.post(<span class="hljs-string">"/todos/"</span>, json=todo_in.dict(), headers=user_token_headers)

    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todo = response.json()
    <span class="hljs-keyword">assert</span> todo[<span class="hljs-string">"title"</span>] == todo_in.title

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_read_all_todos</span>(<span class="hljs-params">client: TestClient, user_token_headers: Dict[str, str]</span>):</span>
    todo1 = schemas.TodoCreate(
        title=utils.random_lower_string(), description=utils.random_lower_string()
    )
    response = client.post(<span class="hljs-string">"/todos/"</span>, json=todo1.dict(), headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todo2 = schemas.TodoCreate(
        title=utils.random_lower_string(), description=utils.random_lower_string()
    )
    response = client.post(<span class="hljs-string">"/todos/"</span>, json=todo2.dict(), headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    response = client.get(<span class="hljs-string">"/todos/"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todos = response.json()
    <span class="hljs-keyword">assert</span> len(todos) &gt; <span class="hljs-number">0</span>
    <span class="hljs-keyword">assert</span> todos[<span class="hljs-number">-1</span>][<span class="hljs-string">"title"</span>] == todo2.title

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_update_todo_complete</span>(<span class="hljs-params">client: TestClient, user_token_headers: Dict[str, str]</span>):</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    response = client.post(<span class="hljs-string">"/todos/"</span>, json=todo_in.dict(), headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todo = response.json()
    <span class="hljs-keyword">assert</span> todo[<span class="hljs-string">"title"</span>] == todo_in.title

    response = client.put(
        <span class="hljs-string">f"/todos/?todo_id=<span class="hljs-subst">{todo[<span class="hljs-string">'id'</span>]}</span>&amp;complete=true"</span>, headers=user_token_headers
    )
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todo = response.json()
    <span class="hljs-keyword">assert</span> todo[<span class="hljs-string">"title"</span>] == todo_in.title
    <span class="hljs-keyword">assert</span> todo[<span class="hljs-string">"done"</span>] <span class="hljs-keyword">is</span> <span class="hljs-literal">True</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_update_todo_complete_when_not_found</span>(<span class="hljs-params">
    client: TestClient, user_token_headers: Dict[str, str]
</span>):</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    response = client.post(<span class="hljs-string">"/todos/"</span>, json=todo_in.dict(), headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todo = response.json()
    <span class="hljs-keyword">assert</span> todo[<span class="hljs-string">"title"</span>] == todo_in.title

    response = client.put(
        <span class="hljs-string">f"/todos/?todo_id=<span class="hljs-subst">{todo[<span class="hljs-string">'id'</span>] + <span class="hljs-number">1</span>}</span>&amp;complete=true"</span>, headers=user_token_headers
    )
    <span class="hljs-keyword">assert</span> response.status_code == <span class="hljs-number">404</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_delete_todo</span>(<span class="hljs-params">client: TestClient, user_token_headers: Dict[str, str]</span>):</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    response = client.post(<span class="hljs-string">"/todos/"</span>, json=todo_in.dict(), headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todo = response.json()
    <span class="hljs-keyword">assert</span> todo[<span class="hljs-string">"title"</span>] == todo_in.title

    response = client.delete(<span class="hljs-string">f"/todos/<span class="hljs-subst">{todo[<span class="hljs-string">'id'</span>]}</span>"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    response = client.get(<span class="hljs-string">"/todos/"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todos = response.json()
    <span class="hljs-keyword">assert</span> todo <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> todos

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_delete_todo_not_found</span>(<span class="hljs-params">client: TestClient, user_token_headers: Dict[str, str]</span>):</span>
    todo_in = schemas.TodoCreate(title=utils.random_lower_string())
    response = client.post(<span class="hljs-string">"/todos/"</span>, json=todo_in.dict(), headers=user_token_headers)
    <span class="hljs-keyword">assert</span> <span class="hljs-number">200</span> &lt;= response.status_code &lt; <span class="hljs-number">300</span>

    todo = response.json()
    <span class="hljs-keyword">assert</span> todo[<span class="hljs-string">"title"</span>] == todo_in.title

    response = client.delete(<span class="hljs-string">f"/todos/<span class="hljs-subst">{todo[<span class="hljs-string">'id'</span>] + <span class="hljs-number">1</span>}</span>"</span>, headers=user_token_headers)
    <span class="hljs-keyword">assert</span> response.status_code == <span class="hljs-number">404</span>
</code></pre>
<p>As an exercise, I encourage you to define a test function for the <code>token/</code> endpoint from the <code>[main.py](http://main.py)</code> file.</p>
<p>With this we are done with testing, let's check the result.</p>
<h2 id="heading-testing-result">Testing Result</h2>
<p><strong>Testing Coverage:</strong> This is a technique to determine how much application code we are testing.</p>
<p>Install the <code>pytest-cov</code> package which is a pytest plugin to measure test coverage.</p>
<pre><code class="lang-bash">$ install pip install pytest-cov
</code></pre>
<p>And run the following command in the <code>todo</code> directory:</p>
<pre><code class="lang-bash">$ python -m pytest app --cov=app --cov-report term-missing
</code></pre>
<p>We get the following output:</p>
<p><img src="A%20Beginner's%20Guide%20to%20FastAPI%20(Draft%202)%205064c7e8ab2745578bf2fe18c70405f0/Untitled%209.png" alt="Untitled" /></p>
<pre><code class="lang-bash">---------- coverage: platform linux, python 3.8.10-final-0 -----------
Name                          Stmts   Miss  Cover   Missing
-----------------------------------------------------------
...
app/crud/todo.py                 28      0   100%
app/crud/users.py                23      0   100%
...
app/routers/todo.py              32      4    88%   49-50, 69-70
app/routers/users.py             25      0   100%
...
-----------------------------------------------------------
TOTAL                           519     15    97%

=============== 26 passed, 6 warnings <span class="hljs-keyword">in</span> 7.53s ================
</code></pre>
<p>We passed all 26 tests that we wrote and the test coverage is 97%.</p>
<p>Now try running the app with <code>uvicorn</code> and try out different endpoints yourself, try creating a user, signing in, creating and deleting todo items.</p>
<h1 id="heading-woohoo">Woohoo!</h1>
<p><strong>Congratulations on making it this far.</strong></p>
<p>We have created a Todo API with FastAPI and in the process learned a lot of things, I hope you have enjoyed it.</p>
<h1 id="heading-whats-next">What's next?</h1>
<p>I would recommend you to read the official <a target="_blank" href="https://fastapi.tiangolo.com/tutorial/">docs</a> of FastAPI and create your own Project.</p>
<p>FastAPI docs are one of the best I have seen with proper examples, even this article is highly inspired by the same and uses many examples of the docs.</p>
<p>You would now find it much easier to work your way through the docs and create structured projects with FastAPI.</p>
]]></content:encoded></item><item><title><![CDATA[Hashbot: A Twitter Bot For Hashnode Articles #christmashackathon]]></title><description><![CDATA[Idea
For the Hashnode Christmas Hackathon, I decided to build a Twitter bot that does two things -

Retweet every tweet with the following keyword in itself -
Hashnode
HashnodeCommunity
HashnodeBot


Reply with the requested article when mentioned in...]]></description><link>https://blog.yuvraj.tech/hashbot-a-twitter-bot-for-hashnode-articles-christmashackathon</link><guid isPermaLink="true">https://blog.yuvraj.tech/hashbot-a-twitter-bot-for-hashnode-articles-christmashackathon</guid><category><![CDATA[Christmas Hackathon]]></category><category><![CDATA[Python]]></category><category><![CDATA[Twitter]]></category><category><![CDATA[bot]]></category><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Wed, 30 Dec 2020 07:41:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1609314046365/0ZC0lXzZP.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="idea">Idea</h2>
<p>For the Hashnode Christmas Hackathon, I decided to build a Twitter bot that does two things -</p>
<ul>
<li>Retweet every tweet with the following keyword in itself -<ul>
<li>Hashnode</li>
<li>HashnodeCommunity</li>
<li>HashnodeBot</li>
</ul>
</li>
<li><p>Reply with the requested article when mentioned in a tweet.</p>
<ul>
<li><p>Tweeting</p>
<blockquote>
<p>@HashnodeBot featured</p>
</blockquote>
<p>  will get you a reply from the bot with today's two featured articles.</p>
</li>
<li><p>Tweeting</p>
<blockquote>
<p>@HashnodeBot  [n]</p>
</blockquote>
<p>  will get you a reply from the bot <strong>n</strong> last articles from the specified user.</p>
</li>
</ul>
</li>
</ul>
<h2 id="development">Development</h2>
<p>On December 28, Morning I started the project, I had never created a bot before so I searched google and learned about <a target="_blank" href="[https://www.tweepy.org/](https://www.tweepy.org/">Tweepy</a>) and how to use it.</p>
<blockquote>
<p>Tweepy is a <strong>Python</strong> library for accessing the Twitter API.</p>
</blockquote>
<h3 id="strategy">Strategy</h3>
<p>Now, was the time to decide how I will achieve the two requirements -</p>
<ul>
<li>Retweeting tweets with concerning keywords.</li>
<li>Replying with Hashnode articles as demanded by the user.</li>
</ul>
<p>The first task was easy and direct to do with <strong>Tweepy,</strong> I just had to write a simple Python script that waits for new tweets with given keywords and then retweet and like them if not done yet.</p>
<p>The second task required me to use both <strong>Hashnode and Twitter API</strong>, the idea was to read tweets that mention the bot @HashnodeBot and then using the Hashnode API get those tweet, but the problem was Hashnode uses GraphQL and I didn't understand it, So I gave a quick look to GraphQL documentation and figured out how to use it. (It was not that hard though 😅).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609313718815/t6Cf30ryw.png" alt="image.png" /></p>
<p>I wrote two python scripts for this task, one fetches articles using hashnode API, and the other replies to the tweet with Bot's mention.</p>
<h2 id="result">Result</h2>
<p>Here is how <strong>Retweet Bot</strong> looks like on Twitter -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609313592972/fasp7fXmE.png" alt="image.png" /></p>
<p>and this is how <strong>Reply Bot</strong> looks like on Twitter -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609313632685/T9q-2J20d.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609313654739/F010BW2Wh.png" alt="image.png" /></p>
<h2 id="problem">Problem</h2>
<p>For some reason, Twitter was not showing the replies from the bot to other users, only the reply count is increasing and the replies are visible from the bots account only.</p>
<blockquote>
<p>Twitter was restricting the visibility of the Bot</p>
</blockquote>
<p>I tried to get around this, searched Google but couldn't make it, The only reason I got is that Twitter spam filtering was responsible for this, so I decided to deploy the bot with only the retweet feature.</p>
<h2 id="deployment">Deployment</h2>
<p>I used Docker to deploy the bot on AWS, this was my first time with both Docker and AWS.</p>
<p>I also used the <a target="_blank" href="https://apoorvtyagi.tech/scp-command-in-linux">scp</a> command for the first time to transfer the docker package to AWS.</p>
<h2 id="final-result">Final Result</h2>
<p>So, in the end, I created and deployed a Twitter Bot that retweets tweets with the following keywords - <strong>Hashnode, HashnodeCommunity.</strong></p>
<p>In the first 24 hours of deployment, the bot has retweeted over 100 hashnode tweets.</p>
<blockquote>
<p><strong>You can follow the bot <a target="_blank" href="[https://twitter.com/hashnodeBot/](https://twitter.com/hashnodeBot/">@HashnodeBot</a> to stay updated with all the amazing articles on hashnode and support the writers.</strong></p>
</blockquote>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/HashnodeBot/status/1343875531272384512">https://twitter.com/HashnodeBot/status/1343875531272384512</a></div>
<h2 id="here-are-the-resources-i-used-in-this-project">Here are the resources I used in this project</h2>
<ul>
<li><a target="_blank" href="https://realpython.com/twitter-bot-python-tweepy/#deploying-bots-to-a-server-using-docker">Realpython guide to creating Twitter bot</a></li>
<li><a target="_blank" href="https://api.hashnode.com/">Hashnode API</a></li>
<li><a target="_blank" href="https://twitter.com/">Twitter</a></li>
<li><a target="_blank" href="https://www.tweepy.org/">Tweepy</a></li>
</ul>
<h2 id="thanks-for-reading">Thanks For Reading</h2>
<p>If you find this article and project helpful, please like and share, and leave your feedback in the comments, It means a lot. 🙏🏼</p>
<p><strong>You may also like:</strong></p>
<ul>
<li><a target="_blank" href="[https://blog.yuvv.xyz/the-mutable-default-argument-mess-in-python](https://blog.yuvv.xyz/the-mutable-default-argument-mess-in-python">The Mutable Default Argument Mess in Python</a>)</li>
<li><a target="_blank" href="https://blog.yuvv.xyz/what-happens-when-you-run-a-computer-program">What Happens When You Run a Computer Program?</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/comprehensions-in-python-explained">Comprehensions in Python: Explained</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/linux-commands-reference-with-examples">Linux Commands Reference With Examples</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[This is how the Internet Works]]></title><description><![CDATA[We use the internet on a daily basis. Our phones, laptops, computers, all connected to the internet. But how the internet works? 
In this blog, we are going to find the answers to these questions -

What is the internet?
What is a network?
What are I...]]></description><link>https://blog.yuvraj.tech/do-you-understand-the-internet</link><guid isPermaLink="true">https://blog.yuvraj.tech/do-you-understand-the-internet</guid><category><![CDATA[internet]]></category><category><![CDATA[Computer Science]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Fri, 27 Nov 2020 13:09:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1606482514479/I-9EaQQF3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We use the internet on a daily basis. Our phones, laptops, computers, all connected to the internet. But how the internet works? </p>
<p>In this blog, we are going to find the answers to these questions -</p>
<ul>
<li>What is the internet?</li>
<li>What is a network?</li>
<li>What are IP addresses?</li>
<li>What happens when you search on Google?</li>
<li>What are the rules of the Internet?</li>
<li>Where is Google’s server located?</li>
<li>What devices hold the internet together?</li>
</ul>
<blockquote>
<p>Fasten your seat belts for a ride over routers...</p>
</blockquote>
<h2 id="what-is-the-internet">What is the Internet?</h2>
<ul>
<li>The Internet is the global system of interconnected computer networks that uses the Internet protocol suite (TCP/IP) to communicate between networks and devices.</li>
<li>It is a network of networks.<ul>
<li>Several collections of computers together make the internet.</li>
</ul>
</li>
<li>It is used for sharing various resources such as web pages, emails, file sharing.</li>
<li>To understand the internet, we first need to understand what a network is?</li>
</ul>
<h2 id="what-is-a-network">What is a Network?</h2>
<ul>
<li><p>A network is a collection of computers, servers, mainframes, network devices, peripherals, or other devices connected to one another to allow the sharing of data.</p>
</li>
<li><p>Consider an example of a network: your <strong>home network</strong> -</p>
<ul>
<li>You have a router in your home.<ul>
<li>This router connects to the Internet.</li>
<li>You pay your isp for this connection - Airtel, Jio, etc.</li>
<li>Other devices connect to the router with cables or wifi.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481227664/iRg8XvpCK.png" alt="Home Network" /></p>
<h2 id="what-are-ip-addresses">What are IP addresses?</h2>
<ul>
<li>Every device on the internet has an IP address that allows other computers to talk to it.</li>
<li>It is of the form: #.#.#.#<ul>
<li>Four numbers separated by dots of the values 0-255.</li>
<li>This version of IP addresses is called <strong>IPv4</strong>.</li>
</ul>
</li>
<li>Like postal addresses, they uniquely identify computers on the internet.</li>
<li>ISPs assign an IP address to your router.<ul>
<li>Earlier, it is used to be physically configured.</li>
<li>Today, it is assigned automatically using a <a target="_blank" href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP</a> Server that lives in ISP.</li>
</ul>
</li>
<li>But, if your ISP only assigns one address to the router, how are you able to connect multiple devices to the internet?<ul>
<li>That’s because your router assigns <strong>private IP addresses</strong> to the devices.</li>
<li>This private IP address is free and reserved for this use only.</li>
<li>These are the private IP address ranges:<ul>
<li>10.0.0.0 – 10.255.255.255</li>
<li>172.16.0.0 – 172.31.255.255</li>
<li>192.168.0.0 – 192.168.255.255</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="what-happens-when-you-search-on-google">What Happens When You Search on Google?</h2>
<p>With an IP address assigned to us, we are officially on the internet. Now we can communicate with other devices on the internet. So, let's try to talk with Google Servers.</p>
<p>We will open software called a browser (like chrome) and enter a query to search with Google’s search engine. The browser will do the job of converting our normal query to a proper HTTP request to google.</p>
<ul>
<li><p>Suppose we searched for cats, our request will look like:</p>
<p><code>GET /search?q=cats HTTP/1.1</code></p>
</li>
</ul>
<p>Computers communicate by sending <strong>packets,</strong> which are like <strong>virtual envelopes</strong> sent between computers. (Ultimately still 0s and 1s).</p>
<p>So we will place this request inside an envelope (as an analogy). On the envelope, we need to mention the destination and source address.</p>
<ul>
<li>We know our IP address.</li>
<li>But we don’t know the IP address of Google…?</li>
</ul>
<p>But we do know the domain name of Google - <a target="_blank" href="http://www.google.com">www.google.com</a>. To convert a domain name to its corresponding IP address, we use a <strong>Domain Name System(DNS) server.</strong></p>
<p>A request will be sent to the ISP’s DNS server for Google’s IP address.</p>
<ul>
<li>If the ISP’s DNS server doesn’t know a website’s IP address, it has been configured to ask another DNS server.</li>
<li>There exist root servers that know where to look to for an IP address if it exists.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481287984/07SvHMUln.png" alt="Packet as envelope" /></p>
<p>We have assumed our IP to be 1.2.3.4 and google’s 5.6.7.8. After sending the request off, we’ll get a response some milliseconds later. The result will be sent back in <strong>one or more</strong> packets.</p>
<ul>
<li>If the result is too large for a single envelope, sending it in one packet could take up the internet traffic.</li>
<li>To solve this, Google will divide the result into smaller fragments (say 4).<ul>
<li>Put the fragments into different envelopes.</li>
<li>Write information on the envelopes:<ul>
<li>Return address: Google IP address</li>
<li>Delivery address: Our IP address.</li>
<li>List the number of packets on each envelope (1 of 4, 2 of 4, …).</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>What if one of the packets goes missing?</strong></p>
<p>We can logically infer which packet is missing based on the ones received. For this, we will need another protocol called <strong>TCP (Transmission control protocol)</strong> which ensures packets can get to their destination.</p>
<p>It supports <strong>sequence numbers</strong> that help data get to its destination.</p>
<ul>
<li>When missing a packet, a computer can make a request for the missing packet.</li>
<li>The computer will put packets together to get a whole file.</li>
</ul>
<p>This protocol also includes conventions for requesting services (<strong>port identifiers).</strong></p>
<ul>
<li>To make sure Google knows we’re requesting a web page and not an email or other service.</li>
</ul>
<p>If 5.6.7.8 is Google’s IP address, 5.6.7.8:80 (port 80) specifies that we want a webpage.</p>
<ul>
<li>80 means <strong>HTTP (Hypertext transfer protocol).</strong><ul>
<li><strong>The language web servers speak.</strong></li>
</ul>
</li>
<li>Emails use port 25 - SMTP.</li>
<li>Secure connection use 443 - HTTPS.</li>
</ul>
<p><strong>Therefore, on the envelope we previously saw, we must have mentioned the port as well before sending it.</strong></p>
<h2 id="what-are-the-rules-of-the-internet">What are the Rules of the Internet?</h2>
<p>We have used the term <strong>protocols</strong> multiple times till now. Protocols are just sets of rules.</p>
<ul>
<li>Humans use these all the time, such as the protocol for meeting people: handshakes. (pre-corona times!!)</li>
</ul>
<p>Internet uses these protocols to standardize all communication. </p>
<ul>
<li>HTTP, FTP, TCP/IP, etc.</li>
</ul>
<p>There is one more protocol called <strong>UDP</strong> (User datagram protocol) that can be used instead of TCP.</p>
<ul>
<li>It doesn’t guarantee delivery.</li>
<li><p>Used for video conferencing.</p>
<ul>
<li>Packets can be dropped for the sake of keeping the conversation flowing.</li>
</ul>
</li>
<li><p>Used anytime you want to keep data coming without waiting for a buffer to fill.</p>
</li>
</ul>
<h2 id="where-is-googles-server-located">Where is Google's Server Located?</h2>
<p>When we sent our envelope, our laptop didn’t know where is the Google’s server located. We knew the IP address of the server but we didn’t have a map to decide which direction to go to and we certainly cannot use Google maps 😅.</p>
<p>This again is the job of routers:</p>
<ul>
<li>Routers have a big table with IP addresses and where data should be routed to get to that destination. Often, the data is routed to the next router.</li>
</ul>
<p>The router’s purpose is to send data in the direction of a destination. The next router will send it to another until it reaches a destination.</p>
<p>The routing decisions are made using certain routing algorithms such as <strong>Dijkstra’s shortest path algorithm or distance vector routing algorithm.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481398222/m8Slahxgn.png" alt="laptop-routers-google" /></p>
<p>We can use a program called <strong>traceroute</strong> that sends packets to each router on a path to a destination, reporting the time it takes to reach that router:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481426890/uUPFyuo0U.png" alt="traceroute to www.google.com" /></p>
<ul>
<li>It took us 13 jumps to get to google finding our way through routers.</li>
<li>Also, Now we can see Google’s IP address is not 5.6.7.8 but 142.250.67.68.</li>
<li>It took us only 42.130 ms to get to Google!!!</li>
</ul>
<h2 id="what-devices-hold-the-internet-together">What Devices Hold the Internet Together?</h2>
<ul>
<li><p><strong>Undersea Cables:</strong> A submarine communications cable is a cable laid on the sea bed between land-based stations to carry telecommunication signals across stretches of ocean and sea.</p>
<p>Check out this video to see the network of undersea cables around the world:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/IlAJJI-qG2k">https://youtu.be/IlAJJI-qG2k</a></div>
</li>
<li><p><strong>Cable Modems:</strong> A cable modem is a hardware device that allows your computer to communicate with an Internet service provider over a landline connection. It converts an analog signal to a digital signal for the purpose of granting access to broadband Internet.</p>
<ul>
<li>Coaxial cable to plug into the wall.</li>
<li>Phone jacks (RJ11) as many services are bundled together these days.</li>
<li>Four jacks for ethernet cables (RJ45).</li>
<li>Devices can plug into these for internet connectivity.</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481619700/nwr0lGumO.png" alt="a RJ45 cable" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481594636/sVi8_7LpU.png" alt="a cable modem" /></p>
<ul>
<li><strong>Switch</strong>: A network switch is networking hardware that connects devices on a computer network by using packet switching to receive and forward data to the destination device.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481542710/wL3a33ptf.png" alt="Switch" /></p>
<ul>
<li><strong>Router</strong>: A router is a networking device that forwards data packets between computer networks. Routers perform the traffic directing functions on the Internet. Home routers can have wifi, firewall, and switching capabilities.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1606481566218/9RkvWpo32.png" alt="Router" /></p>
<h3 id="thanks-for-reading">Thanks For Reading 😊</h3>
<p>If you found this article helpful, please like and share!
Feedbacks are welcome in the comments.</p>
<hr />
<h4 id="you-may-also-like">You may also like:</h4>
<ul>
<li><a target="_blank" href="https://blog.yuvv.xyz/what-happens-when-you-run-a-computer-program">What Happens When You Run a Computer Program?</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/the-mutable-default-argument-mess-in-python">The Mutable Default Argument Mess in Python</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/modern-cpp-features">Modern C++ Features</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/comprehensions-in-python-explained">Comprehensions in Python: Explained</a></li>
</ul>
<p>Connect with me on <a target="_blank" href="https://twitter.com/yuvraajsj18">Twitter</a>, <a target="_blank" href="https://github.com/yuvraajsj18">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/yuvraajsj18/">LinkedIn</a>.</p>
<p>This article is inspired by a presentation I gave with my friend <a target="_blank" href="https://www.instagram.com/manmeet_brar_._/">Manmeet Brar</a> in my Computer Network class.</p>
<p>References: CS50 understanding technology.</p>
]]></content:encoded></item><item><title><![CDATA[The Mutable Default Argument Mess in Python]]></title><description><![CDATA[Meet Kevin, 🙋‍♂️ Kevin is learning Python. One day he was given a problem to solve as follows:

Design a function that appends '#' to a list provided as an argument and then prints it. If no argument is provided then the function should use an empty...]]></description><link>https://blog.yuvraj.tech/the-mutable-default-argument-mess-in-python</link><guid isPermaLink="true">https://blog.yuvraj.tech/the-mutable-default-argument-mess-in-python</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Wed, 18 Nov 2020 12:06:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1605701205295/vdeuH635-.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Meet Kevin, 🙋‍♂️ Kevin is learning Python. One day he was given a problem to solve as follows:</p>
<blockquote>
<p>Design a function that appends '#' to a list provided as an argument and then prints it. If no argument is provided then the function should use an empty list as a default.</p>
</blockquote>
<p>Kevin quickly comes up with the following solution:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">append</span>(<span class="hljs-params">l = []</span>):</span>
    l.append(<span class="hljs-string">'#'</span>)
    print(l)
</code></pre>
<p>Looks good, time for testing the solution:</p>
<pre><code class="lang-python">append([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
<span class="hljs-comment"># OUTPUT: [1, 2, 3, '#'] | OK</span>

append()
<span class="hljs-comment"># OUTPUT: ['#']    | OK</span>

append()
<span class="hljs-comment"># OUTPUT: ['#', '#']  | Strange!!</span>
</code></pre>
<ul>
<li><p>The first call to <code>append</code> worked fine. It added <strong>#</strong> to the list <code>[1, 2, 3]</code> and then printed it.</p>
</li>
<li><p>The second also worked as expected. This time no list is provided as an argument, so it used the default empty list and appended a <strong>#</strong> to it.</p>
</li>
<li><p>Now, the third call resulted in something unexpected.</p>
<p>When we once again called the <code>append</code> without argument, it printed <code>['#', '#']</code> instead of <code>['#']</code> as we got in the above call.</p>
</li>
</ul>
<h1 id="why-did-this-happened">Why did this happened?</h1>
<p>The reason this happened is that Python defines its default argument <em>only once when the function is first defined.</em></p>
<p>This is because python is parsed line by line, when the parser encounters <code>def</code> it sets the default argument to a value and that value is used in every future call.</p>
<p>This behavior of Python becomes of special concern when the default argument is a <strong>mutable</strong>.</p>
<p>As the value of <strong>, immutables</strong> can not be changed, if you update the argument variable inside the function it will create a new object and start pointing to that object instead of changing the original default object.</p>
<p>But in the case of a mutable default argument, the object created at the time of parsing the function is updated instead of creating a different object for that function call.</p>
<h2 id="solution">Solution</h2>
<p>The solution to this problem is to use an immutable default argument instead of a mutable. The preferred choice is <code>None</code> (though you can choose any immutable value).</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">append</span>(<span class="hljs-params">l = None</span>):</span>
    <span class="hljs-keyword">if</span> l <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
        l = []
    l.append(<span class="hljs-string">'#'</span>)
    print(l)
</code></pre>
<p>Let's test this solution -</p>
<pre><code class="lang-python">append([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
<span class="hljs-comment"># OUTPUT: [1, 2, 3, '#']    | OK</span>

append()
<span class="hljs-comment"># OUTPUT: ['#']     | OK</span>

append()
<span class="hljs-comment"># OUTPUT: ['#']        | Works fine!</span>
</code></pre>
<p>Great! this solution worked as expected.</p>
<p>But why? Let's take a look inside..</p>
<h2 id="why-the-solution-works">Why the solution works?</h2>
<p>Watch this video to find out what happened in the <strong>wrong version</strong> of the code -</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/NAEQd0HFxyQ">https://youtu.be/NAEQd0HFxyQ</a></div>
<p>As you can see, in this case, the original <code>l</code> was modified instead of creating a new <code>l</code>  for each function call as a <code>list</code> is a mutable value.</p>
<p>Now, see the <strong>corrected version</strong> of the code -</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/sQWhLwnAh04">https://youtu.be/sQWhLwnAh04</a></div>
<p>Here as <code>None</code> is an immutable value therefore it cannot be changed and a new list object is created for each function call.</p>
<blockquote>
<p>Note: The default argument is a property of the <strong>function object</strong> therefore, initially it is the same for all function calls.</p>
</blockquote>
<h3 id="thanks-for-reading">Thanks For Reading 😊</h3>
<p>If you found this article helpful, please like and share!
Feedbacks are welcome in the comments.</p>
<hr />
<h4 id="you-may-also-like">You may also like:</h4>
<ul>
<li><a target="_blank" href="https://blog.yuvv.xyz/modern-cpp-features">Modern C++ Features</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/what-happens-when-you-run-a-computer-program">What Happens When You Run a Computer Program?</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/comprehensions-in-python-explained">Comprehensions in Python: Explained</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/linux-commands-reference-with-examples">Linux Commands Reference With Examples</a></li>
</ul>
<p>Connect with me on <a target="_blank" href="https://twitter.com/yuvraajsj18">Twitter</a>, <a target="_blank" href="https://github.com/yuvraajsj18">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/yuvraajsj18/">LinkedIn</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Modern C++ Features]]></title><description><![CDATA[C++ is not just C with classes, it is a very powerful language that comes with many features that are provided by languages like Python and JavaScript.
In this article, I have shown a few features that you may know from Python or JavaScript that you ...]]></description><link>https://blog.yuvraj.tech/modern-cpp-features</link><guid isPermaLink="true">https://blog.yuvraj.tech/modern-cpp-features</guid><category><![CDATA[C++]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Thu, 22 Oct 2020 12:55:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1603371127422/h30B_TFru.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>C++ is not just C with classes, it is a very powerful language that comes with many features that are provided by languages like Python and JavaScript.</p>
<p>In this article, I have shown a few features that you may know from Python or JavaScript that you can use in C++ too!!</p>
<blockquote>
<p>This article is for people with a basic understanding of C++</p>
</blockquote>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#templates">Templates</a></li>
<li><a class="post-section-overview" href="#auto">Auto</a></li>
<li><a class="post-section-overview" href="#variable-argument-functions">Variable Argument Function</a></li>
<li><a class="post-section-overview" href="#standard-template-library">Standard Template Library</a></li>
<li><a class="post-section-overview" href="#range-based-for-loop">Range Based For Loop</a></li>
<li><a class="post-section-overview" href="#lambda-expressions">Lambda Expressions</a></li>
</ul>
<h2 id="heading-templates">Templates</h2>
<p>Suppose you want to write a function with the same operations on different data types. </p>
<p>This is straightforward in Python as the same variable can <em>point</em> to different objects of different types. So you can reuse the same code for all types.</p>
<p>Now, in C++ one solution is to overload the function with different types but that will require you to write a lot of code that basically does the same thing. Here comes the use of <strong>templates</strong>. </p>
<p>Instead of writing functions with different types yourself, you can have the compiler generate them for you by using templates. The compiler knows which functions to generate based on the <em>parameter</em> provided.</p>
<p>Let's see an example:</p>
<ul>
<li><p>A template function for getting the maximum of two values, the value can be of any data type.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> type&gt;    <span class="hljs-comment">// Creating a template</span>
<span class="hljs-function">type <span class="hljs-title">max</span><span class="hljs-params">(type first, type second)</span>
</span>{
    <span class="hljs-keyword">return</span> first &gt; second ? first : second;
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; max&lt;<span class="hljs-keyword">int</span>&gt;(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>) &lt;&lt; <span class="hljs-string">"\n"</span>;            <span class="hljs-comment">// 3</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; max(<span class="hljs-number">3.4f</span>, <span class="hljs-number">4.2f</span>) &lt;&lt; <span class="hljs-string">"\n"</span>;    <span class="hljs-comment">// 4.2</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; max(<span class="hljs-string">'C'</span>, <span class="hljs-string">'S'</span>) &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// S</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<ul>
<li>The first call will tell the compiler to create a function with <code>type</code> replaced by <code>int</code></li>
<li>Similarly, the second and third calls will create a function with <code>type</code> replaced by <code>float</code> and <code>char</code>.</li>
<li>In the first call we have explicitly told the compiler that type is <code>int</code> with <code>&lt;type&gt;</code> notation. </li>
</ul>
</li>
</ul>
<blockquote>
<p>You can similarly create templates for classes.</p>
<p>To learn more about templates in C++, checkout this <a target="_blank" href="https://docs.microsoft.com/en-us/cpp/cpp/templates-cpp?view=vs-2019#default-template-arguments">article</a></p>
</blockquote>
<h2 id="heading-auto">Auto</h2>
<p>You can deduce the type of a variable at compile time using the <code>auto</code> keyword.</p>
<p>This is useful when a variable has a complicated type.</p>
<p>Here is an example of <code>auto</code></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-keyword">auto</span> an_int = <span class="hljs-number">50</span>;
    <span class="hljs-keyword">auto</span> a_float = <span class="hljs-number">10.5f</span>;
    <span class="hljs-keyword">auto</span> a_double = <span class="hljs-number">100.12</span>;
    <span class="hljs-keyword">auto</span> a_char = <span class="hljs-string">'S'</span>;
    <span class="hljs-keyword">auto</span> a_string = <span class="hljs-string">"String"</span>;

    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; an_int &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// 50</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; a_float &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// 10.5</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; a_double &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// 100.12</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; a_char &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// S</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; a_string &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// String</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<blockquote>
<p>To learn more about auto in C++, read this <a target="_blank" href="https://docs.microsoft.com/en-us/cpp/cpp/auto-cpp?view=vs-2019">article</a></p>
</blockquote>
<h2 id="heading-variable-argument-functions">Variable Argument Functions</h2>
<p>If you know Python then you must have used <code>*</code> for creating a function with a variable number of arguments.</p>
<p>You can do the same in C++ using Ellipsis and variadic templates.</p>
<p>Let us understand this with an example -</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> type&gt;
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sum</span><span class="hljs-params">(type n)</span>
</span>{
    <span class="hljs-keyword">return</span> n;
}

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> first, <span class="hljs-keyword">typename</span>... types&gt;    <span class="hljs-comment">// Packing Arguments</span>
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sum</span><span class="hljs-params">(first n, types ...args)</span>        <span class="hljs-comment">// Expanding Arguments</span>
</span>{
    <span class="hljs-keyword">return</span> n + sum(args...);    
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-keyword">int</span> sum3 = sum(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>);
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; sum3 &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// 6</span>
    <span class="hljs-keyword">int</span> sum5 = sum(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>);
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; sum5 &lt;&lt; <span class="hljs-string">"\n"</span>;        <span class="hljs-comment">// 15</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>Here, <code>...</code> after <code>typename</code> is packing all the arguments passed when calling into <code>types</code>, and then we are unpacking them again with <code>...</code> before <code>args</code>. </p>
<p>Then we have used recursion to call a function with arguments one less than the original.</p>
<p><strong>Similarly you can create a print function that takes any number of arguments</strong> - </p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> First&gt;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">(First first)</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; first &lt;&lt; <span class="hljs-string">"\n"</span>;
}

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> First, <span class="hljs-keyword">typename</span> ... Types&gt;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">(First first, Types ... args)</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; first &lt;&lt; <span class="hljs-string">" "</span>;
    print(args...);
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    print(<span class="hljs-string">"One"</span>, <span class="hljs-string">"Two"</span>);
    print(<span class="hljs-string">"One"</span>, <span class="hljs-string">"Two"</span>, <span class="hljs-string">"Three"</span>, <span class="hljs-string">"Four"</span>);

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<blockquote>
<p>Learn more about ellipsis and variadic templates in this <a target="_blank" href="https://docs.microsoft.com/en-us/cpp/cpp/ellipses-and-variadic-templates?view=vs-2019">article</a></p>
</blockquote>
<h2 id="heading-standard-template-library">Standard Template Library</h2>
<p>In C++, only a few primitive data types are available inbuilt, unlike Python which provides a dynamic list, dictionary, set and tuples, etc.</p>
<p>Standard template library(STL) is a software library for C++, which provides these kinds of data structures and algorithms.</p>
<p>STL provides the following four components:</p>
<ul>
<li><em>Algorithms</em>: searching, sorting, etc.</li>
<li><em>Containers</em>: Sequences such as vector, list. Queue, stack, map, set, etc.</li>
<li><em>Functions</em></li>
<li><em>Iterators</em></li>
</ul>
<p>It is called a template library because it uses the C++ template feature discussed above.</p>
<p>Let's see one example of a container: vector.</p>
<h4 id="heading-vector">Vector</h4>
<p>The STL <code>vector</code> class is a class template for sequence containers.</p>
<p>It stores elements of a given type in a linear order and allows fast random access to any element. Sounds like an array? Yes, it is an array but it is dynamic means its size can change when needed.</p>
<p>This example shows how to create and use a vector:</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;    // STL Header file for vector class</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt; numbers{<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>};

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; numbers.size(); i++)
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; numbers[i] &lt;&lt; <span class="hljs-string">" "</span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"\n"</span>;  <span class="hljs-comment">// OUTPUT: 1 2 3 4 5</span>

    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">char</span>&gt; alphabets;    <span class="hljs-comment">// Empty vector</span>
    alphabets.push_back(<span class="hljs-string">'a'</span>);    <span class="hljs-comment">// adding an element to back of vector</span>
    alphabets.push_back(<span class="hljs-string">'b'</span>);
    alphabets.push_back(<span class="hljs-string">'c'</span>);

    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; alphabets[<span class="hljs-number">1</span>] &lt;&lt; <span class="hljs-string">"\n"</span>;  <span class="hljs-comment">// OUTPUT: b</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<blockquote>
<p>To learn more about STL, checkout this <a target="_blank" href="https://docs.microsoft.com/en-us/cpp/standard-library/cpp-standard-library-overview?view=vs-2019">article</a></p>
</blockquote>
<h2 id="heading-range-based-for-loop">Range Based For Loop</h2>
<p>In the previous example, we used a simple for loop to iterate over our vector. We can do the same with the better <em>range-based for loop</em>. </p>
<p><strong>Syntax</strong>:</p>
<pre><code class="lang-pseudocode">for (for-range-declaration : expression)
    statement
</code></pre>
<p>So this is how we can change the previous code with a range based for loop:</p>
<pre><code class="lang-cpp"><span class="hljs-comment">// For printing the numbers vector</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> x : numbers)
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; x &lt;&lt; <span class="hljs-string">" "</span>;

<span class="hljs-comment">// For printing the alphabets vector</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> ch : alphabets)    <span class="hljs-comment">// Notice the use of auto - Recommended</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; ch &lt;&lt; <span class="hljs-string">" "</span>;

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> i : {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>})
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; i &lt;&lt; <span class="hljs-string">" "</span>;    <span class="hljs-comment">// 1 2 3</span>

<span class="hljs-keyword">int</span> arr[] = {<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>};
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> j : arr)
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; j &lt;&lt; <span class="hljs-string">" "</span>;    <span class="hljs-comment">// 4 5 6</span>
</code></pre>
<p>Here <code>x</code> will point to an individual element in <code>numbers</code> one by one.</p>
<blockquote>
<p>To learn more about range-based loops, read this <a target="_blank" href="https://docs.microsoft.com/en-us/cpp/cpp/range-based-for-statement-cpp?view=vs-2019">article</a></p>
</blockquote>
<h2 id="heading-lambda-expressions">Lambda Expressions</h2>
<p>A lambda expression is a convenient way of defining an anonymous function.</p>
<p>Lambdas are used to encapsulate a few lines of code that are passed to algorithms and other functions.</p>
<p><strong>Syntax</strong>:</p>
<p><img src="https://docs.microsoft.com/en-us/cpp/cpp/media/lambdaexpsyntax.png?view=vs-2019" alt="Lambda Syntax" /></p>
<ol>
<li><p><em>capture clause</em>: Specifies which variables are <strong>captured</strong> from the surrounding scope and whether the capture is by value or by reference.</p>
<ul>
<li><p>Variables prefixed with &amp; are accessed by reference other by value.</p>
</li>
<li><p>Empty clause <code>[ ]</code> indicates that the lambda body has no access to variables in the enclosing scope.</p>
</li>
<li><code>[&amp;]</code> means all variables are captured by reference.</li>
<li><code>[=]</code> means all variables are captured by value.</li>
</ul>
</li>
<li><p><em>parameter list</em> (optional): A lambda can accept input parameters just like a normal function. It is optional and you can leave the parenthesis empty in case of no parameters.</p>
</li>
<li><p><em>mutable specification</em> (optional): <code>mutable</code> keyword allows us to modify a value captured in the lambda body. (Usage is shown in the example below).</p>
</li>
<li><em>exception-specification</em> (optional): You can use the <code>noexcept</code> exception specification to indicate that the lambda expression does not throw any exceptions.</li>
<li><em>trailing-return-type</em> (optional): Just like normal function a lambda also have a return type. You can omit the return-type part of a lambda expression if the lambda body contains just one return statement or the expression does not return a value.</li>
<li><em>lambda body</em>: A lambda body can contain anything that a normal function's body can contain.</li>
</ol>
<p>These are a few examples of lambda functions:</p>
<ul>
<li><p>Here we have used a lambda function that finds the square of a number. The type of the lambda is automatically deduced using auto and it is stored in an identifier <code>square</code>.</p>
<p>The return type is automatically deduced to <code>int</code>.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-keyword">auto</span> square = [](<span class="hljs-keyword">int</span> n) {
      <span class="hljs-keyword">return</span> n * n;  
    };

    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Square of 2 = "</span> &lt;&lt; square(<span class="hljs-number">2</span>) &lt;&lt; <span class="hljs-string">"\n"</span>;
    <span class="hljs-comment">// Square of 2 = 4</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</li>
<li><p>Here, we have shown the usage of the <code>mutable</code>  keyword, without using it we would have received an error saying <code>outer</code> is read-only.</p>
<p>Moreover, the value of the <code>outer</code> is unchanged outside lambda as it was captured by value <code>[=]</code>.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-keyword">int</span> outer = <span class="hljs-number">50</span>;

    <span class="hljs-keyword">auto</span> fn = [=]() <span class="hljs-keyword">mutable</span> {
        outer = <span class="hljs-number">100</span>;    <span class="hljs-comment">// OK, because of mutable</span>
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Outer = "</span> &lt;&lt; outer &lt;&lt; <span class="hljs-string">"\n"</span>;   <span class="hljs-comment">// Outer = 100</span>
    };

    fn();
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Outer = "</span> &lt;&lt; outer &lt;&lt; <span class="hljs-string">"\n"</span>;   <span class="hljs-comment">// Outer = 50</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</li>
<li><p>Here, we have used lambda to pass a function to the for_each algorithm.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;algorithm&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt; nums{<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>};

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> x : nums) <span class="hljs-comment">// 1 2 3 4 5 6 </span>
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; x &lt;&lt; <span class="hljs-string">" "</span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"\n"</span>;

    <span class="hljs-comment">// Square every number</span>
    <span class="hljs-built_in">std</span>::for_each(begin(nums), end(nums), [](<span class="hljs-keyword">int</span>&amp; n) {n = n * n;}); 

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> x : nums) <span class="hljs-comment">// 1 4 9 16 25 36 </span>
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; x &lt;&lt; <span class="hljs-string">" "</span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"\n"</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</li>
</ul>
<blockquote>
<p>To learn more about lambda functions, checkout this <a target="_blank" href="[https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=vs-2019#:~:text=In%20C%2B%2B11%20and,an%20argument%20to%20a%20function.](https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=vs-2019#:~:text=In C%2B%2B11 and,an argument to a function.">article</a>)</p>
</blockquote>
<h2 id="heading-endnote">EndNote</h2>
<p>This article was only supposed to <em>introduce</em> you to some modern powerful features provided by the C++ language.</p>
<p>If you want to learn more about these features, you may check out the links provided for each topic. The best way to learn these is by using it.</p>
<p>C++ has more amazing and modern features contrary to the belief that it is an old and outdated language.</p>
<p><strong>Share your opinion in the comments</strong>.</p>
<h3 id="heading-thanks-for-reading">Thanks For Reading</h3>
<hr />
<h4 id="heading-read-more-on-scaler-topics">Read more on Scaler Topics</h4>
<ul>
<li><a target="_blank" href="https://www.scaler.com/topics/abstract-class-in-cpp/">Abstract Classes in C++</a></li>
<li><a target="_blank" href="https://www.scaler.com/topics/virtual-base-class-in-cpp/">Virtual Base Class in C++</a></li>
<li><a target="_blank" href="https://www.scaler.com/topics/difference-between-c-and-cplusplus/">Difference Between C and C++</a></li>
<li><a target="_blank" href="https://www.scaler.com/topics/constructor-and-destructor-in-cpp/">Constructor and Destructor in C++</a></li>
</ul>
<p>If you want to learn C++ from basic to advanced, do check out the <a target="_blank" href="https://www.scaler.com/topics/cpp/">C++ course from Scaler Topics</a>.</p>
<h4 id="heading-you-may-also-like">You may also like:</h4>
<ul>
<li><a target="_blank" href="https://blog.yuvv.xyz/how-to-create-header-files-in-cpp">How to Create Header Files in C++</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/what-happens-when-you-run-a-computer-program">What Happens When You Run a Computer Program?</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/comprehensions-in-python-explained">Comprehensions in Python: Explained</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/linux-commands-reference-with-examples">Linux Commands Reference With Examples</a></li>
</ul>
<p>Connect with me on <a target="_blank" href="https://twitter.com/yuvraajsj18">Twitter</a>, <a target="_blank" href="https://github.com/yuvraajsj18">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/yuvraajsj18/">LinkedIn</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to Create Header Files in C++]]></title><description><![CDATA[If you are a C++ programmer, then you must have used predefined header files like <iostream>, <string>, <cmath> etc.
In this article, I have shown how to create your own header files in the right way.
This article is divided into two sections - 

Cre...]]></description><link>https://blog.yuvraj.tech/how-to-create-header-files-in-cpp</link><guid isPermaLink="true">https://blog.yuvraj.tech/how-to-create-header-files-in-cpp</guid><category><![CDATA[C++]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Wed, 21 Oct 2020 11:14:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1603380481315/ItwtsEY3R.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are a C++ programmer, then you must have used predefined header files like <code>&lt;iostream&gt;</code>, <code>&lt;string&gt;</code>, <code>&lt;cmath&gt;</code> etc.</p>
<p>In this article, I have shown how to create your own header files in the right way.</p>
<p>This article is divided into two sections - </p>
<ol>
<li><a class="post-section-overview" href="#creating-ordinary-header-files">Creating Ordinary Header Files</a></li>
<li><a class="post-section-overview" href="#creating-template-header-files">Creating Template Header Files</a></li>
</ol>
<h2 id="creating-ordinary-header-files">Creating Ordinary Header Files</h2>
<p>Suppose you have created the following header file with the following line in it- </p>
<pre><code class="lang-cpp"><span class="hljs-keyword">const</span> <span class="hljs-keyword">int</span> SOME_CONSTANT = <span class="hljs-number">50</span>;    <span class="hljs-comment">// first.h</span>
<span class="hljs-comment">// ...More</span>
</code></pre>
<p>Now you have a second header file which has included the above file -</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"first.h"</span>    <span class="hljs-comment">// second.h</span></span>
<span class="hljs-comment">// ...More</span>
</code></pre>
<p>And you have one more C++ file which includes both these files - </p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"first.h"</span>    <span class="hljs-comment">// third.cpp</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"second.h"</span>    </span>
<span class="hljs-comment">// ...More</span>
</code></pre>
<p>Now, when you compile your <code>third.cpp</code> file, you will get an error like this -</p>
<blockquote>
<p><strong>error: redefinition of ‘const int SOME_CONSTANT’
    1 | const int SOME_CONSTANT = 50;</strong></p>
</blockquote>
<p>Because the <code>first.h</code> file is included twice, therefore its content also gets copied twice in the <code>third.cpp</code> file.</p>
<p>To prevent this we should use <strong>Header Guards</strong>.</p>
<h3 id="using-header-guards">Using Header Guards</h3>
<p>Header Guards are conditional compilations directives which mean they are evaluated at compilation time and the compiler will perform operations on the basis of its result.</p>
<p>Header Guards look like this -</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> HEADERFILE_H</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> HEADERFILE_h</span>

<span class="hljs-comment">// Declarations goes here</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
</code></pre>
<p><code>ifndef</code> means if not defined, if the HEADERFILE_H is not defined it will define it, otherwise if it is already defined it will skip compiling everything between <code>ifndef</code> and <code>endif</code>.</p>
<p><em>Now, we will update our previous example with header guards</em></p>
<ul>
<li><p><code>first.h</code></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> FIRST_H</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> FIRST_H</span>

<span class="hljs-keyword">const</span> <span class="hljs-keyword">int</span> SOME_CONSTANT = <span class="hljs-number">50</span>;
<span class="hljs-comment">// ...More</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
</code></pre>
</li>
<li><p><code>second.h</code></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> SECOND_H</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SECOND_H</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"first.h"</span></span>
<span class="hljs-comment">// ...More</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
</code></pre>
</li>
<li><p><code>third.cpp</code></p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"first.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"second.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-comment">// Using first.h and second.h</span>
}
</code></pre>
</li>
</ul>
<p>Now, our <code>third.cpp</code> file will compile without error.</p>
<h3 id="one-complete-example">One Complete Example</h3>
<p>Let's look at one more example -</p>
<p>In this example, we will create the following three files -</p>
<ul>
<li><code>headerfiles.h</code> - Provides constants, functions and class declarations for use.</li>
<li><code>definitions.cpp</code> - Contains definitions for the headerfiles.h functions and classes.</li>
<li><code>main.cpp</code> - Consumes the functions and classes declared in headerfiles.</li>
</ul>
<h5 id="headerfileh">headerfile.h</h5>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> HEADERFILE_H</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> HEADERFILE_H</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string&gt;</span></span>

<span class="hljs-keyword">const</span> <span class="hljs-keyword">int</span> SOME_CONSTANT = <span class="hljs-number">50</span>;

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">(<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> message)</span></span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SomeClass</span>
{</span>
    <span class="hljs-keyword">private</span>:
        <span class="hljs-keyword">int</span> var;

    <span class="hljs-keyword">public</span>:
        SomeClass(<span class="hljs-keyword">int</span> var);
        <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span></span>;
};

<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
</code></pre>
<h5 id="definitionscpp">definitions.cpp</h5>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"headerfile.h"</span></span>

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">(<span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> message)</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"Message = "</span> &lt;&lt; message &lt;&lt; <span class="hljs-string">"\n"</span>;
}

SomeClass::SomeClass(<span class="hljs-keyword">int</span> var)
{
    <span class="hljs-keyword">this</span>-&gt;var = var;
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">SomeClass::print</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; <span class="hljs-string">"var = "</span> &lt;&lt; var &lt;&lt; <span class="hljs-string">"\n"</span>;
}
</code></pre>
<h5 id="maincpp">main.cpp</h5>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"headerfile.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    print(<span class="hljs-string">"Hello, World"</span>);  <span class="hljs-comment">// OUTPUT: Message = Hello, World</span>

    <span class="hljs-function">SomeClass <span class="hljs-title">object</span><span class="hljs-params">(<span class="hljs-number">50</span>)</span></span>;

    object.print();     <span class="hljs-comment">// OUTPUT: var = 50</span>

    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; SOME_CONSTANT &lt;&lt; <span class="hljs-string">"\n"</span>; <span class="hljs-comment">// OUTPUT: 50</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>This is the right way to create header files, you separate the <strong>declarations</strong> and <strong>definitions</strong> in two files and only include the header file when necessary.</p>
<p>You will link the definitions file when compiling like this -</p>
<blockquote>
<p><strong>g++ -o main main.cpp definitions.cpp</strong></p>
</blockquote>
<h2 id="creating-template-header-files">Creating Template Header Files</h2>
<p>Now in case of templates, you can't simply create two different files for declarations and definitions like the previous example because, when compilers compile the program it needs to replace the generic types with the required template arguments.</p>
<p>For example -</p>
<pre><code class="lang-cpp"><span class="hljs-meta"># foo.h</span>
<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> type&gt;
<span class="hljs-function">type <span class="hljs-title">sum</span><span class="hljs-params">(type a, type b)</span>
</span>{
    type result = a + b;
    <span class="hljs-keyword">return</span> result;
}

<span class="hljs-meta"># main.cpp</span>
sum(<span class="hljs-number">50</span>, <span class="hljs-number">100</span>);    <span class="hljs-comment">// This will create a function sum with type replaced with int everywhere</span>
</code></pre>
<p>If we haven't provided the definition in the header file, the compiler won't be able to do perform the replacement(or instantiation).</p>
<p>Now, to separate our definition and declaration in the case of templates we can use the following way -</p>
<h5 id="maxh">max.h</h5>
<p>Header file to store function and class declaration</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> MAX_H</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MAX_H</span>

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> type&gt;
<span class="hljs-function">type <span class="hljs-title">max</span><span class="hljs-params">(type a, type b)</span></span>;

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"max.tpp"</span>    <span class="hljs-comment">// IMPORTANT: We are including our definitions in the header file at the end</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
</code></pre>
<h5 id="maxtpp">max.tpp</h5>
<p>Definition file, note that its extension is <code>.tpp</code> and not <code>.cpp</code> as per the convention for template definitions files.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"max.h"</span></span>

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> type&gt;
<span class="hljs-function">type <span class="hljs-title">max</span><span class="hljs-params">(type a, type b)</span>
</span>{
    <span class="hljs-keyword">return</span> a &gt; b ? a : b;
}
</code></pre>
<h5 id="maincpp">main.cpp</h5>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"max.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; max(<span class="hljs-number">50</span>, <span class="hljs-number">100</span>) &lt;&lt; <span class="hljs-string">"\n"</span>;   <span class="hljs-comment">// 100</span>

    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<h4 id="thanks-for-reading">Thanks for reading</h4>
<hr />
<h4 id="references">References:</h4>
<ul>
<li>https://www.learncpp.com/cpp-tutorial/header-guards/</li>
<li>https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file</li>
</ul>
<h4 id="you-may-also-like">You may also like:</h4>
<ul>
<li><a target="_blank" href="https://blog.yuvv.xyz/what-happens-when-you-run-a-computer-program">What Happens When You Run a Computer Program?</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/comprehensions-in-python-explained">Comprehensions in Python: Explained</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/linux-commands-reference-with-examples">Linux Commands Reference With Examples</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[What Happens When You Run a Computer Program?]]></title><description><![CDATA[Introduction
How do you run a computer program?

You may double click the icon.
Or

You may run it through a terminal if you happened to be a programmer.


In both cases the Operating System launches the program after performing some operations and h...]]></description><link>https://blog.yuvraj.tech/what-happens-when-you-run-a-computer-program</link><guid isPermaLink="true">https://blog.yuvraj.tech/what-happens-when-you-run-a-computer-program</guid><category><![CDATA[operating system]]></category><category><![CDATA[process]]></category><category><![CDATA[cpu]]></category><dc:creator><![CDATA[Yuvraj Singh Jadon]]></dc:creator><pubDate>Sat, 12 Sep 2020 07:50:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1599897005239/u707SkB3B.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>How do you run a computer program?</p>
<ul>
<li><p>You may double click the icon.</p>
<p>Or</p>
</li>
<li><p>You may run it through a terminal if you happened to be a programmer.</p>
</li>
</ul>
<p>In both cases the Operating System <strong>launches</strong> the program after performing some operations and hand it to the <strong>CPU</strong> to execute it.</p>
<p>Let us look at the journey of a program from sitting in the hard disk to being executed by the <strong>processor</strong>.</p>
<h2 id="what-is-a-computer-program">What is a Computer Program?</h2>
<p>A computer program is an <em>executable</em> version of the source file written by a programmer that contains a <em>list of instructions</em>.</p>
<p>A computer program is stored on a <strong>hard disk</strong> until requested to be executed by a user, therefore it is known as a <strong>passive entity</strong>.</p>
<p>The moment you request execution of a computer program, The <strong>Operating System</strong>(OS) comes into play. It is the job of OS to <strong>transform</strong> the passive program into an active entity that can be run by a processor.</p>
<h2 id="process-transformation-of-a-program">Process: Transformation of a Program</h2>
<p>The OS transforms the passive program into an <strong>active entity</strong> by:</p>
<ul>
<li><p>Copying all the instructions into <strong>random-access memory</strong>(RAM), this is known as <strong>loading </strong>the program.</p>
</li>
<li><p>Allocating computer resources such as:</p>
<ul>
<li><p>Call Stack: Memory to store function parameters, local variables, and return address.</p>
</li>
<li><p>Data Sections: Memory to store global variables.</p>
</li>
<li>Heap: Memory that is dynamically allocated during run time.</li>
<li>The current Activity of the process is represented by the processor's registers' values such as <strong>Program Counter</strong> that stores the address of the next instruction to be executed.</li>
</ul>
</li>
</ul>
<p>This active form of a computer program is known as a <strong>process</strong>.</p>
<blockquote>
<p>One thing to note is - if you run the same program multiple times, for instance, you open chrome twice you will be creating two different processes from one program. Although both processes will contain the same instructions in <strong>text segment</strong>, their data may be different.</p>
</blockquote>
<p><strong>Diagrammatic Representation of a process in memory:</strong></p>
<p><img src="https://github.com/yuvraajsj18/Operating-Systems/raw/master/notes/processes/What%20Happens%20When%20You%20Run%20a%20Computer%20Program.assets/image-20200912000950072.png" alt="A Process in memory" /></p>
<h2 id="from-memory-to-cpu">From Memory to CPU</h2>
<p>Now our computer program has reached the memory and is waiting for its turn to be executed by CPU.</p>
<p>Once, Its turn arrives, the OS directs the CPU to begin running at the first instruction in the process's text segment in memory.</p>
<p>Then Its CPU's job to execute our program <strong><em>instruction by instruction</em></strong>.</p>
<p>These instructions are in machine code(binary) and are extremely simple like adding two numbers or deciding if a number is equal to zero or not.</p>
<blockquote>
<p>Saying that a CPU can execute 2 billion operations per second means that CPU can execute 2 billion lines of machine code per second.</p>
</blockquote>
<p>CPU runs this instruction using a <strong>fetch/execute</strong> cycle:</p>
<ol>
<li><p><strong>Fetch</strong> instruction from memory.</p>
</li>
<li><p><strong>Decode</strong> the instruction.</p>
<p>We need to decode the instruction because each binary sequence in instruction corresponds to a  particular operation depending on the CPU design.</p>
<p>For Example: In <code>0 001 0000 0010 0100</code>  the second sequence of 3 bit <code>001</code> may mean to <code>add</code> the number at address (referred by the last three sequences of 4 bits) to the value already stored in instructions.</p>
</li>
<li><p><strong>Fetch Operand</strong> if necessary, this means that if there is another value required to operate fetch it from its address in memory, in the previous example our operand address was <code>0000 0010 0100</code>.</p>
</li>
<li><p><strong>Execute</strong> - Finally, execute the operation by performing the required logic in the CPU.</p>
</li>
</ol>
<p><img src="https://github.com/yuvraajsj18/Operating-Systems/raw/master/notes/processes/What%20Happens%20When%20You%20Run%20a%20Computer%20Program.assets/image-20200912122757814.png" alt="Fetch/Execute Cycle Diagram" /></p>
<h2 id="termination">Termination</h2>
<p>A program may be terminated because of the following reason:</p>
<ol>
<li>Program Exists Normally.</li>
<li>Program Stuck/Infinite Loop - Abnormal Exit.</li>
<li>Running out of memory.</li>
<li>Memory Access Error - When the program tries to access the memory of another program the OS kills it.</li>
</ol>
<p>After termination, the OS will reclaim the memory provided to the program to run.</p>
<h2 id="takeaways">Takeaways</h2>
<ul>
<li>A computer program is a passive entity sitting in the hard disk.</li>
<li>A process is an active entity in RAM that stores the program code and has associated resources.</li>
<li>CPU runs the instructions in the process text segment line by line.</li>
<li>The OS keeps everything organized.</li>
</ul>
<p><img src="https://github.com/yuvraajsj18/Operating-Systems/raw/master/notes/processes/What%20Happens%20When%20You%20Run%20a%20Computer%20Program.assets/image-20200912123516818.png" alt="CPU, RAM, Storage" /></p>
<hr />
<h4 id="references">References</h4>
<ul>
<li>Operating System Concepts - Book by Avi Silberschatz</li>
<li><a target="_blank" href="https://web.stanford.edu/class/cs101/software-1.html">Stanford cs101</a></li>
</ul>
<p>Hope you found this article helpful and interesting, if you have any feedback please comment down below!</p>
<h4 id="you-may-also-like">You may also like:</h4>
<ul>
<li><a target="_blank" href="https://blog.yuvv.xyz/how-to-create-header-files-in-cpp">How to Create Header Files in C++</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/modern-cpp-features">Modern C++ Features</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/comprehensions-in-python-explained">Comprehensions in Python: Explained</a></li>
<li><a target="_blank" href="https://blog.yuvv.xyz/linux-commands-reference-with-examples">Linux Commands Reference With Examples</a></li>
</ul>
<p>Connect with me on <a target="_blank" href="https://twitter.com/yuvraajsj18">Twitter</a>, <a target="_blank" href="https://github.com/yuvraajsj18">GitHub</a>, and <a target="_blank" href="https://www.linkedin.com/in/yuvraajsj18/">LinkedIn</a>.</p>
<p><strong>Thanks for reading</strong></p>
]]></content:encoded></item></channel></rss>