<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Curl on Nicola Iarocci</title>
    <link>https://nicolaiarocci.com/tags/curl/</link>
    <description>Recent content in Curl on Nicola Iarocci</description>
    <generator>Hugo -- 0.143.1</generator>
    <language>en</language>
    <copyright>Produced / Written / Maintained by Nicola Iarocci since 2010</copyright>
    <lastBuildDate>Fri, 21 Nov 2025 16:57:44 +0100</lastBuildDate>
    <atom:link href="https://nicolaiarocci.com/tags/curl/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Curl and jq go to a conference</title>
      <link>https://nicolaiarocci.com/curl-and-jq-go-to-a-conference/</link>
      <pubDate>Fri, 21 Nov 2025 16:57:44 +0100</pubDate>
      <guid>https://nicolaiarocci.com/curl-and-jq-go-to-a-conference/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m presenting at the &lt;a href=&#34;https://www.wpc.education&#34;&gt;WPC 2025 Conference&lt;/a&gt; on December 3rd in Milan. My session topic is Feature Flag Management and Dynamic Configurations in C#.&lt;/p&gt;
&lt;p&gt;I will use a Web API as an example project, and since I&amp;rsquo;ll be using curl live to query it, I&amp;rsquo;ll need to pipe responses through &lt;a href=&#34;https://jqlang.org&#34;&gt;jq&lt;/a&gt; to obtain nicely formatted JSON for the audience.&lt;/p&gt;
&lt;p&gt;The problem with jq is that it crashes on 400s or 500s because the response body is empty in those cases. Error responses are inherent to the demo, and crashes are not the most desirable thing during a presentation.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;m presenting at the <a href="https://www.wpc.education">WPC 2025 Conference</a> on December 3rd in Milan. My session topic is Feature Flag Management and Dynamic Configurations in C#.</p>
<p>I will use a Web API as an example project, and since I&rsquo;ll be using curl live to query it, I&rsquo;ll need to pipe responses through <a href="https://jqlang.org">jq</a> to obtain nicely formatted JSON for the audience.</p>
<p>The problem with jq is that it crashes on 400s or 500s because the response body is empty in those cases. Error responses are inherent to the demo, and crashes are not the most desirable thing during a presentation.</p>
<p>I cooked up a quick bash function that enhances curl and jq. It is called cj (curl + jq) and prevents crashes on errors, displays HTTP status codes with color-coded output (green for success, red for errors), and prettifies JSON responses.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<p>As I fully expect someone in the audience to raise their hand and ask what the hell &ldquo;cj&rdquo; is, I&rsquo;m posting it for reference so I can point them here if needed (Hi there!).</p>
<p>The function looks like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cj() {
</span></span><span style="display:flex;"><span>    local response http_code body
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    response=<span style="font-weight:bold">$(</span>curl -s -w <span style="font-style:italic">&#34;\n%{http_code}&#34;</span> <span style="font-style:italic">&#34;</span>$@<span style="font-style:italic">&#34;</span><span style="font-weight:bold">)</span>
</span></span><span style="display:flex;"><span>    http_code=<span style="font-weight:bold;font-style:italic">${</span>response##*<span style="font-style:italic">$&#39;\n&#39;</span><span style="font-weight:bold;font-style:italic">}</span>
</span></span><span style="display:flex;"><span>    body=<span style="font-weight:bold;font-style:italic">${</span>response%<span style="font-style:italic">$&#39;\n&#39;</span>*<span style="font-weight:bold;font-style:italic">}</span>
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> [[ $http_code =~ ^2[0-9][0-9]$ ]]; <span style="font-weight:bold">then</span>
</span></span><span style="display:flex;"><span>        echo -e <span style="font-style:italic">&#34;\033[0;32mHTTP Code: </span>$http_code<span style="font-style:italic">\033[0m&#34;</span>
</span></span><span style="display:flex;"><span>        echo <span style="font-style:italic">&#34;</span>$body<span style="font-style:italic">&#34;</span> | jq 2&gt;/dev/null || echo <span style="font-style:italic">&#34;</span>$body<span style="font-style:italic">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>
</span></span><span style="display:flex;"><span>        echo -e <span style="font-style:italic">&#34;\033[0;31mHTTP Code: </span>$http_code<span style="font-style:italic">\033[0m&#34;</span>
</span></span><span style="display:flex;"><span>        echo -e <span style="font-style:italic">&#34;\033[0;31m</span>$body<span style="font-style:italic">\033[0m&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">fi</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It currently sits at the bottom of my .zshrc file. I might turn it into a script in the future, but it&rsquo;s probably going to be short-lived, so I&rsquo;m happy with its current residence.</p>
<p>It&rsquo;s pretty straightforward, but let&rsquo;s break it down line by line.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cj() {
</span></span></code></pre></div><p>Defines a function named cj (short for &ldquo;curl with jq&rdquo;), which will wrap the standard curl command with automatic JSON formatting and colored output.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>local response http_code body
</span></span></code></pre></div><p>Declares three local variables scoped to this function: <code>response</code> will store the full curl output, <code>http_code</code> will contain the HTTP status code, and <code>body</code> will hold the response body.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>response=<span style="font-weight:bold">$(</span>curl -s -w <span style="font-style:italic">&#34;\n%{http_code}&#34;</span> <span style="font-style:italic">&#34;</span>$@<span style="font-style:italic">&#34;</span><span style="font-weight:bold">)</span>
</span></span></code></pre></div><p>Executes curl with the <code>-s</code> flag for silent mode (no progress bar), <code>-w &quot;\n%{http_code}&quot;</code> to append a newline and the HTTP status code at the end of the output, and <code>&quot;$@&quot;</code> to forward all arguments passed to the function. The entire output is captured in the response variable.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>http_code=<span style="font-weight:bold;font-style:italic">${</span>response##*<span style="font-style:italic">$&#39;\n&#39;</span><span style="font-weight:bold;font-style:italic">}</span>
</span></span></code></pre></div><p>Extracts the HTTP status code using Bash parameter expansion. The <code>##*$'\n'</code> pattern removes everything up to and including the last newline, leaving only the status code. This is faster than using external commands like tail.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>body=<span style="font-weight:bold;font-style:italic">${</span>response%<span style="font-style:italic">$&#39;\n&#39;</span>*<span style="font-weight:bold;font-style:italic">}</span>
</span></span></code></pre></div><p>Extracts the response body using parameter expansion. The <code>%$'\n'*</code> pattern removes the last newline and everything after it (the status code), leaving only the body content. This is more efficient than using, say, sed.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="font-weight:bold">if</span> [[ $http_code =~ ^2[0-9][0-9]$ ]]; <span style="font-weight:bold">then</span>
</span></span></code></pre></div><p>Checks if the HTTP status code matches the pattern for success responses (2xx). The regex <code>^2[0-9][0-9]$</code> matches any three-digit number starting with 2.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo -e <span style="font-style:italic">&#34;\033[0;32mHTTP Code: </span>$http_code<span style="font-style:italic">\033[0m&#34;</span>
</span></span></code></pre></div><p>Prints the HTTP status code in green color. The <code>-e</code> flag enables interpretation of backslash escapes, <code>\033[0;32m</code> is the ANSI code for green text, and <code>\033[0m</code> resets the color back to default.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="font-style:italic">&#34;</span>$body<span style="font-style:italic">&#34;</span> | jq 2&gt;/dev/null || echo <span style="font-style:italic">&#34;</span>$body<span style="font-style:italic">&#34;</span>
</span></span></code></pre></div><p>This one was fun. Attempts to format the response body as JSON using jq. If jq is not installed or the body isn&rsquo;t valid JSON, stderr is redirected to <code>/dev/null</code> and the <code>||</code> operator triggers the fallback, which simply prints the raw body.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="font-weight:bold">else</span>
</span></span><span style="display:flex;"><span>        echo -e <span style="font-style:italic">&#34;\033[0;31mHTTP Code: </span>$http_code<span style="font-style:italic">\033[0m&#34;</span>
</span></span></code></pre></div><p>For non-2xx responses (errors), prints the HTTP status code in red color using the ANSI code <code>\033[0;31m</code>.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo -e <span style="font-style:italic">&#34;\033[0;31m</span>$body<span style="font-style:italic">\033[0m&#34;</span>
</span></span></code></pre></div><p>Prints the error response body also in red color, making errors immediately visible during the demo.</p>
<p>And that is all.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>I could of course update the API to return valid JSON even on errors, but that&rsquo;s boring.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
