<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mandar Vaze</title>
    <description>The latest articles on DEV Community by Mandar Vaze (@mandarvaze).</description>
    <link>https://dev.to/mandarvaze</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F95682%2F028b36fe-d6ae-4945-8351-03c9b1afd185.jpeg</url>
      <title>DEV Community: Mandar Vaze</title>
      <link>https://dev.to/mandarvaze</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mandarvaze"/>
    <language>en</language>
    <item>
      <title>Firefox Reader mode in your Terminal</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Wed, 19 Jan 2022 03:52:17 +0000</pubDate>
      <link>https://dev.to/mandarvaze/firefox-reader-mode-in-your-terminal-f87</link>
      <guid>https://dev.to/mandarvaze/firefox-reader-mode-in-your-terminal-f87</guid>
      <description>&lt;p&gt;I'm trying to move to more text based workflows.&lt;/p&gt;

&lt;p&gt;On that journey, I came across &lt;code&gt;readable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;readable&lt;/code&gt; strips out just the readability code from mozilla's firefox engine and provides it as a node module.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -g readability-cli&lt;/code&gt; will install a script called &lt;code&gt;readable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By default, readable will strip out all the non-essentials from the webpage and create another HTML page.&lt;/p&gt;

&lt;p&gt;One can not use it as-is, cause it has all the HTML tags. So one needs a browser.&lt;/p&gt;

&lt;p&gt;Since we are already in terminal why not use &lt;code&gt;w3m&lt;/code&gt; ?&lt;/p&gt;

&lt;p&gt;Here is how I use it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;readable https://microblog.desipenguin.com/post/fzf-with-fish/ | w3m -T text/html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and here is how it looks 😄&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--htglxqY7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0qbs4ly2s5v3z9qdav0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--htglxqY7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0qbs4ly2s5v3z9qdav0.png" alt="microblog in terminal" width="778" height="801"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;On a related note, w3m official homepage asks one to download tarball.&lt;/p&gt;

&lt;p&gt;But your OS's package manager probably has w3m. So I suggest use that instead.&lt;/p&gt;

&lt;p&gt;FWIW, I used &lt;code&gt;brew install w3m&lt;/code&gt; on macOS.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>focus</category>
      <category>read</category>
      <category>web</category>
    </item>
    <item>
      <title>How to Implement Role based Access Control With FastAPI</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Wed, 30 Dec 2020 16:19:08 +0000</pubDate>
      <link>https://dev.to/mandarvaze/how-to-implement-role-based-access-control-with-fastapi-488n</link>
      <guid>https://dev.to/mandarvaze/how-to-implement-role-based-access-control-with-fastapi-488n</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5far77562a70u7l3bz7k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5far77562a70u7l3bz7k.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Role based Access Control (RBAC)
&lt;/h2&gt;

&lt;p&gt;Most of the CRUD apps, require some level of role based access control.&lt;/p&gt;

&lt;p&gt;You may have at least two types of users.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Elevated permission user (admin, root or superuser)&lt;/li&gt;
&lt;li&gt;Normal user aka everyone else ;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;More likely you have more levels in between.&lt;/p&gt;

&lt;p&gt;This means only the users with specific &lt;em&gt;role&lt;/em&gt; can access certain API endpoints&lt;br&gt;
or operations e.g. Allow everyone the &lt;code&gt;GET&lt;/code&gt; operation, but only &lt;code&gt;admin&lt;/code&gt; can &lt;code&gt;DELETE&lt;/code&gt;.&lt;br&gt;
Some levels in-between can create/update etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Following code assumes your &lt;code&gt;User&lt;/code&gt; model has a &lt;code&gt;role&lt;/code&gt; attribute.&lt;br&gt;
It is better to have a default value so that every user created starts&lt;br&gt;
with lowest level, even if role is not assigned when creating.&lt;/p&gt;

