<?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[Swarnim Walavalkar's Blog]]></title><description><![CDATA[Building software as an instrument of progress.]]></description><link>https://hashnode.swarnimwalavalkar.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 10 May 2026 19:18:26 GMT</lastBuildDate><atom:link href="https://hashnode.swarnimwalavalkar.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Build a MongoDB CRUD API with NodeJS]]></title><description><![CDATA[🎯 Objectives:

Build a MongoDB CURD API with NodeJS

👨‍💻 Technologies Used:

ExpressJS
Monk
Joi

📃 Prerequisites:

Javascript
NodeJS
ExpressJS
MongoDB Setup and Running on your machine

Difficulty: 🟡 Intermediate
Setup
Start off by intializing a...]]></description><link>https://hashnode.swarnimwalavalkar.com/build-a-mongodb-crud-api-with-nodejs</link><guid isPermaLink="true">https://hashnode.swarnimwalavalkar.com/build-a-mongodb-crud-api-with-nodejs</guid><category><![CDATA[Node.js]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[Express.js]]></category><dc:creator><![CDATA[Swarnim Walavalkar]]></dc:creator><pubDate>Mon, 21 Sep 2020 13:36:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1600868248667/Nzfj-Pp2e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="objectives">🎯 Objectives:</h1>
<ul>
<li>Build a MongoDB CURD API with NodeJS</li>
</ul>
<h1 id="technologies-used">👨‍💻 Technologies Used:</h1>
<ul>
<li><a target="_blank" href="https://expressjs.com/">ExpressJS</a></li>
<li><a target="_blank" href="https://automattic.github.io/monk/">Monk</a></li>
<li><a target="_blank" href="https://joi.dev/">Joi</a></li>
</ul>
<h1 id="prerequisites">📃 Prerequisites:</h1>
<ul>
<li>Javascript</li>
<li>NodeJS</li>
<li>ExpressJS</li>
<li>MongoDB Setup and Running on your machine</li>
</ul>
<h1 id="difficulty-intermediate">Difficulty: 🟡 Intermediate</h1>
<h2 id="setup"><strong>Setup</strong></h2>
<p>Start off by intializing a new NodeJS project inside an empty directory and installing <em>Monk</em>, <em>Express</em>, and <em>Joi</em>.</p>
<ul>
<li>Init a node project</li>
</ul>
<pre><code class="lang-bash">npm init -y
</code></pre>
<ul>
<li>Install express, monk, joi</li>
</ul>
<pre><code class="lang-bash">npm i express monk joi
</code></pre>
<h2 id="basic-express-server">Basic Express Server</h2>
<p>Then, Lets setup a basic express server to make sure everything is running as intended...</p>
<p><strong>Setup a Hello World Server</strong></p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>)
<span class="hljs-keyword">const</span> app = express()
<span class="hljs-keyword">const</span> port = <span class="hljs-number">3030</span>

<span class="hljs-comment">//Express.json to parse the request json body into useable Javascript Objects</span>
app.use(express.json())

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send(<span class="hljs-string">"&lt;h1&gt;Hello World!&lt;/h1&gt;"</span>)
})

app.listen(port, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port http://localhost:<span class="hljs-subst">${port}</span>`</span>)
})
</code></pre>
<p>Run the application and check on your specified port</p>
<pre><code class="lang-bash">node app.js
</code></pre>
<h2 id="setup-monk"><strong>Setup Monk</strong></h2>
<p>Monk is going to be the library we use to interface with the mongodb database.</p>
<p>Lets Import it in. After that connect it to the mongodb server running in your system</p>
<p>the port will likely be 27017. If in doubt refer to your mongodb daemon.</p>
<blockquote>
<p>💡 Make sure you have the mongodb deamon running on your system.</p>
</blockquote>
<p>The next thing we'll do is create and set the collection variable to the working collection we'll do all our operations on this object.</p>
<p>Then we run a quick little log letting us know when the application has successfully connected to the database</p>
<pre><code class="lang-jsx"><span class="hljs-comment">//import monk</span>
<span class="hljs-keyword">const</span> monk = <span class="hljs-built_in">require</span>(<span class="hljs-string">"monk"</span>)

