<?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: Ahmed Helmi</title>
    <description>The latest articles on DEV Community by Ahmed Helmi (@00geekinside00).</description>
    <link>https://dev.to/00geekinside00</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%2F172279%2F17c7fb56-7ff0-4718-b354-c0accc8a8384.jpeg</url>
      <title>DEV Community: Ahmed Helmi</title>
      <link>https://dev.to/00geekinside00</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/00geekinside00"/>
    <language>en</language>
    <item>
      <title>How to Use a Terraform Provider Locally</title>
      <dc:creator>Ahmed Helmi</dc:creator>
      <pubDate>Fri, 28 Feb 2025 15:21:10 +0000</pubDate>
      <link>https://dev.to/00geekinside00/how-to-use-a-terraform-provider-locally-p6m</link>
      <guid>https://dev.to/00geekinside00/how-to-use-a-terraform-provider-locally-p6m</guid>
      <description>&lt;p&gt;Recently, I was working on a project that needed Terraform, but there was a catch; I had to work in an environment where there is no access to the Terraform Registry. So, I had to figure out how to use a Terraform provider locally, without relying on Terraform’s online registry. If you’re in a similar boat whether for testing, security, or any other reason then this guide is for you!&lt;/p&gt;

&lt;p&gt;Terraform doesn’t just pick up providers from your directory automatically. You need to set things up manually, and that’s where my scripts come in. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Get Your Provider Binary
&lt;/h3&gt;

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

&lt;p&gt;First, grab your provider binary file (in this case, we’re using &lt;code&gt;vsphere&lt;/code&gt; with version &lt;code&gt;2.10.0&lt;/code&gt;). Make sure it's in your working directory before running the script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Run the PowerShell Script (Windows)
&lt;/h3&gt;

&lt;p&gt;Save the following script as &lt;code&gt;setup-local-provider.ps1&lt;/code&gt; and execute it in your PowerShell terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# PowerShell script to setup local Terraform provider in current directory&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.10.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vsphere"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$providerBinary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"terraform-provider-&lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="se"&gt;`_&lt;/span&gt;&lt;span class="s2"&gt;v&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="s2"&gt;.exe"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Function to create terraform.rc file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Create-TerraformRC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$rcContent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sh"&gt;@"
provider_installation {
  filesystem_mirror {
    path = "&lt;/span&gt;&lt;span class="bp"&gt;$PWD&lt;/span&gt;&lt;span class="sh"&gt;\.terraform\plugins"
  }
  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}
"@&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nv"&gt;$rcPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;APPDATA&lt;/span&gt;&lt;span class="s2"&gt;\terraform.rc"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$rcContent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$rcPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UTF8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Created terraform.rc at: &lt;/span&gt;&lt;span class="nv"&gt;$rcPath&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Function to create provider.tf file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Create-ProviderConfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$tfContent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sh"&gt;@"
terraform {
  required_providers {
    &lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="sh"&gt; = {
      source = "hashicorp/&lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="sh"&gt;"
      version = "&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="sh"&gt;"
    }
  }
}
"@&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nv"&gt;$tfPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"provider.tf"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$tfContent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tfPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UTF8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Created provider.tf configuration"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;# Verify provider binary exists in current directory&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$providerBinary&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="kr"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Provider binary not found in current directory: &lt;/span&gt;&lt;span class="nv"&gt;$providerBinary&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Create directory structure&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$providerDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".terraform/plugins/registry.terraform.io/hashicorp/&lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="s2"&gt;/windows_amd64"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$providerDir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-Null&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Created provider directory structure"&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Copy provider binary&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Copy-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$providerBinary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$providerDir&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$providerBinary&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Copied provider binary to: &lt;/span&gt;&lt;span class="nv"&gt;$providerDir&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$providerBinary&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Create terraform.rc file&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Create-TerraformRC&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Create provider configuration&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Create-ProviderConfig&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;`n&lt;/span&gt;&lt;span class="s2"&gt;Setup completed successfully!&lt;/span&gt;&lt;span class="se"&gt;`n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Next steps:"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1. Run terraform init -plugin-dir='.terraform/plugins' to initialize your working directory"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2. Create your terraform configuration files (.tf)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3. Run 'terraform plan' to verify the setup"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error: &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ForegroundColor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Red&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Run the Linux Script (Linux/macOS)
&lt;/h3&gt;