&lt;p&gt;Let us first define the &lt;code&gt;RoleChecker&lt;/code&gt; class as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RoleChecker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allowed_roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowed_roles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;allowed_roles&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_current_active_user&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowed_roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User with role &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; not in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowed_roles&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Operation not permitted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then in your routes file use it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;allow_create_resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RoleChecker&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/some-resource/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;schemas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MyResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allow_create_resource&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;schemas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceCreate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="c1"&gt;# Some validation like resource does not already exist
&lt;/span&gt;    &lt;span class="c1"&gt;# Create the resource
&lt;/span&gt;    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes you want to allow multiple roles to perform certain operation.&lt;br&gt;
That is why, &lt;code&gt;RoleChecker&lt;/code&gt; takes a list of roles like :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;allow_create_resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RoleChecker&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;manager&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Learning (Or how I got here)
&lt;/h2&gt;

&lt;p&gt;If you came here just looking for solution, you can stop reading now.&lt;/p&gt;

&lt;p&gt;Read on, to know how I reached the solution, things I tried (and failed)&lt;/p&gt;

&lt;p&gt;(Sometimes such details give you an idea for something you may want in the future)&lt;/p&gt;

&lt;p&gt;As you may know, you can get the current user details in the API via&lt;br&gt;
Dependency Injection via &lt;code&gt;user: User = Depends(get_current_user)&lt;/code&gt;&lt;br&gt;
See the &lt;a href="https://fastapi.tiangolo.com/tutorial/security/get-current-user/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So easy first attempt was on the lines of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Operation not permitted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I extended the above to &lt;code&gt;user.role not in ["admin", "manager"]&lt;/code&gt; to allow&lt;br&gt;
multiple roles to perform that operation.&lt;/p&gt;

&lt;p&gt;It works for "proof of concept", but we cant be adding similar code &lt;strong&gt;everywhere&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then I created&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required_role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_current_active_user&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;required_role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Operation not permitted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I needed to pass the list of roles to the function. Unfortunately I could not&lt;br&gt;
call this via &lt;code&gt;Depends&lt;/code&gt;. I kept getting &lt;code&gt;Depends has no attribute ...&lt;/code&gt; error.&lt;/p&gt;

&lt;p&gt;Also, I need to call this from the &lt;code&gt;router&lt;/code&gt; decorator function as&lt;br&gt;
&lt;code&gt;dependencies=[Depends(my_func)]&lt;/code&gt; rather than in the function param&lt;br&gt;
like  &lt;code&gt;user: User = Depends(get_current_user)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally another user pointed me to &lt;a href="https://fastapi.tiangolo.com/advanced/advanced-dependencies/#parameterize-the-instance?" rel="noopener noreferrer"&gt;this&lt;/a&gt; section of the documentation, and that was that. 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;I'm grateful for &lt;a href="http://marcelotryle.com/" rel="noopener noreferrer"&gt;Marcelo aka Kludex&lt;/a&gt; and &lt;a href="https://github.com/dannyrohde" rel="noopener noreferrer"&gt;Danny Rohde&lt;/a&gt; on FastAPI gitter for the ideas and help.&lt;/p&gt;

</description>
      <category>python</category>
      <category>fastapi</category>
      <category>api</category>
      <category>accesscontrol</category>
    </item>
    <item>
      <title>How to Create Header Images for Your Blog</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Thu, 19 Nov 2020 17:07:33 +0000</pubDate>
      <link>https://dev.to/mandarvaze/how-to-create-header-images-for-your-blog-akp</link>
      <guid>https://dev.to/mandarvaze/how-to-create-header-images-for-your-blog-akp</guid>
      <description>&lt;h2&gt;
  
  
  Option 1 : Quick and &lt;del&gt;dirty&lt;/del&gt; Beautiful
&lt;/h2&gt;

&lt;p&gt;Head over to &lt;a href="https://coverview.now.sh/"&gt;https://coverview.now.sh/&lt;/a&gt; - explore.&lt;br&gt;
It is self explanatory.&lt;/p&gt;

&lt;p&gt;When in hurry, this is the best.&lt;/p&gt;

&lt;p&gt;It has a nice feature that lets you add an icon based on the technology you are blogging about like python, docker, react, heroku and so on.&lt;/p&gt;