<span class="hljs-comment">//connect to mongo database</span>
<span class="hljs-keyword">const</span> dbUrl = <span class="hljs-string">"localhost:27017/crud_api"</span>
<span class="hljs-keyword">const</span> db = monk(dbUrl)

<span class="hljs-comment">// this collection variable will have the collection we'll be working with</span>
<span class="hljs-keyword">const</span> collection = db.get(<span class="hljs-string">"documents"</span>)

<span class="hljs-comment">//Notifies when the database is connected successfully</span>
db.then(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Database connected sucessfully`</span>)
})
</code></pre>
<h2 id="crud-routes">CRUD Routes</h2>
<h3 id="get-all-documents-from-database"><strong>Get all documents from database</strong></h3>
<pre><code class="lang-jsx">app.get(<span class="hljs-string">"/"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-comment">//Get all documents in the data variable using the collection.find() method</span>
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> collection.find()
  res.send(data)
})
</code></pre>
<p>We call the <em>collection.find()</em> method with no arguments which returns all documents in the collection.</p>
<p>The Method returns a promise which resolves to an array of objects which we later send in our response.</p>
<h3 id="find-one-document-with-an-id"><strong>Find one Document with an ID</strong></h3>
<pre><code class="lang-jsx"><span class="hljs-comment">//Get a Specific Document with provided ID</span>
app.get(<span class="hljs-string">"/:id"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-comment">//Find the document with the given id</span>
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> <span class="hljs-built_in">document</span> = <span class="hljs-keyword">await</span> collection.findOne({
      <span class="hljs-attr">_id</span>: req.params.id,
    })

    <span class="hljs-comment">//Send the found document in the response</span>
    res.send(<span class="hljs-built_in">document</span>)
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-comment">//Incase of an errror send a 404 NOT FOUND</span>
    res.status(<span class="hljs-number">404</span>).send({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Document Not Found"</span> })
  }
})
</code></pre>
<p>Very similarly with this one, We call the <em>collection.findOne()</em> method this time with an object containing the filters to find the document through. In this case just the <em>id</em>.</p>
<p>This also returns a promise which resolves to the found document which we send as our response.</p>
<p>Incase of an error we send a 404 not found status code along with an error message.</p>
<h3 id="insert-documents-to-db">Insert <strong>Documents to DB</strong></h3>
<p>Before we could write the POST and PUT methods, we need to implement validation</p>
<h3 id="setup-joi-and-request-schema"><strong>Setup Joi and Request Schema</strong></h3>
<p>Joi will be the library I'm going to use to handle request validation.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Joi Setup</span>
<span class="hljs-keyword">const</span> Joi = <span class="hljs-built_in">require</span>(<span class="hljs-string">"joi"</span>)

<span class="hljs-comment">// Request Schema For the Post Method</span>
<span class="hljs-keyword">const</span> BookPostSchema = Joi.object({
  <span class="hljs-attr">title</span>: Joi.string().required(),
  <span class="hljs-attr">author</span>: Joi.string().required(),
  <span class="hljs-attr">length</span>: Joi.number().integer(),
  <span class="hljs-attr">rating</span>: Joi.number().max(<span class="hljs-number">5</span>),
})
</code></pre>
<p>This schema object will be used to validate data coming in from the POST method.</p>
<p><strong>Validate Data in the Post method</strong></p>
<pre><code class="lang-jsx"><span class="hljs-comment">//Insert a single document in the database</span>
app.post(<span class="hljs-string">"/"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">//Validate the request body</span>
    <span class="hljs-keyword">const</span> requestData = <span class="hljs-keyword">await</span> BookPostSchema.validateAsync(req.body)
    <span class="hljs-comment">//Insert it in the Database</span>
    <span class="hljs-keyword">const</span> insertedData = <span class="hljs-keyword">await</span> collection.insert(requestData)
    <span class="hljs-comment">//Send a 201 (Created) status code and the newly created data object</span>
    res.status(<span class="hljs-number">201</span>).send(insertedData)
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-comment">//In case of an error send the error object along with a 400 (Bad Request) status code</span>
    res.send(error)
  }
})
</code></pre>
<p><strong>Request Schema for the put method</strong></p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Request For the Put Method Schema</span>
<span class="hljs-keyword">const</span> BookUpdateSchema = Joi.object({
  <span class="hljs-attr">title</span>: Joi.string(),
  <span class="hljs-attr">author</span>: Joi.string(),
  <span class="hljs-attr">length</span>: Joi.number().integer(),
  <span class="hljs-attr">rating</span>: Joi.number().max(<span class="hljs-number">5</span>),
})
</code></pre>
<p>This schema object will be used to validate data coming in from the PUT method.</p>
<h3 id="put-route"><strong>Put</strong> <strong>Route</strong></h3>
<pre><code class="lang-jsx"><span class="hljs-comment">//Update a Single Document</span>
app.put(<span class="hljs-string">"/:id"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">//Validate the request body</span>
    <span class="hljs-keyword">const</span> requestData = <span class="hljs-keyword">await</span> BookUpdateSchema.validateAsync(req.body)
    <span class="hljs-comment">//Find the document with the given id and update with the request data</span>
    <span class="hljs-keyword">const</span> updatedDocument = <span class="hljs-keyword">await</span> collection.findOneAndUpdate(
      {
        <span class="hljs-attr">_id</span>: req.params.id,
      },
      { <span class="hljs-attr">$set</span>: requestData }
    )

    <span class="hljs-comment">//if The document is found and updated</span>
    <span class="hljs-keyword">if</span> (updatedDocument) {
      <span class="hljs-comment">//Send the updated document in the response</span>
      res.send(updatedDocument)
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">//Otherwise send a 404 Not FOUND error code</span>
      res.status(<span class="hljs-number">404</span>).send({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Document Not Found"</span> })
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-comment">//This catch block catches errors from the validation</span>
    <span class="hljs-comment">//Which we send as the response</span>
    res.send(error)
  }
})
</code></pre>
<h3 id="delete-route"><strong>Delete Route</strong></h3>
<pre><code class="lang-jsx"><span class="hljs-comment">//Delete a Single Document</span>
app.delete(<span class="hljs-string">"/:id"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-comment">//Delete the document with the provided id</span>
  <span class="hljs-keyword">const</span> deletedDocument = <span class="hljs-keyword">await</span> collection.findOneAndDelete({
    <span class="hljs-attr">_id</span>: req.params.id,
  })

  <span class="hljs-comment">//If the Document is found</span>
  <span class="hljs-keyword">if</span> (deletedDocument) {
    <span class="hljs-comment">//Send a success message and the deleted document in the response</span>
    res.send({
      <span class="hljs-attr">message</span>: <span class="hljs-string">"Document Deleted Succesfully"</span>,
      <span class="hljs-attr">deletedDocument</span>: deletedDocument,
    })
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">//Otherwise send an error</span>
    res.send({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Document not found"</span> }).status(<span class="hljs-number">404</span>)
  }
})
</code></pre>
<p>And That's it! A very simple API written in Node and Express to perform CRUD Operations on a MongoDB database.</p>
<h2 id="download-the-project-from-github">Download the Project from GitHub:</h2>
<p><a target="_blank" href="https://github.com/SwarnimWalavalkar/mongo-node-crud-api">https://github.com/SwarnimWalavalkar/mongo-node-crud-api</a></p>
<h2 id="further-reading">Further Reading:</h2>
<p>Monk JS Documentation: <a target="_blank" href="https://automattic.github.io/monk/">https://automattic.github.io/monk/</a></p>
<p>Joi Documentation: <a target="_blank" href="https://joi.dev/api/">https://joi.dev/api/</a></p>
<p>Express JS Documentation: <a target="_blank" href="https://expressjs.com/en/4x/api.html">https://expressjs.com/en/4x/api.html</a></p>
<p>Node JS Documentation: <a target="_blank" href="https://nodejs.org/en/docs/">https://nodejs.org/en/docs/</a></p>
<p>MongoDB Node Driver Documentation: <a target="_blank" href="https://docs.mongodb.com/drivers/node/">https://docs.mongodb.com/drivers/node/</a></p>
]]></content:encoded></item><item><title><![CDATA[Build and Deploy a REST API Microservice with Python Flask and Docker]]></title><description><![CDATA[Objectives:

Build a simple but real-world useable REST API
Follow REST and Microservice Arch Best Practices
Deploy to a Docker Container

Technologies used:

Python
Flask
Flask Restful
Docker

Prerequisites:

A Foundational Understanding of Python
A...]]></description><link>https://hashnode.swarnimwalavalkar.com/build-and-deploy-a-microservice</link><guid isPermaLink="true">https://hashnode.swarnimwalavalkar.com/build-and-deploy-a-microservice</guid><category><![CDATA[REST API]]></category><category><![CDATA[Python]]></category><category><![CDATA[Flask]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Swarnim Walavalkar]]></dc:creator><pubDate>Mon, 31 Aug 2020 11:55:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1599739070832/HsIbEk48k.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="objectives">Objectives:</h2>
<ul>
<li>Build a simple but real-world useable REST API</li>
<li>Follow REST and Microservice Arch Best Practices</li>
<li>Deploy to a Docker Container</li>
</ul>
<h2 id="technologies-used">Technologies used:</h2>
<ul>
<li>Python</li>
<li>Flask</li>
<li>Flask Restful</li>
<li>Docker</li>
</ul>
<h2 id="prerequisites">Prerequisites:</h2>
<ul>
<li>A Foundational Understanding of Python</li>
<li>Acquaintance with the Flask Microframework</li>
<li>A Primary Understanding of Docker and Docker Container Management</li>
</ul>
<h2 id="difficulty-intermediate">Difficulty: ⚡⚡Intermediate</h2>
<h2 id="setup">Setup:</h2>
<p>Make sure you have pipenv installed.</p>
<pre><code class="lang-bash">pip install pipenv
</code></pre>
<p>Then, start by making a directory for the project and cd into it</p>
<pre><code class="lang-bash">mkdir FlaskBookApi/
<span class="hljs-built_in">cd</span> FlaskBookApi/
</code></pre>
<p>Then install the flask and flask-restful packages using pipenv. This will do a couple of things:</p>
<pre><code class="lang-bash">pipenv install flask flask-restful
</code></pre>
<p>It creates a python virtual environment with your directory's name in a central location and installs the specified packages (in this case, <em>flask</em> and <em>flask-restful</em>). Along with that, In your working directory, it creates the Pipfile, which contains all of the projects dependencies with their appropriate version numbers along with the Python version used by the project. It also creates the Pipfile.lock to enable deterministic builds in production.</p>
<p>This isn't a pipenv tutorial, So I won't go into too much detail about that.</p>
<h2 id="write-the-api">Write The API:</h2>
<p>Alright, Now the fun part! Lets Build this thing!</p>
<p>Start by creating a Python file in the working directory.</p>
<pre><code class="lang-bash">touch api.py
</code></pre>
<p>Great! Now import and initialize flask and flask restful</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_restful <span class="hljs-keyword">import</span> Resource, Api, reqparse, abort, marshal, fields

<span class="hljs-comment"># Initialize Flask</span>
app = Flask(__name__)
api = Api(app)
</code></pre>
<p>Be sure to import the required modules from flask-restful as shown above.</p>
<p>We'll be building a simple API that goes over the performing some basic CRUD operations on a datastore of books (or as it happens, in this case, a List of Dictionaries).</p>
<p>We're going to use a simple Python Dictionary for storage, But it can easily be swapped in with a real database solution, should you need to. But for the sake of simplicity, I've decided to go with a simple List of Dictionaries</p>
<p>Lets get started. First declare a List containing several Dictionaries, representing individual 'Book' elements</p>
<pre><code class="lang-python"><span class="hljs-comment"># A List of Dicts to store all of the books</span>
books = [{
    <span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">"title"</span>: <span class="hljs-string">"Zero to One"</span>,
    <span class="hljs-string">"author"</span>: <span class="hljs-string">"Peter Thiel"</span>,
    <span class="hljs-string">"length"</span>: <span class="hljs-number">195</span>,
    <span class="hljs-string">"rating"</span>: <span class="hljs-number">4.17</span>
},
    {
    <span class="hljs-string">"id"</span>: <span class="hljs-number">2</span>,
    <span class="hljs-string">"title"</span>: <span class="hljs-string">"Atomic Habits "</span>,
    <span class="hljs-string">"author"</span>: <span class="hljs-string">"James Clear"</span>,
    <span class="hljs-string">"length"</span>: <span class="hljs-number">319</span>,
    <span class="hljs-string">"rating"</span>: <span class="hljs-number">4.35</span>
}
]
</code></pre>
<p>Next, Set up a Dictionary to determine the schema for the book object, as expected by the API. This will help with validating requests later.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Schema For the Book Request JSON</span>
bookFields = {
    <span class="hljs-string">"id"</span>: fields.Integer,
    <span class="hljs-string">"title"</span>: fields.String,
    <span class="hljs-string">"author"</span>: fields.String,
    <span class="hljs-string">"length"</span>: fields.Integer,
    <span class="hljs-string">"rating"</span>: fields.Float
}
</code></pre>
<p>Flask Restful is an extension to the Flask Microframework that makes it a whole lot easier to build RESTful APIs</p>
<p>A fundamental building block provided by flask-restful is Resources. Resources give you easy access to multiple HTTP methods just by defining the methods on your Resource Class.</p>
<p>Here is the Book Resource class: This contains the HTTP routes for accessing, modifying and deleting each individual book entity. Now, Lets Break this down...</p>
<pre><code class="lang-python"><span class="hljs-comment"># Resource: Individual Book Routes</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span><span class="hljs-params">(Resource)</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-comment"># Initialize The Flsak Request Parser and add arguments as in an expected request</span>
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument(<span class="hljs-string">"title"</span>, type=str, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"author"</span>, type=str, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"length"</span>, type=int, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"rating"</span>, type=float, location=<span class="hljs-string">"json"</span>)

        super(Book, self).__init__()

    <span class="hljs-comment"># GET - Returns a single book object given a matching id</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self, id)</span>:</span>
        book = [book <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books <span class="hljs-keyword">if</span> book[<span class="hljs-string">'id'</span>] == id]

        <span class="hljs-keyword">if</span>(len(book) == <span class="hljs-number">0</span>):
            abort(<span class="hljs-number">404</span>)

        <span class="hljs-keyword">return</span>{<span class="hljs-string">"book"</span>: marshal(book[<span class="hljs-number">0</span>], bookFields)}

    <span class="hljs-comment"># PUT - Given an id</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">put</span><span class="hljs-params">(self, id)</span>:</span>
        book = [book <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books <span class="hljs-keyword">if</span> book[<span class="hljs-string">'id'</span>] == id]

        <span class="hljs-keyword">if</span> len(book) == <span class="hljs-number">0</span>:
            abort(<span class="hljs-number">404</span>)

        book = book[<span class="hljs-number">0</span>]

        <span class="hljs-comment"># Loop Through all the passed agruments</span>
        args = self.reqparse.parse_args()
        <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> args.items():
            <span class="hljs-comment"># Check if the passed value is not null</span>
            <span class="hljs-keyword">if</span> v <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">None</span>:
                <span class="hljs-comment"># if not, set the element in the books dict with the 'k' object to the value provided in the request.</span>
                book[k] = v

        <span class="hljs-keyword">return</span>{<span class="hljs-string">"book"</span>: marshal(book, bookFields)}

        <span class="hljs-comment"># Delete - Given an id</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete</span><span class="hljs-params">(self, id)</span>:</span>
        book = [book <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books <span class="hljs-keyword">if</span> book[<span class="hljs-string">'id'</span>] == id]

        <span class="hljs-keyword">if</span>(len(book) == <span class="hljs-number">0</span>):
            abort(<span class="hljs-number">404</span>)

        books.remove(book[<span class="hljs-number">0</span>])

        <span class="hljs-keyword">return</span> <span class="hljs-number">201</span>
</code></pre>
<p>First, In the init method of the class, you initialize the request parser. It'll allow you easy access to any variable on the <em>flask.request</em> and also validates the response based on the arguments provided</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span><span class="hljs-params">(Resource)</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-comment"># Initialize The Flsak Request Parser and add arguments as in an expected request</span>
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument(<span class="hljs-string">"title"</span>, type=str, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"author"</span>, type=str, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"length"</span>, type=int, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"rating"</span>, type=float, location=<span class="hljs-string">"json"</span>)

        super(Book, self).__init__()
</code></pre>
<p>Next, The GET Method, This one's really simple, it takes in an id and loops through the books list and checks each element's id with the specified ID, If a match is found, it returns that dict. The <em>marshal</em> method just makes sure the object that is being returned is being filtered through the fields defined in the bookFields dict.</p>
<pre><code class="lang-python"><span class="hljs-comment"># GET - Returns a single book object given a matching id</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self, id)</span>:</span>
        book = [book <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books <span class="hljs-keyword">if</span> book[<span class="hljs-string">'id'</span>] == id]

        <span class="hljs-keyword">if</span>(len(book) == <span class="hljs-number">0</span>):
            abort(<span class="hljs-number">404</span>)

        <span class="hljs-keyword">return</span>{<span class="hljs-string">"book"</span>: marshal(book[<span class="hljs-number">0</span>], bookFields)}
</code></pre>
<p>The Put method is used to update the element with the specified id, It takes a response object with the fields to be updated First, It loops through the books list and checks each element's id with the specified ID, If a match is found, It parses all of the provided arguments using the reqparser.</p>
<p>Then, Loops through the parsed arguments and updates the fields as in the request object.</p>
<pre><code class="lang-python"><span class="hljs-comment"># PUT - Given an id</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">put</span><span class="hljs-params">(self, id)</span>:</span>
        book = [book <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books <span class="hljs-keyword">if</span> book[<span class="hljs-string">'id'</span>] == id]

        <span class="hljs-keyword">if</span> len(book) == <span class="hljs-number">0</span>:
            abort(<span class="hljs-number">404</span>)

        book = book[<span class="hljs-number">0</span>]

        <span class="hljs-comment"># Loop Through all the passed agruments</span>
        args = self.reqparse.parse_args()
        <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> args.items():
            <span class="hljs-comment"># Check if the passed value is not null</span>
            <span class="hljs-keyword">if</span> v <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">None</span>:
                <span class="hljs-comment"># if not, set the element in the books dict with the 'k' object to the value provided in the request.</span>
                book[k] = v

        <span class="hljs-keyword">return</span>{<span class="hljs-string">"book"</span>: marshal(book, bookFields)}
</code></pre>
<p>The Delete method just simply takes in an id and deletes the element in the books list with the id.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Delete - Given an id</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete</span><span class="hljs-params">(self, id)</span>:</span>
        book = [book <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books <span class="hljs-keyword">if</span> book[<span class="hljs-string">'id'</span>] == id]

        <span class="hljs-keyword">if</span>(len(book) == <span class="hljs-number">0</span>):
            abort(<span class="hljs-number">404</span>)

        books.remove(book[<span class="hljs-number">0</span>])

        <span class="hljs-keyword">return</span> <span class="hljs-number">201</span>
</code></pre>
<p>Next is the BookList class, This contains the routes dealing with operations on the entire database.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookList</span><span class="hljs-params">(Resource)</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument(
            <span class="hljs-string">"title"</span>, type=str, required=<span class="hljs-keyword">True</span>, help=<span class="hljs-string">"The title of the book must be provided"</span>, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(
            <span class="hljs-string">"author"</span>, type=str, required=<span class="hljs-keyword">True</span>, help=<span class="hljs-string">"The author of the book must be provided"</span>, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"length"</span>, type=int, required=<span class="hljs-keyword">True</span>,
                                   help=<span class="hljs-string">"The length of the book (in pages)"</span>, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(
            <span class="hljs-string">"rating"</span>, type=float, required=<span class="hljs-keyword">True</span>, help=<span class="hljs-string">"The rating must be provided"</span>, location=<span class="hljs-string">"json"</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-keyword">return</span>{<span class="hljs-string">"books"</span>: [marshal(book, bookFields) <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books]}

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post</span><span class="hljs-params">(self)</span>:</span>
        args = self.reqparse.parse_args()
        book = {
            <span class="hljs-string">"id"</span>: books[<span class="hljs-number">-1</span>][<span class="hljs-string">'id'</span>] + <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> len(books) &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>,
            <span class="hljs-string">"title"</span>: args[<span class="hljs-string">"title"</span>],
            <span class="hljs-string">"author"</span>: args[<span class="hljs-string">"author"</span>],
            <span class="hljs-string">"length"</span>: args[<span class="hljs-string">"length"</span>],
            <span class="hljs-string">"rating"</span>: args[<span class="hljs-string">"rating"</span>]
        }

        books.append(book)
        <span class="hljs-keyword">return</span>{<span class="hljs-string">"book"</span>: marshal(book, bookFields)}, <span class="hljs-number">201</span>
</code></pre>
<p>The Init method initializes the request parser. It parses the request JSON Object and also validates it based on the arguments provided.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span>
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument(
            <span class="hljs-string">"title"</span>, type=str, required=<span class="hljs-keyword">True</span>, help=<span class="hljs-string">"The title of the book must be provided"</span>, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(
            <span class="hljs-string">"author"</span>, type=str, required=<span class="hljs-keyword">True</span>, help=<span class="hljs-string">"The author of the book must be provided"</span>, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(<span class="hljs-string">"length"</span>, type=int, required=<span class="hljs-keyword">True</span>,
                                   help=<span class="hljs-string">"The length of the book (in pages)"</span>, location=<span class="hljs-string">"json"</span>)
        self.reqparse.add_argument(
            <span class="hljs-string">"rating"</span>, type=float, required=<span class="hljs-keyword">True</span>, help=<span class="hljs-string">"The rating must be provided"</span>, location=<span class="hljs-string">"json"</span>)
</code></pre>
<p>The Get method simply returns all the elements in the books list</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-keyword">return</span>{<span class="hljs-string">"books"</span>: [marshal(book, bookFields) <span class="hljs-keyword">for</span> book <span class="hljs-keyword">in</span> books]}
</code></pre>
<p>The Post method takes a JSON Object. Parses it , creates a new dict and appends it to the Books list.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post</span><span class="hljs-params">(self)</span>:</span>
        args = self.reqparse.parse_args()
        book = {
            <span class="hljs-string">"id"</span>: books[<span class="hljs-number">-1</span>][<span class="hljs-string">'id'</span>] + <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> len(books) &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>,
            <span class="hljs-string">"title"</span>: args[<span class="hljs-string">"title"</span>],
            <span class="hljs-string">"author"</span>: args[<span class="hljs-string">"author"</span>],
            <span class="hljs-string">"length"</span>: args[<span class="hljs-string">"length"</span>],
            <span class="hljs-string">"rating"</span>: args[<span class="hljs-string">"rating"</span>]
        }

        books.append(book)
        <span class="hljs-keyword">return</span>{<span class="hljs-string">"book"</span>: marshal(book, bookFields)}, <span class="hljs-number">201</span>
</code></pre>
<p>And Thats it! Now just attach those Resource classes to some endpoints and test it out!</p>
<pre><code class="lang-python">api.add_resource(BookList, <span class="hljs-string">"/books"</span>)
api.add_resource(Book, <span class="hljs-string">"/books/&lt;int:id&gt;"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(debug=<span class="hljs-keyword">True</span>)
</code></pre>
<h2 id="deploy-on-docker">Deploy on Docker:</h2>
<p>Alright, Now lets deploy this microservice API to a docker container.</p>
<p>First, create a Dockerfile in the project directory.</p>
<p>A Docker file is in essence a set of instructions for building an Image which is a blueprint which your container will run off of.</p>
<p>Lets go over this line by line.</p>
<pre><code class="lang-docker">FROM python:3.8

RUN pip3 install pipenv

ENV PROJECT_DIR /usr/src/flaskbookapi

WORKDIR ${PROJECT_DIR}

COPY Pipfile .
COPY Pipfile.lock .
COPY . .

RUN pipenv install --deploy --ignore-pipfile

EXPOSE 5000

CMD ["pipenv", "run", "python", "api.py"]
</code></pre>
<p>This use the python 3.8 image from Docker Hub as our base image, This makes sure we have Python and all of its dependencies on the container</p>
<pre><code class="lang-docker">FROM python:3.8
</code></pre>
<p>This installs pipenv on the container.</p>
<pre><code class="lang-docker">RUN pip3 install pipenv
</code></pre>
<p>The first line sets a environment variable as a path to a directory to store the projects code.</p>
<p>Then the next command sets that directory as the working directory.</p>
<pre><code class="lang-docker">ENV PROJECT_DIR /usr/src/flaskbookapi

WORKDIR ${PROJECT_DIR}
</code></pre>
<p>Next, We copy over all of our files to the container</p>
<pre><code class="lang-docker">COPY Pipfile .
COPY Pipfile.lock .
COPY . .
</code></pre>
<p>This command runs pipenv install with the —deploy flag and also sets it to ignore the pipfile and just use the pipfile.lock to install dependencies</p>
<pre><code class="lang-docker">RUN pipenv install --deploy --ignore-pipfile
</code></pre>
<p>Next, We expose the 5000 port to be able to use it.</p>
<pre><code class="lang-docker">EXPOSE 5000
</code></pre>
<p>Finally, we run our program using the CMD command.</p>
<pre><code class="lang-docker">CMD ["pipenv", "run", "python", "api.py"]
</code></pre>
<p>Now lets use that Dockerfile to build an image which will later be used to make a container</p>
<pre><code class="lang-bash">docker build -t flaskbookapi:1.0 .
</code></pre>
<p>Now, finally! Fire up a container with the image we just built!</p>
<pre><code class="lang-bash">docker run -p 5000:5000 --name FlaskBookAPI flaskbookapi:1.0
</code></pre>
<p>And Boom! Out API is up and running! On a Docker container</p>
<pre><code class="lang-bash">$ docker run -p 5000:5000 --name FlaskBookAPI flaskbookapi:1.0
 * Serving Flask app <span class="hljs-string">"api"</span> (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it <span class="hljs-keyword">in</span> a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
</code></pre>
<h2 id="download-the-project-from-github">Download the Project from GitHub:</h2>
<p><a target="_blank" href="https://github.com/SwarnimWalavalkar/rest-api-microservice-docker">https://github.com/SwarnimWalavalkar/rest-api-microservice-docker</a></p>
<h2 id="further-reading">Further Reading:</h2>
<p>Flask Documentation: <a target="_blank" href="https://flask.palletsprojects.com/en/1.1.x/">https://flask.palletsprojects.com/en/1.1.x/</a></p>
<p>Flast-Restful Documentation: <a target="_blank" href="https://flask-restful.readthedocs.io/en/latest/">https://flask-restful.readthedocs.io/en/latest/</a></p>
<p>Docker Documentation: <a target="_blank" href="https://docs.docker.com/">https://docs.docker.com/</a></p>
<p>Pipenv: <a target="_blank" href="https://pipenv-fork.readthedocs.io/en/latest/">https://pipenv-fork.readthedocs.io/en/latest/</a></p>
]]></content:encoded></item></channel></rss>