&lt;p&gt;Save the following script as &lt;code&gt;setup-local-provider.sh&lt;/code&gt; and execute it in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2.10.0"&lt;/span&gt;
&lt;span class="nv"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"vsphere"&lt;/span&gt;
&lt;span class="nv"&gt;provider_binary&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"terraform-provider-&lt;/span&gt;&lt;span class="nv"&gt;$provider_v$version&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Function to create terraform.rc file&lt;/span&gt;
create_terraform_rc&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; ~/.terraformrc
provider_installation {
  filesystem_mirror {
    path = "&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="sh"&gt;/.terraform/plugins"
  }
  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Created terraform.rc at ~/.terraformrc"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Function to create provider.tf file&lt;/span&gt;
create_provider_config&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; provider.tf
terraform {
  required_providers {
    &lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="sh"&gt; = {
      source = "hashicorp/&lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="sh"&gt;"
      version = "&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="sh"&gt;"
    }
  }
}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Created provider.tf configuration"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Main setup&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$provider_binary&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Provider binary not found in current directory: &lt;/span&gt;&lt;span class="nv"&gt;$provider_binary&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Create directory structure&lt;/span&gt;
&lt;span class="nv"&gt;provider_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;".terraform/plugins/registry.terraform.io/hashicorp/&lt;/span&gt;&lt;span class="nv"&gt;$provider&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="s2"&gt;/linux_amd64"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$provider_dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Created provider directory structure"&lt;/span&gt;

&lt;span class="c"&gt;# Copy provider binary&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$provider_binary&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$provider_dir&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Copied provider binary to: &lt;/span&gt;&lt;span class="nv"&gt;$provider_dir&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$provider_binary&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Create terraform.rc file&lt;/span&gt;
create_terraform_rc

&lt;span class="c"&gt;# Create provider configuration&lt;/span&gt;
create_provider_config

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Setup completed successfully!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Next steps:"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"1. Run twtrito initialize your working directory"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"2. Create your terraform configuration files (.tf)"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"3. Run 'terraform plan' to verify the setup"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Step 4: Initialize Terraform
&lt;/h3&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init &lt;span class="nt"&gt;-plugin-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'.terraform/plugins'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This tells Terraform to use the local plugin directory instead of trying to download the provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Verify Your Setup
&lt;/h3&gt;

&lt;p&gt;Try running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If everything is set up correctly, Terraform should recognize the provider and not try to download it from the registry.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>infrastructureascode</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Unlocking the Potential of Cloudflare Workers for Small Projects</title>
      <dc:creator>Ahmed Helmi</dc:creator>
      <pubDate>Sat, 27 Jul 2024 09:57:29 +0000</pubDate>
      <link>https://dev.to/00geekinside00/unlocking-the-potential-of-cloudflare-workers-for-small-projects-45d0</link>
      <guid>https://dev.to/00geekinside00/unlocking-the-potential-of-cloudflare-workers-for-small-projects-45d0</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%2Fuploads%2Farticles%2Fr09vzbcjd0cx6i623z10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr09vzbcjd0cx6i623z10.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cloudflare Workers is a serverless platform that allows developers to run code at the edge, close to the end users. Unlike some other serverless platforms that run in centralized data centers, Cloudflare Workers run in over 200 locations worldwide, providing lower latency and high performance. This article explores why Cloudflare Workers is a fantastic choice for smaller projects and offers a practical use case of creating a Telegram bot using Cloudflare Workers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Choose Cloudflare Workers for Smaller Projects?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Low Latency and High Performance&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Imagine your code running in data centers closest to your users, reducing latency significantly and providing a fast, responsive experience. Cloudflare Workers make this possible by running at the edge. This advantage is particularly crucial for smaller projects with a distributed user base. &lt;a href="https://www.cloudflare.com/network/" rel="noopener noreferrer"&gt;Learn more about Cloudflare's edge network&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Cost Efficiency&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Budget constraints are a common concern for small projects. Cloudflare Workers offers a generous free tier that includes up to 100,000 requests per day, often more than enough for smaller projects. Beyond that, the pricing remains competitive, helping you keep costs minimal. &lt;a href="https://workers.cloudflare.com/#pricing" rel="noopener noreferrer"&gt;See Cloudflare Workers pricing&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Ease of Deployment and Maintenance&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;One of the most appealing aspects of Cloudflare Workers is the simplicity of deployment. There's no need to manage servers or worry about infrastructure. This ease of use allows you to focus on what matters most: developing and deploying your project quickly. &lt;a href="https://developers.cloudflare.com/workers/get-started/guide" rel="noopener noreferrer"&gt;Get started with Cloudflare Workers&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Scalability&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Even small projects can experience unexpected traffic spikes. Cloudflare Workers scale automatically to handle increased load, ensuring your project remains responsive and reliable without requiring any intervention. &lt;a href="https://blog.cloudflare.com/cloud-computing-without-containers/" rel="noopener noreferrer"&gt;Learn about Cloudflare’s scalability&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Built-in Security&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Security is crucial, especially for web applications. Cloudflare provides built-in DDoS protection, SSL/TLS encryption, and other security features to protect your application without additional configuration or cost. For smaller projects, this means robust security without the hassle. &lt;a href="https://www.cloudflare.com/products/" rel="noopener noreferrer"&gt;Explore Cloudflare’s security features&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key-Value Storage and Database Services
&lt;/h3&gt;

&lt;p&gt;Cloudflare offers additional services that complement Cloudflare Workers, making it even more powerful for small projects.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Cloudflare Workers KV&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Workers KV is a global, low-latency key-value storage system. It allows you to store and retrieve data quickly, making it perfect for caching, configuration, and session management. With Workers KV, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Store data globally:&lt;/strong&gt; Data is replicated across Cloudflare's edge network, providing high availability and low latency access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage configurations:&lt;/strong&gt; Store configuration data that needs to be quickly accessible by your Worker scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache responses:&lt;/strong&gt; Cache static assets or frequently accessed data to improve performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developers.cloudflare.com/workers/learning/how-kv-works" rel="noopener noreferrer"&gt;Learn more about Workers KV&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Cloudflare D1&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Cloudflare D1 is a managed SQL database built on SQLite, designed for serverless applications. It integrates seamlessly with Cloudflare Workers, enabling you to use a familiar SQL interface for data management. D1 is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prototyping and development:&lt;/strong&gt; Quickly spin up a database for your applications without managing infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small to medium-sized applications:&lt;/strong&gt; Use a scalable SQL database for applications that require relational data storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://developers.cloudflare.com/d1/" rel="noopener noreferrer"&gt;Learn more about Cloudflare D1&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perfect for Prototyping and Hackathons
&lt;/h3&gt;

&lt;p&gt;Cloudflare Workers shine in environments where rapid development and deployment are crucial, such as prototyping and hackathons.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Rapid Deployment&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In hackathons and prototyping, time is of the essence. Cloudflare Workers enable you to deploy your code almost instantly without setting up servers or worrying about infrastructure, allowing you to focus on developing features and iterating quickly.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Minimal Setup&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Getting started with Cloudflare Workers requires minimal setup, making it perfect for hackathons where simplicity and speed are vital.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Real-Time Testing&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Cloudflare Workers run at the edge, allowing you to test your application in real-time and see how it performs under different network conditions. This immediate feedback is invaluable for refining your prototype or hackathon project on the fly.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Scalable Infrastructure&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;During a hackathon, you may not know how many users will interact with your project. Cloudflare Workers' ability to scale automatically ensures that your application can handle unexpected spikes in traffic, providing a seamless experience for users and judges alike.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Cost-Effective Experimentation&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Hackathons and prototypes often operate on a limited budget. With Cloudflare Workers' generous free tier, you can experiment with different ideas without worrying about incurring significant costs. This allows for more creative freedom and innovation.&lt;/p&gt;

&lt;h3&gt;
  
  
  USECASE: Creating a Telegram Bot with Cloudflare Workers
&lt;/h3&gt;

&lt;p&gt;Let's create a simple Telegram bot using Cloudflare Workers, integrating Workers KV for storing user data and Cloudflare D1 for managing a simple database. This bot will respond to user messages with a predefined response and store user messages in a database.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Set Up Your Cloudflare Worker
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a Cloudflare Account&lt;/strong&gt;: If you don’t have one, sign up at &lt;a href="https://www.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Up a Worker&lt;/strong&gt;: In the Cloudflare dashboard, navigate to the Workers section and create a new Worker.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 2: Configure Workers KV
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a KV Namespace&lt;/strong&gt;: In the Workers section of the Cloudflare dashboard, go to the "KV" tab and create a new namespace. Note the &lt;code&gt;KV_NAMESPACE_ID&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bind the KV Namespace to Your Worker&lt;/strong&gt;: In the Worker configuration, add a binding for the KV namespace:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kv_namespace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MY_KV_NAMESPACE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"namespace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KV_NAMESPACE_ID"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Set Up Cloudflare D1
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a D1 Database&lt;/strong&gt;: In the Cloudflare dashboard, go to the D1 section and create a new database. Note the &lt;code&gt;D1_DATABASE_ID&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bind the D1 Database to Your Worker&lt;/strong&gt;: In the Worker configuration, add a binding for the D1 database:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"d1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MY_D1_DATABASE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"database_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"D1_DATABASE_ID"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Write the Bot Code
&lt;/h4&gt;

&lt;p&gt;Here’s a basic example of a Telegram bot using Cloudflare Workers, Workers KV, and Cloudflare D1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/webhook&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from Cloudflare Workers!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="c1"&gt;// Store user message in KV&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;MY_KV_NAMESPACE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Insert user message into D1 database&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;MY_D1_DATABASE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`INSERT INTO messages (chat_id, message) VALUES (?, ?)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Not Found&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_TELEGRAM_BOT_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://api.telegram.org/bot&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/sendMessage`&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;h4&gt;
  
  
  Step 5: Configure Telegram Webhook
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a Telegram Bot&lt;/strong&gt;: If you haven't already, create a bot by talking to &lt;a href="https://t.me/botfather" rel="noopener noreferrer"&gt;BotFather&lt;/a&gt; on Telegram.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set the Webhook URL&lt;/strong&gt;: Use the following command to set your webhook URL to your Cloudflare Worker URL:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   https://api.telegram.org/bot&amp;lt;YOUR_BOT_TOKEN&amp;gt;/setWebhook?url=https://&amp;lt;YOUR_WORKER_SUBDOMAIN&amp;gt;.workers.dev/webhook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 6: Test Your Bot
&lt;/h4&gt;

&lt;p&gt;Send a message to your bot on Telegram, and it should respond with "Hello from Cloudflare Workers!" It will also store the message in the Workers KV and insert it into the D1 database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Cloudflare Workers provide a powerful, cost-effective, and scalable solution for smaller projects. With low latency, ease of deployment, built-in security, and scalability, Cloudflare Workers are an excellent choice for developers looking to build and deploy applications quickly. The example of creating a Telegram bot demonstrates how simple and effective it can be to use Cloudflare Workers, Workers KV, and Cloudflare D1 for your projects.&lt;/p&gt;

&lt;p&gt;Whether you're prototyping a new idea or participating in a hackathon, Cloudflare Workers offer the speed, simplicity, and flexibility needed to turn your vision into reality swiftly and efficiently. And with the added power of Cloudflare’s key-value storage and managed database services, you have all the tools you need to build robust and responsive applications.&lt;/p&gt;

</description>
      <category>cloudflarechallenge</category>
      <category>serverless</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Google Chrome DevTools: Handy Tips</title>
      <dc:creator>Ahmed Helmi</dc:creator>
      <pubDate>Mon, 25 Dec 2023 15:26:46 +0000</pubDate>
      <link>https://dev.to/00geekinside00/google-chrome-devtools-handy-tips-and-tricks-241l</link>
      <guid>https://dev.to/00geekinside00/google-chrome-devtools-handy-tips-and-tricks-241l</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DS46Y-m3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8yg44c6n9qywh7v7kdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DS46Y-m3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8yg44c6n9qywh7v7kdf.png" alt="Image description" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google Chrome DevTools is a powerful set of web development tools built directly into the Chrome browser. It provides a wide range of features that help developers debug, optimize, and understand web applications. In this article, we'll unravel more features, sprinkle in additional tips. Let's dive in!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Gateway to DevTools Magic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To open devtools just right-click anywhere on a webpage, choose "Inspect," and voila! If you're into shortcuts, hit Ctrl+Shift+I (Windows/Linux) or Cmd+Opt+I (Mac). Also you can find it in the Chrome menu under "More Tools" &amp;gt; "Developer Tools."&lt;/p&gt;

&lt;p&gt;Dark Mode: Click the gear icon in the top-right corner of DevTools and choose "Preferences." Embrace the darkness by enabling the "Dark Theme" for a sleek and magical appearance.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jRj-7Ozv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1xx3zsjxbptgehxqept.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jRj-7Ozv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1xx3zsjxbptgehxqept.png" alt="Image description" width="640" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Play with Devices
Touch and Feel: Toggle the "Toggle device toolbar" button to simulate touch interactions. Feel the of touch events without getting fingerprints on your screen.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt; Console tricks!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;a. Magic Commands&lt;br&gt;
&lt;code&gt;$_&lt;/code&gt; to the Rescue: Use &lt;code&gt;$_&lt;/code&gt; in the console to reference the result of the last expression. It's like summoning the spirit of your previous command.&lt;/p&gt;

&lt;p&gt;b. Fancy Logging&lt;br&gt;
Styling Your Logs: Add &lt;code&gt;%c&lt;/code&gt; to your console.log and apply CSS styles to your log messages. Spice up your console with colors and fonts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6xZ-Hpeb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/611erjpodbsh2pq70jw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6xZ-Hpeb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/611erjpodbsh2pq70jw6.png" alt="Image description" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;c. Table Talk&lt;br&gt;
Multidimensional Tables: Nest arrays and objects within your data for a table. :)&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;The Story of Your Code in the Source Panel&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;a. Hide and Seek&lt;br&gt;
Navigate with Precision: Use Ctrl+P (Windows/Linux) or Cmd+P (Mac) to quickly navigate and find files in the source panel. &lt;/p&gt;