&lt;p&gt;While it lets you choose background from bunch of options, you can not (yet) upload your own background image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2 : More Work, More Control
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a login on Canva. It is free.&lt;/li&gt;
&lt;li&gt;Create New Design 1600x840 - This size works well for most blogs&lt;/li&gt;
&lt;li&gt;Go to Background and select something you like&lt;/li&gt;
&lt;li&gt;Go to Elements, and select twitter. Choose twitter icon that you like&lt;/li&gt;
&lt;li&gt;Go to Text, select a style and then type in your twitter handle.&lt;/li&gt;
&lt;li&gt;Go to Text, select a style and then type in your website URL.&lt;/li&gt;
&lt;li&gt;Go to Text, select "Add Heading", change font to your liking.&lt;/li&gt;
&lt;li&gt;Arrange the text elements such that Heading is prominent.&lt;/li&gt;
&lt;li&gt;Optionally, add a little illustration either from Canva or other sites like undraw.co&lt;/li&gt;
&lt;li&gt;Optionally, add a technology icon like previous option. (I haven't done that yet)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To avoid doing most of these steps over and over, Save background, twitter and website URL in a template. Each time just change the header (and technology icon, if you have one).&lt;/p&gt;

&lt;p&gt;I am trying to use SVG for my blog for two reasons - files are "text" and light. But for some reason, my SVG are only Black and White. I'm sure there are color SVG, but then they are as "heavy" as PNG.&lt;/p&gt;

&lt;p&gt;I have found Convertio (link in the Resource section below) to be good option. But there are more options out there. (Including &lt;code&gt;potrace&lt;/code&gt; which one can use locally.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.canva.com/join/qlx-tlw-qdh"&gt;Canva&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://undraw.co"&gt;Undraw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://convertio.co/"&gt;Convertio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blogging</category>
      <category>cover</category>
      <category>image</category>
    </item>
    <item>
      <title>Why my tests fail only during pre-commit ?</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Sat, 05 Sep 2020 16:44:18 +0000</pubDate>
      <link>https://dev.to/mandarvaze/why-my-tests-fail-only-during-pre-commit-3f76</link>
      <guid>https://dev.to/mandarvaze/why-my-tests-fail-only-during-pre-commit-3f76</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xm7Mof5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z4otbi7ysl1hnbq1sh8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xm7Mof5p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z4otbi7ysl1hnbq1sh8c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Symptom
&lt;/h2&gt;

&lt;p&gt;Recently I ran across (what I thought was) strange behaviour.&lt;/p&gt;

&lt;p&gt;I use &lt;code&gt;pre-commit&lt;/code&gt; for all my git commits, and one of the step is to ensure that&lt;br&gt;
all the unit tests pass.&lt;/p&gt;

&lt;p&gt;I also have a &lt;code&gt;make&lt;/code&gt; target to run just the unit tests.&lt;/p&gt;

&lt;p&gt;Each time when I tried commit, the unit test step in the &lt;code&gt;pre-commit&lt;/code&gt;&lt;br&gt;
would fail - which indicates that the unit tests did not pass. But when I run&lt;br&gt;
&lt;code&gt;make unit&lt;/code&gt; it would pass. 🤷&lt;/p&gt;

&lt;p&gt;During the &lt;code&gt;pre-commit&lt;/code&gt;, pytest would return with &lt;code&gt;exit code 5&lt;/code&gt; - which&lt;br&gt;
indicates &lt;code&gt;no tests ran&lt;/code&gt;. So it wasn't that one or more tests failed during&lt;br&gt;
&lt;code&gt;pre-commit&lt;/code&gt; - but nothing was &lt;em&gt;tested&lt;/em&gt; - and due to non-zero exit code,&lt;br&gt;
&lt;code&gt;pre-commit&lt;/code&gt; prevented the commit (as it should)&lt;/p&gt;

&lt;h2&gt;
  
  
  Root Cause
&lt;/h2&gt;

&lt;p&gt;It turns out &lt;code&gt;pre-commit&lt;/code&gt; runs all the steps only on the modified files.&lt;br&gt;
It passes the list of modified files to each command - implicitly.&lt;br&gt;
That is, unless you configure it not to. 😀&lt;/p&gt;

&lt;p&gt;So when I modify a source file (not a test file) - pytest would "ignore"&lt;br&gt;
the file - since it would not contain any tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Now that we understand the "why" - solution is obvious.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Patient : Doctor, it hurts when I do &lt;em&gt;this&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Doctor : Then don't do &lt;em&gt;that&lt;/em&gt;&lt;br&gt;
😂&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the unit test step, ask pre-commit not to pass the file names as an argument&lt;br&gt;
via &lt;code&gt;pass_filenames: false&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pre-commit/pre-commit/issues/1130"&gt;Stackoverflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>python</category>
      <category>pytest</category>
      <category>precommit</category>
      <category>git</category>
    </item>
    <item>
      <title>Chrome on Docker</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Tue, 02 Jun 2020 01:56:01 +0000</pubDate>
      <link>https://dev.to/mandarvaze/chrome-on-docker-3185</link>
      <guid>https://dev.to/mandarvaze/chrome-on-docker-3185</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Some days ago, I got a call from someone asking for a solution. Due to global pandemic they were unable to hand over a laptop to new employee. They wanted the new employee to access a certain websites but did not wish to share the passwords.&lt;/p&gt;

&lt;p&gt;Their idea : provide access to &lt;em&gt;already-logged-in&lt;/em&gt; browser to the new person, so they would have access to the sites, but do not need the passwords.&lt;/p&gt;

&lt;p&gt;They had considered AWS workspaces - but it is costly. (Finally they got some "Free for a couple of months" deal, and used as their final solution)&lt;/p&gt;

&lt;p&gt;I suggested "Chrome in Docker". The conversation ended, but it intrigued me and wanted to try it out myself.&lt;/p&gt;

&lt;p&gt;I started with &lt;a href="https://github.com/jessfraz/dockerfiles/tree/master/chrome/stable"&gt;this&lt;/a&gt; but it did not work as-is for me. Partially because (I think) the original repo assumes linux host, and I am on macOS. So I had to make some changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of my changes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I included the &lt;code&gt;chrome.json&lt;/code&gt; in the repo. See details about this file in the Dockerfile comments.&lt;/li&gt;
&lt;li&gt;I had to replace &lt;code&gt;libpango&lt;/code&gt; with &lt;code&gt;libpangox&lt;/code&gt; since the original repo is couple years old.&lt;/li&gt;
&lt;li&gt;Removed &lt;code&gt;talk-plugin&lt;/code&gt; cause I don't need it.&lt;/li&gt;
&lt;li&gt;Created &lt;code&gt;run.sh&lt;/code&gt;- because the &lt;code&gt;docker&lt;/code&gt; command becomes too long, and changing a param becomes PITA&lt;/li&gt;
&lt;li&gt;Removed &lt;code&gt;--device&lt;/code&gt; params because it does not apply to macOS (I think)&lt;/li&gt;
&lt;li&gt;Finally, I needed XServer, which comes with linux but not macOS. Hence &lt;code&gt;brew cask install xquartz&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bit of Troubleshooting
&lt;/h2&gt;

&lt;p&gt;Where is the fun if things work in the first attempt ?&lt;br&gt;
I kept getting &lt;code&gt;Unable to Open XDisplay&lt;/code&gt; error.&lt;/p&gt;

&lt;p&gt;To fix the error, I had to set the &lt;code&gt;ip&lt;/code&gt; as per &lt;a href="https://medium.com/@dimitris.kapanidis/running-gui-apps-in-docker-containers-3bd25efa862a"&gt;this&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created &lt;code&gt;setxhost.sh&lt;/code&gt; to simplify this. (Originally it was part of &lt;code&gt;run.sh&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;You can see all my changes in my &lt;a href="https://github.com/mandarvaze/chrome-on-docker"&gt;git repo&lt;/a&gt; which contains all my&lt;br&gt;
modification.&lt;/p&gt;

&lt;p&gt;The README has detailed instructions to try this on your mac.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>macos</category>
      <category>chrome</category>
    </item>
    <item>
      <title>How to Write Middleware using FastAPI</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Tue, 05 May 2020 16:23:46 +0000</pubDate>
      <link>https://dev.to/mandarvaze/how-to-write-middleware-using-fastapi-2gl</link>
      <guid>https://dev.to/mandarvaze/how-to-write-middleware-using-fastapi-2gl</guid>
      <description>&lt;p&gt;For one of my project, I needed to host an API service on the RapidAPI platform. In order to make sure that all the requests to the application are routed via RapidAPI I needed to check special header sent by RapidAPI.&lt;/p&gt;

&lt;p&gt;RapidAPI forwards each &lt;em&gt;valid&lt;/em&gt; request to the configured server, but injects additional header &lt;code&gt;X-RapidAPI-Proxy-Secret&lt;/code&gt;. While a hacker may also send the same header, the value of this header will be only known to RapidAPI platform and your app.&lt;/p&gt;

&lt;p&gt;I deployed the server on heroku, and defined an environment variable&lt;br&gt;
&lt;code&gt;PROXY_SECRET&lt;/code&gt; which I check against the one sent with the request.&lt;/p&gt;

&lt;p&gt;Sometimes I need to test the server directly, in which case I simply do not set this variable (like on my local machine) and this check is bypassed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;starlette.requests&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;starlette.responses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PlainTextResponse&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_rapidAPI_proxy_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;call_next&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Check if server knows about valid "secret"
&lt;/span&gt;    &lt;span class="n"&gt;secret_header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PROXY_SECRET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;secret_header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;
        &lt;span class="c1"&gt;# If the header is missing, or does not match expected value
&lt;/span&gt;        &lt;span class="c1"&gt;# Reject the request altogether
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"X-RapidAPI-Proxy-Secret"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
            &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"X-RapidAPI-Proxy-Secret"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;secret_header&lt;/span&gt;
        &lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;PlainTextResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"Direct access to the API not allowed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;call_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py"&gt;Uvcorn's
ProxyMiddleWare&lt;/a&gt; -
This is related but was not directly useful for me.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fastapi.tiangolo.com/tutorial/middleware/"&gt;FastAPI middleware documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.rapidapi.com/docs/headers-sent-by-mashape-proxy2#headers-sent-to-the-request"&gt;RapidAPI Proxy Secret&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>fastapi</category>
      <category>rapidapi</category>
    </item>
    <item>
      <title>How to Process Headers using FastAPI</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Sun, 03 May 2020 17:33:49 +0000</pubDate>
      <link>https://dev.to/mandarvaze/how-to-process-headers-using-fastapi-2b39</link>
      <guid>https://dev.to/mandarvaze/how-to-process-headers-using-fastapi-2b39</guid>
      <description>&lt;p&gt;&lt;em&gt;This was originally posted on my blog, &lt;a href="https://learnings.desipenguin.com/"&gt;here.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;FastAPI makes processing Headers very easy, just like everything else. There are&lt;br&gt;
two ways to process headers with FastAPI.&lt;/p&gt;
&lt;h2&gt;
  
  
  Via Request Object
&lt;/h2&gt;

&lt;p&gt;When writing &lt;a href="https://dev.to/post/middleware-fastapi/"&gt;middleware&lt;/a&gt; we have direct access to the &lt;code&gt;Request&lt;/code&gt;, so it is&lt;br&gt;
much easier to write as :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;call_next&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;"X-My-Header"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Do something with X-My-Header
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  As a Function Param
&lt;/h2&gt;

&lt;p&gt;When writing normal endpoints, it is easier to process headers. One of your&lt;br&gt;
function parameter could be &lt;code&gt;Header&lt;/code&gt; itself. FastAPI will do all the work for&lt;br&gt;
you, so that you can focus on the business logic.&lt;/p&gt;

&lt;p&gt;See the sample code from FastAPI documentation of this topic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/items/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"User-Agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_agent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Important thing to remember that variable name &lt;strong&gt;must&lt;/strong&gt; be in snake_case.&lt;/p&gt;

&lt;p&gt;e.g. In the sample code above, we are processing &lt;code&gt;User-Agent&lt;/code&gt; header. So&lt;br&gt;
variable name &lt;strong&gt;must&lt;/strong&gt; be &lt;code&gt;user_agent&lt;/code&gt;. Names with &lt;code&gt;-&lt;/code&gt; are invalid in python. So&lt;br&gt;
FastAPI will convert the dashes/hyphens to underscore for you.&lt;/p&gt;

&lt;p&gt;But wait ..&lt;/p&gt;

&lt;p&gt;If you &lt;em&gt;really&lt;/em&gt; don't want the auto conversion to underscore. just tell FastAPI&lt;br&gt;
that via &lt;code&gt;convert_underscores=False&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;See documentation below for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fastapi.tiangolo.com/tutorial/header-params/"&gt;Header Param&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>How to Safely use Google Application Credentials on Heroku</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Fri, 01 May 2020 18:06:35 +0000</pubDate>
      <link>https://dev.to/mandarvaze/how-to-safely-use-google-application-credentials-on-heroku-4cng</link>
      <guid>https://dev.to/mandarvaze/how-to-safely-use-google-application-credentials-on-heroku-4cng</guid>
      <description>&lt;p&gt;&lt;em&gt;This was originally posted on my blog, &lt;a href="https://learnings.desipenguin.com/post/goog-cred-heroku/"&gt;here.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;If you have deployed an app on heroku, you know that the &lt;strong&gt;only&lt;/strong&gt; way to get any files there is via git.&lt;br&gt;
Normally this is fine, but Google API expects an environment variable &lt;code&gt;GOOGLE_APPLICATION_CREDENTIALS&lt;/code&gt; that points to a json &lt;strong&gt;file&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you google, you might come across tutorials like &lt;a href="https://towardsdatascience.com/tutorial-google-vision-api-with-python-and-heroku-3b8d3ff5f6ef"&gt;this&lt;/a&gt; or even &lt;a href="https://stackoverflow.com/questions/57126545/how-to-authenticate-google-vision-api-credentials-on-heroku-using-node-js"&gt;SO answer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essentially they tell you to commit the &lt;code&gt;json&lt;/code&gt; file downloaded from Google into git. Since heroku does not have a &lt;em&gt;file system&lt;/em&gt; per se, there is no way to get the json file to heroku.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt; ..... this file should &lt;strong&gt;never&lt;/strong&gt; be in git. The file contains your&lt;br&gt;
security credentials, and it is (indirectly) linked to your credit card.&lt;/p&gt;

&lt;p&gt;Even if hacker does not get (direct) access to your credit card, if they use &lt;em&gt;your&lt;/em&gt; credentials, &lt;em&gt;your&lt;/em&gt; account will get billed (once you go over quota) and google will charge &lt;em&gt;your&lt;/em&gt; credit card.&lt;/p&gt;

&lt;p&gt;So putting the credentials json file in git is a bad idea.&lt;/p&gt;

&lt;p&gt;So what should a developer to do ?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;workaround&lt;/em&gt; is to store the contents on json file in an environment variable, and at runtime, create the json file on-the-fly by reading the environment variable.&lt;/p&gt;

&lt;p&gt;But there is better option, use this &lt;a href="https://elements.heroku.com/buildpacks/elishaterada/heroku-google-application-credentials-buildpack"&gt;Custom Build pack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even better, Create &lt;code&gt;.profile&lt;/code&gt; file in your repo, and create the json file from the environment variable. &lt;a href="https://github.com/elishaterada/heroku-google-application-credentials-buildpack/pull/5#issuecomment-547896688"&gt;No buildpack required.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On your local machine, where you have downloaded the &lt;code&gt;credentials.json&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Store the JSON contents in environment variable :  &lt;code&gt;heroku config:set GOOGLE_CREDENTIALS="$(&amp;lt; credentials.json)"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;.profile&lt;/code&gt; and put this in it : &lt;code&gt;echo ${GOOGLE_CREDENTIALS} &amp;gt;&lt;br&gt;
/app/google-credentials.json&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;This will create the file on heroku's ephemeral file system each time a dyno
is booted.&lt;/li&gt;
&lt;li&gt;Commit this &lt;code&gt;.profile&lt;/code&gt; in the root of your git repo&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Point to the file as Google API expects.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;heroku config:set GOOGLE_APPLICATION_CREDENTIALS=/app/google-credentials.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;🎉&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>heroku</category>
      <category>git</category>
      <category>security</category>
    </item>
    <item>
      <title>How to gain experience building large scale apps?</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Sun, 07 Apr 2019 17:15:45 +0000</pubDate>
      <link>https://dev.to/mandarvaze/how-to-gain-experience-building-large-scale-apps-5aom</link>
      <guid>https://dev.to/mandarvaze/how-to-gain-experience-building-large-scale-apps-5aom</guid>
      <description>&lt;p&gt;My resume was recently rejected because I do not have experience building "large scale apps" that serve millions of users.&lt;/p&gt;

&lt;p&gt;I have over two decades of experience, but mostly in startups/small-ish companies. Thus most of the times I got to work on "new" projects.&lt;/p&gt;

&lt;p&gt;Startups always want MVP that can be shipped/released early, so the "growth" is always iterative. Most of the times, the product was discontinued and/or startup closed shop.&lt;/p&gt;

&lt;p&gt;While I (believe I) have "theoretical" knowledge about dos and don'ts of building large scale apps, it is not same as having "real" experience from the trenches.&lt;/p&gt;

&lt;p&gt;They won't hire me because of lack of "relevant" experience, plus the fact that I am senior engineer. If I were junior experience I assume they would not have this "requirement". I did offer to accept "junior" position (I really liked the company I applied for and their product) but I was told they don't have time for "babysitting" and thus aren't hiring for junior positions at all.&lt;/p&gt;

&lt;p&gt;So what do you guys suggest I do to gain "real" experience building large scale app ? (In my case, it is chicken and egg situation)&lt;/p&gt;




&lt;p&gt;P.S: I am NOT looking for links to posts like "How to build large scale apps using ...."&lt;/p&gt;

&lt;p&gt;P.P.S: If you would like to offer me intership (to gain experience building Large scale app) I'm game. Relevant details available in my profile.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>Ethereum Transaction Details for Humans</title>
      <dc:creator>Mandar Vaze</dc:creator>
      <pubDate>Mon, 15 Oct 2018 15:50:55 +0000</pubDate>
      <link>https://dev.to/mandarvaze/ethereum-transaction-details-for-humans-5h09</link>
      <guid>https://dev.to/mandarvaze/ethereum-transaction-details-for-humans-5h09</guid>
      <description>&lt;p&gt;&lt;em&gt;This was originally posted on my blog, &lt;a href="https://learnings.desipenguin.com/post/view-eth-txn-details/"&gt;here.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When working on one of my projects, it was asked "How do we ensure that transaction was indeed recorded on the blockchain"&lt;/p&gt;

&lt;p&gt;While we can (and did) store the transaction hash returned by the function call in the database, &lt;code&gt;txn_hash&lt;/code&gt; alone does no good.&lt;/p&gt;

&lt;p&gt;e.g. "Official" method to get the details of the transaction (from the &lt;code&gt;txn_hash&lt;/code&gt;) returns something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b§234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nonce&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blockHash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blockNumber&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transactionIndex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;from&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;to&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x6295ee1b4f6dd65047762f924ecd367c17eabf8f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123450000000000000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;314159&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gasPrice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2000000000000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x57cb2fc4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It doesn't really mean much - even to the developers. Sure &lt;code&gt;from&lt;/code&gt; and &lt;code&gt;to&lt;/code&gt; addresses provide some useful data, but we don't know what "operation" was performed and with what data. (The data is in the &lt;code&gt;input&lt;/code&gt; field shown above, but does not make sense "as-is")&lt;/p&gt;

&lt;p&gt;What if you could see something like the following, instead ?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mintToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5bb4b21e60d0033a1b86b83e4a1f8307ab2d01f9&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You get the function &lt;strong&gt;name&lt;/strong&gt;, not an address, and the parameters passed to the function - which can be "somewhat" useful, depending on the the types of parameters. &lt;/p&gt;

&lt;p&gt;e.g. in the above sample, the first input param is the address and the second one  - a number.&lt;/p&gt;

&lt;p&gt;It may be easy to guess (from the function name) that we are minting 0x64 i.e. 100 tokens for a given address.&lt;/p&gt;

&lt;p&gt;Isn't that much better ?&lt;/p&gt;

&lt;p&gt;Getting such "human readable" output is made possible by &lt;code&gt;ethereum-input-data-decoder&lt;/code&gt; library - which does the &lt;em&gt;heavy lifting&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I added some wrapper functionality to make it as generic as possible without having to make code changes.&lt;/p&gt;

&lt;p&gt;You can pass the &lt;code&gt;txn_hash&lt;/code&gt; and the path to the JSON file created by &lt;code&gt;truffle compile&lt;/code&gt; as arguments to the script.&lt;/p&gt;

&lt;p&gt;Thus it works for &lt;strong&gt;any&lt;/strong&gt; contract.&lt;/p&gt;




&lt;p&gt;You can see the source code &lt;a href="https://github.com/mandarvaze/eth-playground/tree/master/utils"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any queries (about the code) feel free to file a github issue (or ask here in comments)&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