&lt;p&gt;It's like having a file finder of vscode.&lt;/p&gt;

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

&lt;p&gt;b. Breakpoints with Conditions&lt;/p&gt;

&lt;p&gt;Logpoint : Instead of stopping at a breakpoint, set a "Logpoint" to log a message to the console. Keep the magic flowing without interrupting the spell ;)&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Network Adventures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;a. Speed Bumps&lt;/p&gt;

&lt;p&gt;Online, Offline, and Beyond: Simulate offline experiences by checking the "Offline" option in the Network panel. Experience the magic of how your website behaves without an internet connection.&lt;/p&gt;

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

&lt;p&gt;b. Copy-Paste Wizardry&lt;/p&gt;

&lt;p&gt;Preserve the Magic: When copying an object from the console, use copy(myObject) to preserve the object in its original form. No more losing properties during the copy-paste ritual.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performance Magic Show&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;a. Lights, Camera, Action!&lt;br&gt;
Frame Mode: In the Performance panel, switch to "Frames" mode to analyze your website's performance frame by frame. It's like directing a movie of your web page.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Application Playground&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;a. Storage Treasure Hunt&lt;br&gt;
IndexedDB Explorer: Under the "Application" panel, explore IndexedDB with the "IndexedDB" tab.]&lt;/p&gt;

&lt;p&gt;b. Application Manifest Magic&lt;br&gt;
Manifest Insights: Check the "Manifest" tab to inspect your web app's manifest file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Miscellaneous Enchantments&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Search Everywhere: Press Ctrl+Shift+F (Windows/Linux) or Cmd+Opt+F (Mac) to search across all DevTools panels. A magical way to find what you seek without going too far.&lt;/p&gt;

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

&lt;p&gt;In Conclusion&lt;br&gt;
Google Chrome DevTools is a versatile tool that can greatly improve your web development workflow. By incorporating these tips and tricks into your routine, you'll be able to debug more efficiently, optimize performance, and gain a deeper understanding of your web applications.  &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>debug</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Cloud Computing Made Easy: A Beginner's Guide</title>
      <dc:creator>Ahmed Helmi</dc:creator>
      <pubDate>Thu, 09 Nov 2023 07:45:52 +0000</pubDate>
      <link>https://dev.to/00geekinside00/cloud-computing-made-easy-a-beginners-guide-9kj</link>
      <guid>https://dev.to/00geekinside00/cloud-computing-made-easy-a-beginners-guide-9kj</guid>
      <description>&lt;p&gt;In the digital age, cloud computing has become a fundamental component of our daily lives. Whether we're storing files, streaming content, or running business applications, the cloud plays a crucial role in how we access and manage data and services. In this article, we will explore the basic concepts of cloud computing, demystifying the technology that powers the digital world.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Cloud Computing?
&lt;/h2&gt;

&lt;p&gt;At its core, cloud computing refers to the delivery of computing services, including storage, processing power, and software, over the internet. Instead of relying on local servers or personal devices, users access these resources remotely through data centers maintained by cloud service providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Characteristics
&lt;/h2&gt;

&lt;p&gt;a. On-Demand Self-Service: Cloud users can provision and manage resources as needed, without requiring human intervention from the service provider.&lt;/p&gt;

&lt;p&gt;b. Broad Network Access: Cloud services are accessible over the internet from a variety of devices, such as laptops, smartphones, and tablets.&lt;/p&gt;

&lt;p&gt;c. Resource Pooling: Cloud providers pool resources to serve multiple customers. These resources are dynamically allocated and reassigned as needed.&lt;/p&gt;

&lt;p&gt;d. Rapid Elasticity: Cloud resources can be quickly scaled up or down to accommodate changing demands, ensuring efficient resource utilization.&lt;/p&gt;

&lt;p&gt;e. Measured Service: Cloud usage is metered, allowing users to pay only for the resources they consume. This pay-as-you-go model is cost-effective and flexible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Models
&lt;/h2&gt;

&lt;p&gt;Cloud computing offers various service models to cater to different user needs:&lt;/p&gt;

&lt;p&gt;a. Infrastructure as a Service (IaaS): IaaS provides virtualized computing resources, such as virtual machines, storage, and networking. Users have control over the operating system and applications.&lt;/p&gt;

&lt;p&gt;b. Platform as a Service (PaaS): PaaS offers a platform that allows developers to build, deploy, and manage applications without worrying about the underlying infrastructure.&lt;/p&gt;

&lt;p&gt;c. Software as a Service (SaaS): SaaS delivers software applications over the internet on a subscription basis. Users access the software through a web browser without installing or maintaining it locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment Models
&lt;/h2&gt;

&lt;p&gt;Cloud computing can be deployed in various ways to meet different requirements:&lt;/p&gt;

&lt;p&gt;a. Public Cloud: Public cloud services are provided by third-party cloud service providers and are available to anyone over the internet. They are cost-effective and scalable but may raise security and privacy concerns.&lt;/p&gt;

&lt;p&gt;b. Private Cloud: Private clouds are built and maintained by organizations for their exclusive use. They offer greater control, security, and customization but can be more expensive to set up and manage.&lt;/p&gt;

&lt;p&gt;c. Hybrid Cloud: Hybrid cloud combines public and private cloud services, allowing data and applications to be shared between them. This model provides flexibility and scalability while addressing security and compliance concerns.&lt;/p&gt;

&lt;p&gt;d. Community Cloud: A community cloud is shared by a specific group of organizations with common interests, such as regulatory compliance. It offers a balance between public and private clouds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Cloud Computing
&lt;/h2&gt;

&lt;p&gt;Cloud computing offers several advantages, including:&lt;/p&gt;

&lt;p&gt;a. Cost Savings: Organizations can reduce capital expenses and only pay for the resources they use.&lt;/p&gt;

&lt;p&gt;b. Scalability: Businesses can easily scale up or down based on demand, ensuring efficient resource allocation.&lt;/p&gt;

&lt;p&gt;c. Accessibility: Cloud services are accessible from anywhere with an internet connection.&lt;/p&gt;

&lt;p&gt;d. Reliability: Leading cloud providers offer high availability and redundancy, reducing downtime.&lt;/p&gt;

&lt;p&gt;e. Security: Reputable cloud providers invest heavily in security measures to protect data and infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Considerations
&lt;/h2&gt;

&lt;p&gt;While cloud computing provides numerous benefits, it also comes with its own set of challenges:&lt;/p&gt;

&lt;p&gt;a. Security and Privacy: Organizations must trust cloud providers with their data, and data breaches or unauthorized access can be a concern.&lt;/p&gt;

&lt;p&gt;b. Compliance: Companies in regulated industries may face challenges in meeting compliance requirements when using the cloud.&lt;/p&gt;

&lt;p&gt;c. Downtime: Internet connectivity issues or outages on the provider's end can disrupt services.&lt;/p&gt;

&lt;p&gt;d. Data Transfer Costs: Moving data in and out of the cloud can result in additional expenses.&lt;/p&gt;

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

&lt;p&gt;Cloud computing is a transformative technology that has revolutionized the way individuals and organizations access and manage their digital resources. By understanding the basic concepts, service models, deployment options, and potential benefits and challenges, you can make informed decisions about how to leverage the power of the cloud in your personal or business endeavors.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>🌟 Keeping It Simple: Usable Security for the Everyday User 🌟</title>
      <dc:creator>Ahmed Helmi</dc:creator>
      <pubDate>Tue, 15 Aug 2023 16:08:43 +0000</pubDate>
      <link>https://dev.to/00geekinside00/keeping-it-simple-usable-security-for-the-everyday-user-28p4</link>
      <guid>https://dev.to/00geekinside00/keeping-it-simple-usable-security-for-the-everyday-user-28p4</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0nOdwQD8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngzs53cohfvzx8li0gq8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0nOdwQD8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngzs53cohfvzx8li0gq8.png" alt="Image description" width="768" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey there, folks! Let's dive into a topic that affects all of us in the digital world: usable security. Usable security refers to the design and implementation of security measures and systems in a way that prioritizes the user experience and usability, while still maintaining a high level of protection against security threats. It aims to strike a balance between effective security practices and the ease of use for individuals interacting with those security measures.&lt;/p&gt;

&lt;p&gt;🔒 The Struggle is Real:&lt;br&gt;
We've all been there – faced with complicated security measures that make us want to pull out our hair. Who can blame us? Remembering long, convoluted passwords filled with a mix of uppercase, lowercase, symbols, and a secret handshake? It's enough to give anyone a headache. But fear not, my friends, because usable security is here to save the day!&lt;/p&gt;

&lt;p&gt;🔐 Putting the "User" in "Usable":&lt;br&gt;
Usable security is all about understanding us, the users. It's about designing security systems that fit our needs and capabilities like a glove. After all, security should be for everyone, not just tech gurus. So, let's bring on the user-friendly interfaces, straightforward instructions, and intuitive workflows. We want security measures that won't make us feel like we need a degree in rocket science to navigate them!&lt;/p&gt;

&lt;p&gt;In the context of usable security, the focus is on creating security solutions that are accessible, intuitive, and user-friendly, reducing the cognitive load and frustration often associated with traditional complex security measures. The goal is to encourage users to adopt and comply with security practices by making them understandable, straightforward, and seamlessly integrated into their digital interactions.&lt;/p&gt;

&lt;p&gt;Usable security takes into account human factors, such as cognitive abilities, behavioral patterns, and user expectations. It involves designing clear and concise user interfaces, providing understandable instructions and feedback, and aligning security measures with user needs and capabilities. By doing so, usable security aims to enhance user acceptance and cooperation, ultimately leading to improved security outcomes.&lt;/p&gt;

&lt;p&gt;💡 Tips for a User-Friendly Security Experience:&lt;br&gt;
1️⃣ Keep It Simple, Silly: Let's simplify the complex. No one wants to feel like they're decoding the Da Vinci Code just to access their accounts. Streamline security processes and present information in plain language. We're all about keeping it simple and stress-free.&lt;/p&gt;

&lt;p&gt;2️⃣ Be Transparent: Trust is the name of the game. Be open and honest about security risks, privacy policies, and why certain security measures are necessary. When we understand the "why" behind the hoops we're jumping through, we're more likely to cooperate.&lt;/p&gt;

&lt;p&gt;3️⃣ Show Us the Way: User-friendly interfaces are our best friends. Invest in designs that guide us through security processes with ease. No more guessing games or feeling like we're wandering in a digital labyrinth. Let's make security a walk in the park!&lt;/p&gt;

&lt;p&gt;4️⃣ Educate and Empower: Knowledge is power. Educate us about common security threats, best practices, and why security matters. Teach us how to fish, so we can protect ourselves even when you're not around. We're in this together!&lt;/p&gt;

&lt;p&gt;5️⃣ Evolve and Adapt: The digital landscape is ever-changing, and so are the threats we face. Stay on top of the latest trends, research, and industry standards. Continuously improve security measures based on user feedback and emerging technologies. Let's keep our defenses up-to-date and our security game strong.&lt;/p&gt;

&lt;p&gt;🔒 A Brighter, User-Friendly Future:&lt;br&gt;
Usable security is our ticket to a safer digital world without the headaches. By prioritizing user experience and making security accessible to everyone, we can create a future where protection and simplicity coexist in harmony.&lt;/p&gt;

&lt;p&gt;So, my friends, let's champion usable security! Share your thoughts, funny security anecdotes, or tips in the comments below. Together, we can make security a friend, not a foe.  🔒💻&lt;/p&gt;

</description>
      <category>programming</category>
      <category>usability</category>
      <category>security</category>
    </item>
    <item>
      <title>Recording and Replaying HTTP Interactions with Ease: A Guide to VCR.py</title>
      <dc:creator>Ahmed Helmi</dc:creator>
      <pubDate>Wed, 05 Jul 2023 03:19:49 +0000</pubDate>
      <link>https://dev.to/00geekinside00/recording-and-replaying-http-interactions-with-ease-a-guide-to-vcrpy-1c70</link>
      <guid>https://dev.to/00geekinside00/recording-and-replaying-http-interactions-with-ease-a-guide-to-vcrpy-1c70</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Testing code that interacts with external services can be tricky. You need to make sure that your code is handling all the possible responses correctly, and that it's not making too many unnecessary requests. But how do you test this kind of code reliably and efficiently?&lt;/p&gt;

&lt;p&gt;That's where VCR.py comes in. The idea behind VCR.py is simple: it records HTTP interactions made by your code, and then replays them when your tests run. That way, your tests can simulate HTTP requests without actually hitting the external service. Pretty neat, right?&lt;/p&gt;

&lt;p&gt;In this article, we'll take a closer look at VCR.py and some of its features. We'll cover how to use VCR.py to record and replay HTTP interactions, how to customize its behavior with matchers and filters, and how to work with the cassette file that VCR.py uses to store recorded interactions.&lt;/p&gt;

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

&lt;p&gt;To get started with VCR.py, you'll need to install it first. You can do this using pip:&lt;/p&gt;

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

pip &lt;span class="nb"&gt;install &lt;/span&gt;vcrpy


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

&lt;/div&gt;

&lt;p&gt;Once you have VCR.py installed, you can start using it in your tests. Here's a simple example:&lt;/p&gt;

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

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_cassette&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test_api.yaml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;once&lt;/span&gt;&lt;span class="sh"&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;test_api&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="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.example.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&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;200&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In this example, we're using VCR.py to intercept a GET request to &lt;code&gt;https://api.example.com&lt;/code&gt;. The first time this test is run, VCR.py will record the HTTP interaction in a cassette file named &lt;code&gt;test_api.yaml&lt;/code&gt;. On subsequent runs, VCR.py will replay the recorded interaction from the cassette file instead of making a new request.&lt;/p&gt;

&lt;p&gt;Record_mode that passed in with the VCR cassette determines how the interactions with an external API are recorded. There are four record modes available:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;once&lt;/code&gt;: This mode will record the interactions with the external API the first time the test is run. Subsequent runs of the test will use the recorded interactions instead of making new requests to the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;new_episodes&lt;/code&gt;: This mode will record any interactions with the external API that haven't been previously recorded. If an interaction has already been recorded, it will be replayed instead of making a new request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;all&lt;/code&gt;: This mode will record all interactions with the external API, regardless of whether they have been previously recorded or not. This is useful for building up a complete set of recordings for an API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;none&lt;/code&gt;: This mode will turn off recording altogether and will only replay previously recorded interactions. This mode is useful when you want to ensure that your tests are only using recorded interactions and not making any new requests to the external API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the previous example, the &lt;code&gt;record_mode&lt;/code&gt; argument is set to &lt;code&gt;'once'&lt;/code&gt;, which means that the interactions with the external API will be recorded the first time the test is run and subsequently replayed on all subsequent runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with the Cassette File
&lt;/h2&gt;

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

&lt;p&gt;The cassette file is where VCR.py stores recorded HTTP interactions. By default, the cassette file is a YAML file, but you can also use JSON or SQLite. The cassette file can be easily read and edited, which makes it easy to inspect the contents of the file and make changes if necessary.&lt;/p&gt;

&lt;p&gt;Here's an example of a cassette file:&lt;/p&gt;

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

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!!binary&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;eyJ0ZXN0IjoidGVzdCJ9&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://api.example.com/foo&lt;/span&gt;
  &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!!binary&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;{"id": "123", "foo": "bar"}&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OK&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In this example, we have a single interaction that was recorded. The interaction consists of a POST request to &lt;code&gt;https://api.example.com/foo&lt;/code&gt; with a JSON request body, and a response with a JSON body containing an ID and a foo value.&lt;/p&gt;

&lt;p&gt;One important thing to keep in mind when working with the cassette file is that it can become quite large if you have a lot of interactions recorded. To help with this, VCR.py provides several options for controlling how interactions are recorded and stored in the cassette file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Matchers
&lt;/h2&gt;

&lt;p&gt;By default, VCR.py matches HTTP interactions based on the HTTP method, URL, and request body. But what if you want to match on other criteria, like headers or query parameters?&lt;/p&gt;

&lt;p&gt;That's where matchers come in. Matchers allow you to specify custom criteria for matching HTTP interactions. Here's an example:&lt;/p&gt;

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

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;custom_matcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Your custom matching logic here
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_cassette&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_test.yaml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                      &lt;span class="n"&gt;match_on&lt;/span&gt;&lt;span class="o"&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;method&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;uri&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;custom_matcher&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;test_my_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="c1"&gt;# Code that makes HTTP requests
&lt;/span&gt;

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

&lt;/div&gt;

&lt;p&gt;In this example, we define a custom matcher function &lt;code&gt;custom_matcher&lt;/code&gt; that takes two requests and returns &lt;code&gt;True&lt;/code&gt; if they match based on our custom criteria. We then use this custom matcher in our &lt;code&gt;use_cassette&lt;/code&gt; call, along with the default matchers for HTTP method and URI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filters
&lt;/h2&gt;

&lt;p&gt;Sometimes you might want to filter or modify requests or responses before they are recorded or played back. For example, you might want to filter out sensitive data from the response before it gets stored in the cassette file. Or you might want to modify the request headers before the request is sent.&lt;/p&gt;

&lt;p&gt;VCR.py provides two options for filtering: &lt;code&gt;before_record&lt;/code&gt; and &lt;code&gt;before_playback&lt;/code&gt;. These options allow you to specify functions that are called before requests are recorded or played back, respectively. Here's an example:&lt;/p&gt;

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

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer xxxxxxx&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Set-Cookie&lt;/span&gt;&lt;span class="sh"&gt;'&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="n"&gt;response&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_cassette&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;my_test.yaml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="n"&gt;before_record&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;filter_request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="n"&gt;before_playback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;filter_response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Your test code here
&lt;/span&gt;

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

&lt;/div&gt;

&lt;p&gt;In this example, we define two filter functions &lt;code&gt;filter_request&lt;/code&gt; and &lt;code&gt;filter_response&lt;/code&gt; that modify the request and response respectively. We then pass these filter functions to the &lt;code&gt;before_record&lt;/code&gt; and &lt;code&gt;before_playback&lt;/code&gt; options of &lt;code&gt;use_cassette&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Placeholders
&lt;/h2&gt;

&lt;p&gt;Sometimes you might have dynamic data in your responses that you don't want to hard-code in your tests. For example, if you have a test that creates a new resource and returns a unique ID, you might want to use a placeholder to represent that ID in the cassette file.&lt;/p&gt;

&lt;p&gt;VCR.py supports placeholders in the cassette file. Placeholders are strings that are replaced with actual values during playback. Here's an example:&lt;/p&gt;

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

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!!binary&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;eyJ0ZXN0IjoidGVzdCJ9&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://api.example.com/foo&lt;/span&gt;
  &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!!binary&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;{"id": "{{ ID }}", "foo": "bar"}&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OK&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In this example, we're using the &lt;code&gt;{{ ID }}&lt;/code&gt; placeholder in the response body to represent the unique ID that is generated by the API. When VCR.py replays the response, it will substitute the placeholder with the actual ID value that was returned by the API during the recording.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Illustration
&lt;/h2&gt;

&lt;p&gt;Let's assume that we have a simple Flask web application that acts as an external web service API. It returns a JSON response  when we make a GET request to the &lt;code&gt;/hello&lt;/code&gt; endpoint:&lt;/p&gt;

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

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/hello&lt;/span&gt;&lt;span class="sh"&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;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&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;Hello, World!&lt;/span&gt;&lt;span class="sh"&gt;'&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now, let's write a vcrpy test to test this API. We'll use the &lt;code&gt;requests&lt;/code&gt; library to make the HTTP request to the API:&lt;/p&gt;

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

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_hello_api&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_cassette&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hello_api.yaml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;once&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&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:5000/hello&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&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;200&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&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;Hello, World!&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;In this test, we're using the &lt;code&gt;use_cassette&lt;/code&gt; context manager to wrap the HTTP request to our Flask app. We're specifying that we want to use the cassette file &lt;code&gt;hello_api.yaml&lt;/code&gt; to record the interactions with the API, and we're using the &lt;code&gt;record_mode&lt;/code&gt; argument to specify that we only want to record the interactions once (i.e., on the first run of the test).&lt;/p&gt;

&lt;p&gt;When we run this test for the first time, vcrpy will record the interaction with the Flask app and save it to the &lt;code&gt;hello_api.yaml&lt;/code&gt; file. On subsequent runs of the test, vcrpy will replay the interaction from the cassette file instead of making a new HTTP request to the Flask app.&lt;/p&gt;

&lt;p&gt;To run this test, we can simply execute the test file using a test runner such as pytest:&lt;/p&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;pytest test_hello_api.py


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

&lt;/div&gt;

&lt;p&gt;This will run the test and output the results of the assertions. If the test passes, we should see output similar to the following:&lt;/p&gt;

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

&lt;span class="o"&gt;============================&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;session starts &lt;span class="o"&gt;============================&lt;/span&gt;
collected 1 item

test_hello_api.py &lt;span class="nb"&gt;.&lt;/span&gt;                                                   &lt;span class="o"&gt;[&lt;/span&gt;100%]

&lt;span class="o"&gt;=============================&lt;/span&gt; 1 passed &lt;span class="k"&gt;in &lt;/span&gt;0.13s &lt;span class="o"&gt;=============================&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;If the test fails, we'll see an error message indicating which assertion failed.&lt;/p&gt;

&lt;p&gt;here's what the &lt;code&gt;hello_api.yaml&lt;/code&gt; cassette file might look like after vcrpy records the HTTP interaction with the Flask app (ie. our external API):&lt;/p&gt;

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

&lt;span class="na"&gt;interactions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Accept-Encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;identity&lt;/span&gt;
      &lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keep-alive&lt;/span&gt;
      &lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost:5000&lt;/span&gt;
      &lt;span class="na"&gt;User-Agent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python-requests/2.25.1&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:5000/hello&lt;/span&gt;
  &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utf-8&lt;/span&gt;
      &lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"message":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Hello,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;World!"}'&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Keep-Alive&lt;/span&gt;
      &lt;span class="na"&gt;Content-Length&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;25'&lt;/span&gt;
      &lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
      &lt;span class="na"&gt;Date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Mon, 05 Jul 2023 12:34:56 GMT&lt;/span&gt;
      &lt;span class="na"&gt;Keep-Alive&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;timeout=5, max=100&lt;/span&gt;
      &lt;span class="na"&gt;Server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Werkzeug/2.0.2 Python/3.9.5&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OK&lt;/span&gt;
  &lt;span class="na"&gt;recorded_at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2023-07-05T12:34:56.789012Z&lt;/span&gt;
  &lt;span class="na"&gt;recorded_with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vcrpy/4.1.1&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This file contains a YAML representation of the HTTP interaction between the test and the Flask app. The &lt;code&gt;interactions&lt;/code&gt; section contains a list of all the HTTP interactions that were recorded, in this case just one. The &lt;code&gt;request&lt;/code&gt; and &lt;code&gt;response&lt;/code&gt; sections contain the request and response headers and bodies, respectively. The &lt;code&gt;recorded_at&lt;/code&gt; and &lt;code&gt;recorded_with&lt;/code&gt; fields indicate when and with what version of vcrpy the interaction was recorded.&lt;/p&gt;

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

&lt;p&gt;VCR.py is a powerful tool for testing code that interacts with external services. Its ability to record and replay HTTP interactions makes it easy to write tests that are reliable and efficient. With VCR.py, you can customize how interactions are matched and filtered, and work with the cassette file to inspect and modify recorded interactions.&lt;/p&gt;

&lt;p&gt;I hope this article has given you a good introduction to VCR.py and its features. If you're interested in learning more, I encourage you to check out the &lt;a href="https://vcrpy.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and start experimenting with VCR.py in your own tests.&lt;/p&gt;

</description>
      <category>http</category>
      <category>python</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Test-Driven Development in Python: Best Practices, and Detailed Explanation</title>
      <dc:creator>Ahmed Helmi</dc:creator>
      <pubDate>Thu, 29 Jun 2023 15:47:37 +0000</pubDate>
      <link>https://dev.to/00geekinside00/test-driven-development-in-python-best-practices-and-detailed-explanation-42e8</link>
      <guid>https://dev.to/00geekinside00/test-driven-development-in-python-best-practices-and-detailed-explanation-42e8</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%2Fuploads%2Farticles%2Fra31gf600xopk1b7yl09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fra31gf600xopk1b7yl09.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey there, Python lovers! Are you looking for a way to improve your software development process and build more maintainable code? Look no further than test-driven development (TDD) in Python! In this article, we’ll explore the benefits of TDD, best practices for implementing it, and some fun example to get you started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why You Should Give TDD a Try:
&lt;/h2&gt;

&lt;p&gt;TDD can provide a variety of benefits when developing Python applications. By writing tests before writing code, you can catch errors and bugs early, reducing the time and cost required for testing and debugging. This leads to better code quality, faster development time, better collaboration among team members, and improved confidence in your code. Who wouldn’t want those benefits?&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for TDD in Python:
&lt;/h2&gt;

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

&lt;p&gt;The TDD process is often described as “&lt;em&gt;Red-Green-Refactor&lt;/em&gt;”. The “&lt;em&gt;Red&lt;/em&gt;” phase involves writing a test that fails, which means that the code being tested hasn’t been written yet. The “&lt;em&gt;Green&lt;/em&gt;” phase involves writing the minimum amount of code required to pass the test. Once the test passes, the “&lt;em&gt;Refactor&lt;/em&gt;” phase involves improving the code’s design and efficiency without changing its behavior.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Write tests first: This ensures that your code meets the requirements of the project and works as expected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write small and simple tests: Testing one aspect of the code at a time makes it easier to identify and fix errors and bugs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test edge cases: Testing unexpected inputs and outputs ensures that your code can handle anything that comes its way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;a href="https://docs.python.org/3/library/unittest.html" rel="noopener noreferrer"&gt;unittest&lt;/a&gt;: Python’s built-in testing framework is easy to use and helps you write and run tests quickly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run tests frequently: Catch errors and bugs as soon as they are introduced by running tests frequently during development.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tools that maybe handy:
&lt;/h2&gt;

&lt;p&gt;Test Coverage: Test coverage is a metric that measures the percentage of the code that is covered by tests. Achieving high test coverage is important, as it ensures that all parts of the code are thoroughly tested. Python provides several tools, such as &lt;a href="https://coverage.readthedocs.io/en/7.2.7/" rel="noopener noreferrer"&gt;coverage.py&lt;/a&gt;, that can be used to measure test coverage.&lt;/p&gt;

&lt;p&gt;Test Doubles: Test doubles are objects that are used in place of other objects during testing. For example, a mock object can be used to simulate the behavior of a real object. Python provides several libraries, such as &lt;a href="https://docs.python.org/3/library/unittest.mock.html" rel="noopener noreferrer"&gt;unittest.mock&lt;/a&gt;, that can be used to create test doubles.&lt;/p&gt;

&lt;p&gt;Test-Driven Data Analysis (TDDA): Test-driven data analysis is a variant of TDD that is used in data science. TDDA involves writing tests for data cleaning, data preprocessing, and statistical models. By using TDDA, data scientists can ensure that their results are reproducible and that their code is correct.&lt;/p&gt;

&lt;p&gt;HTTP interaction replay: It is like recording and playing back conversations between your Python program and a web server. It’s useful for testing, debugging, and mocking web-based applications. When you use a library like &lt;a href="https://vcrpy.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;VCR.py&lt;/a&gt; it records the HTTP requests and responses, and then plays them back later when you need them.&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD with python in action:
&lt;/h2&gt;

&lt;p&gt;Let’s consider a feature for an e-commerce application where a customer can add a product to their cart. Here’s an example of how you might use TDD to develop this feature in Python:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write a failing test&lt;/strong&gt;: The first step in TDD is to write a test that fails. In this case, we might write a test that checks whether a customer’s cart is updated correctly when they add a product:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def test_add_to_cart():
 customer = Customer()
 product = Product(‘123’, ‘Widget’, 9.99)
 customer.add_to_cart(product)
 assert customer.cart == {‘123’: {‘name’: ‘Widget’, ‘price’: 9.99, ‘quantity’: 1}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run the test&lt;/strong&gt;: When you run the test, it should fail because we haven’t implemented the add_to_cart method yet.&lt;/p&gt;

&lt;p&gt;Write the implementation: Now we can write the implementation code for the add_to_cart method. It might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
class Customer:
    def __init__(self):
        self.cart = {}

    def add_to_cart(self, product):
        if product.id in self.cart:
            self.cart[product.id]['quantity'] += 1
        else:
            self.cart[product.id] = {'name': product.name, 'price': product.price, 'quantity': 1}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run the test again&lt;/strong&gt;: Now that we’ve implemented the add_to_cart method, we can run the test again. This time, it should pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refactor&lt;/strong&gt;: If necessary, we can now refactor our code to make it more efficient, readable, and maintainable. For example, we might extract the cart item creation logic into a separate method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Customer:
    def __init__(self):
        self.cart = {}

    def add_to_cart(self, product):
        if product.id in self.cart:
            self.cart[product.id]['quantity'] += 1
        else:
            self.cart[product.id] = self._create_cart_item(product)

    def _create_cart_item(self, product):
        return {'name': product.name, 'price': product.price, 'quantity': 1}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Repeat&lt;/strong&gt;: We can now continue this cycle of writing failing tests, implementing the code to make them pass, and refactoring as necessary until we’ve fully developed and tested the feature.&lt;/p&gt;

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

&lt;p&gt;In conclusion, test-driven development is a great way to develop Python programs that are reliable, maintainable, and bug-free. By writing test cases before writing the implementation, we can catch errors and bugs early in the development process and avoid costly debugging later on. With practice, you’ll find that TDD becomes an intuitive and efficient way to develop software. &lt;/p&gt;

</description>
      <category>tdd</category>
      <category>python</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
