<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Haim Gelfenbeyn's Blog</title><link>https://haim.dev/posts/</link><description>Recent content in Posts on Haim Gelfenbeyn's Blog</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 02 Apr 2023 09:21:39 -0400</lastBuildDate><atom:link href="https://haim.dev/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Duplicating HTTP status in the response body is an anti-pattern</title><link>https://haim.dev/posts/2023-04-02-duplicating-http-status-in-response-body-is-an-antipattern/</link><pubDate>Sun, 02 Apr 2023 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2023-04-02-duplicating-http-status-in-response-body-is-an-antipattern/</guid><description>&lt;p&gt;In this blog post, I discuss the use of HTTP response status codes and the potential issues with duplicating them in the response body, as well as how RFC7807 provides a solution for conveying application-specific errors.&lt;/p&gt;
&lt;p&gt;Sometimes, I see APIs where the error response looks like this (HTTP header and body):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-http" data-lang="http"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt; &lt;span class="ne"&gt;Bad Request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Content-Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="l"&gt;application/json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Foo is blank&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"&gt;HTTP response status code&lt;/a&gt; is duplicated in the body of the response. There are different reasons why people think this is a good idea:&lt;/p&gt;</description></item><item><title>Programming in Go is surprisingly productive</title><link>https://haim.dev/posts/2022-10-07-golang-is-surprisingly-effective/</link><pubDate>Fri, 07 Oct 2022 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2022-10-07-golang-is-surprisingly-effective/</guid><description>&lt;p&gt;In my work life I&amp;rsquo;m involved with projects in Ruby, Python, Swift, Rust, Javascript, Typescript. I don&amp;rsquo;t have strong
programming language preferences and believe in the &amp;ldquo;right tool for the job&amp;rdquo; approach: the language should be a good
fit for a problem domain, team expertise, time/budget constrains, etc. Rust is my go-to language when high-performance,
strong type safety, rich ecosystem, compiled language is required.&lt;/p&gt;
&lt;p&gt;Go is often suggested in similar circumstances, and I&amp;rsquo;ve read a couple Go books, but I could
never understand why someone would prefer Go to Rust: Rust is much safer, much richer language; Rust&amp;rsquo;s strict and pedantic
compile-time checks help avoid whole classes of bugs that could bite you in Go. Even when the features are quite similar
(error checking), Rust approach (&lt;code&gt;?&lt;/code&gt; operator) is elegant and makes the code so much easier to read.&lt;/p&gt;</description></item><item><title>Run-once Kubernetes DaemonSet pods</title><link>https://haim.dev/posts/2022-01-01-run-once-kubernetes-daemonset-pods/</link><pubDate>Sat, 01 Jan 2022 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2022-01-01-run-once-kubernetes-daemonset-pods/</guid><description>&lt;p&gt;Sometimes there&amp;rsquo;s a need to run some code just &lt;em&gt;once&lt;/em&gt;, but on each node in your Kubernetes cluster: collecting some
immutable node information is a prime use case. For example, for my &lt;a href="https://github.com/haimgel/do-floating-ip-k8s"&gt;Floating IP controller&lt;/a&gt;
I need to collect the Anchor IP address on every node. See &lt;a href="https://haim.dev/posts/2021-12-30-floating-ip-on-digital-ocean-k8s/"&gt;my previous post&lt;/a&gt;
for context.&lt;/p&gt;
&lt;p&gt;Kubernetes does not support this out-of-the box: &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#pod-template"&gt;DaemonSet supports&lt;/a&gt;
only &lt;code&gt;RestartPolicy&lt;/code&gt; of &lt;code&gt;Always&lt;/code&gt;, so any pod that stops will be started immediately again. There are workarounds
documented only, but they all rotate around the idea of having something &lt;em&gt;lightweight&lt;/em&gt; running all the time on the node,
to satisfy Kubernetes restart policy. This strikes me as &lt;em&gt;inelegant&lt;/em&gt;.&lt;/p&gt;</description></item><item><title>Integrating DigitalOcean floating IPs with Kubernetes</title><link>https://haim.dev/posts/2021-12-30-floating-ip-on-digital-ocean-k8s/</link><pubDate>Thu, 30 Dec 2021 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2021-12-30-floating-ip-on-digital-ocean-k8s/</guid><description>&lt;h2 id="the-problem"&gt;The problem&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.digitalocean.com/products/kubernetes/"&gt;DigitalOcean&lt;/a&gt; Kubernetes platform is great. Its Load Balancer
is well-integrated and works great, too, &lt;em&gt;unless&lt;/em&gt; you need to expose UDP services in your cluster: UDP load balancing
is not supported! So it&amp;rsquo;s not possible to load-balance DNS, HTTP/3 or any other UDP service.&lt;/p&gt;
&lt;h2 id="how-are-we-going-to-solve-this"&gt;How are we going to solve this?&lt;/h2&gt;
&lt;p&gt;DigitalOcean supports &lt;a href="https://docs.digitalocean.com/products/networking/floating-ips/"&gt;floating IPs&lt;/a&gt;:
publicly-accessible static IP addresses that you can assign to Droplets and instantly remap between other Droplets
in the same datacenter.&lt;/p&gt;</description></item><item><title>Redundant first-hop router with Raspberry Pi</title><link>https://haim.dev/posts/2020-12-30-redundand-first-hop-router/</link><pubDate>Wed, 30 Dec 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-12-30-redundand-first-hop-router/</guid><description>&lt;p&gt;In my house, I&amp;rsquo;m using a general-purpose Linux machine as router. This is a much more flexible setup than using a
dedicated device, it provides numerous benefits comparing to using a dedicated router, but it did pose a unique
challenge: my router is actually a VM, not a physical machine: the host&amp;rsquo;s LAN carries multiple VLANs and the
router/firewall VM just passes traffic between them.&lt;/p&gt;
&lt;p&gt;This works great, but introduces multiple additional points of failure, comparing to a dedicated hardware router,
the VM host being the biggest one. It needs to be updated/patched from time to time, and I didn&amp;rsquo;t want to end up without
Internet/DNS/DHCP at that time. And here comes the idea of using a Raspberry Pi as a &amp;ldquo;backup&amp;rdquo; router when my main one
is down for whatever reason.&lt;/p&gt;</description></item><item><title>Linking Swift code into a Rust app</title><link>https://haim.dev/posts/2020-09-10-linking-swift-code-into-rust-app/</link><pubDate>Thu, 10 Sep 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-09-10-linking-swift-code-into-rust-app/</guid><description>&lt;h2 id="why-would-you-want-to-do-that"&gt;Why would you want to do that?&lt;/h2&gt;
&lt;p&gt;I initially wrote my &amp;ldquo;KVM replacement&amp;rdquo; &lt;a href="https://haim.dev/posts/2020-07-28-dual-monitor-kvm/"&gt;display-switch&lt;/a&gt; application twice, in Rust
and Swift. The primary reason was that there is no MacOS-compatible DDC/CI control library for Rust. However, as the
app became somewhat popular, and I wanted to add new features and improvements, I realized that this is not sustainable:
I would have to implement every new feature twice.&lt;/p&gt;
&lt;p&gt;So I thought: what if I extract only the MacOS-compatible DDC control Swift code as a separate library, and statically
link it into the main Rust application?&lt;/p&gt;</description></item><item><title>Signing and notarizing a Python MacOS UI application</title><link>https://haim.dev/posts/2020-08-08-python-macos-app/</link><pubDate>Sat, 08 Aug 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-08-08-python-macos-app/</guid><description>&lt;h1 id="why-write-a-macos-application-in-python"&gt;Why write a MacOS application in Python?&lt;/h1&gt;
&lt;p&gt;Python has an amazingly rich ecosystem of libraries, tools and frameworks. It is a clean, modern language, it allows
for rapid prototyping and quick development cycles. UI was not the central, focal point of my app, so it made a lot
of sense for me to do it in Python: I thought I&amp;rsquo;d write the core functionality first, and add the UI afterwards.&lt;/p&gt;</description></item><item><title>Dual-monitor 4K@60hz KVM switch for $30</title><link>https://haim.dev/posts/2020-07-28-dual-monitor-kvm/</link><pubDate>Tue, 28 Jul 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-07-28-dual-monitor-kvm/</guid><description>&lt;h1 id="the-need-for-kvm"&gt;The need for KVM&lt;/h1&gt;
&lt;p&gt;I like my two big hi-res monitors. I love my keyboard and my mouse. And I connect them to my stationary
&amp;ldquo;main&amp;rdquo; PC and to several other Windows and Mac laptops, alternatively. I&amp;rsquo;d like to easily switch where these peripheral
devices are connected to, and that&amp;rsquo;s the traditional role of a &lt;a href="https://en.wikipedia.org/wiki/KVM_switch"&gt;KVM switch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately for me, KVM switches that support 4K/60hz resolutions cost hundreds of dollars, there are
no KVM switches that support USB-C, and I couldn&amp;rsquo;t find KVM switches that support multiple high-res monitors
either.&lt;/p&gt;</description></item><item><title>Fresh air with ESP8266 and Home Assistant (part 2)</title><link>https://haim.dev/posts/2020-04-26-hrv-with-esp8266-2/</link><pubDate>Sun, 26 Apr 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-04-26-hrv-with-esp8266-2/</guid><description>&lt;p&gt;This is the second post about hooking up Heat Recovery Ventilator to Home Assistant. Previously, I wrote about
&lt;a href="https://haim.dev/posts/2020-04-25-hrv-with-esp8266-1/"&gt;the hardware aspect&lt;/a&gt; and here I&amp;rsquo;ll discuss the software that is needed to
make it all work.&lt;/p&gt;
&lt;h2 id="esp8266-firmware"&gt;ESP8266 Firmware&lt;/h2&gt;
&lt;p&gt;There are several IoT frameworks available for ESP8266. I&amp;rsquo;ve decided to build my solution on top of &lt;a href="http://homieiot.github.io/homie-esp8266/"&gt;Homie for ESP8266&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Homie is a thin and simple MQTT convention for the IoT, it integrates very well with Home Assistant and supports
advanced features like initial setup of devices and OTA firmware updates. Homie implementation for ESP8266 is well-designed
and is a pleasure to work with.&lt;/p&gt;</description></item><item><title>Fresh air with ESP8266 and Home Assistant (part 1)</title><link>https://haim.dev/posts/2020-04-25-hrv-with-esp8266-1/</link><pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-04-25-hrv-with-esp8266-1/</guid><description>&lt;p&gt;This is the first post in a series about how I implemented MQTT controller for a Heat Recovery Ventilator (HRV) in my
house, and hooked it up to my home automation system.&lt;/p&gt;
&lt;h2 id="what-is-hrv"&gt;What is HRV?&lt;/h2&gt;
&lt;p&gt;Our house is quite new, and therefore pretty well sealed. In order to maintain a healthy interior climate and not lose
too much energy in a cold Canadian climate, we have a &lt;a href="https://en.wikipedia.org/wiki/Heat_recovery_ventilation"&gt;Heat Recovery Ventilator system&lt;/a&gt;,
which is a system that brings in fresh outdoor air and heats (or cools) it with an interior air it exhausts, thus
reducing energy costs.&lt;/p&gt;</description></item><item><title>Automating "lunch" Slack status</title><link>https://haim.dev/posts/2020-04-18-slack-status/</link><pubDate>Sat, 18 Apr 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-04-18-slack-status/</guid><description>&lt;h2 id="why"&gt;Why?&lt;/h2&gt;
&lt;p&gt;My work is 100% remote, I work from home most of the time. Although I usually have a stable schedule and try to have
meals at the same time every day, sometimes meetings get into way, and I eat earlier or later than usual. To let my
co-workers know that I&amp;rsquo;m currently away, I prefer to set a Slack status (and do not send messages saying
&amp;ldquo;going to lunch&amp;rdquo; and &amp;ldquo;back&amp;rdquo;).&lt;/p&gt;</description></item><item><title>Wall-mounted Dashboards (part 3)</title><link>https://haim.dev/posts/2020-04-13-wall-tablet-3/</link><pubDate>Mon, 13 Apr 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-04-13-wall-tablet-3/</guid><description>&lt;p&gt;This is the third article in a &lt;a href="https://haim.dev/series/wall-mounted-home-automation-dashboards/"&gt;series about my DIY approach to wall-mounted home automation dashboards&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="choosing-the-dashboard-platform"&gt;Choosing the dashboard platform&lt;/h2&gt;
&lt;p&gt;The &amp;ldquo;heart&amp;rdquo; of my home automation system is &lt;a href="https://www.home-assistant.io/"&gt;Home Assistant&lt;/a&gt;, an open source home
automation platform written in Python. Its built-in web frontend is suitable for a dashboard, &lt;em&gt;but only if the only
thing you want to control is Home Assistant&lt;/em&gt;. I knew from the start that there were going to be several custom
components in my dashboard, so my primary requirement was ease of development and personal familiarity.&lt;/p&gt;</description></item><item><title>Wall-mounted Dashboards (part 2)</title><link>https://haim.dev/posts/2020-03-14-wall-tablet-2/</link><pubDate>Sat, 14 Mar 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-03-14-wall-tablet-2/</guid><description>&lt;p&gt;This is the second article in a &lt;a href="https://haim.dev/series/wall-mounted-home-automation-dashboards/"&gt;series of articles&lt;/a&gt; about my DIY
approach to wall-mounted home automation dashboards. See &lt;a href="https://haim.dev/posts/2020-03-07-wall-tablet-1"&gt;the first part&lt;/a&gt; for
initial planning, hardware, mounting and power supplies.&lt;/p&gt;
&lt;h2 id="a-big-disappointment"&gt;A big disappointment&lt;/h2&gt;
&lt;p&gt;My initial idea was to build an intercom system with these tablets. This turned out to be a bad idea, for two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tablet&amp;rsquo;s microphone and speaker quality&lt;/strong&gt;: They were pretty bad! I did some initial testing with various open-source
Android softphones, and you had to stand pretty close to the tablet for the mike to pick up anything reliably, and the
speakers were pretty weak! The fact that they are on the back of the tablet, facing the wall, didn&amp;rsquo;t help at all.&lt;/p&gt;</description></item><item><title>Wall-mounted Dashboards (part 1)</title><link>https://haim.dev/posts/2020-03-07-wall-tablet-1/</link><pubDate>Sat, 07 Mar 2020 00:00:00 +0000</pubDate><guid>https://haim.dev/posts/2020-03-07-wall-tablet-1/</guid><description>&lt;p&gt;This is the first article in a series of articles about my DIY approach to wall-mounted home automation dashboards.
This is a bit old news for us, as I completed this project 2 years ago. I didn&amp;rsquo;t want to write about it immediately
after completion, I wasn&amp;rsquo;t sure how reliable the whole system is. However, today, two years later, it&amp;rsquo;s still 100%
operational, so it&amp;rsquo;s time!&lt;/p&gt;
&lt;h2 id="the-objective"&gt;The objective&lt;/h2&gt;
&lt;p&gt;After we moved to a new house, I mentioned in passing to my wife that I would like to be able to control the various
aspects of our house from a wall-mounted touch panel. To my surprise, this idea was well-received, and in fact the
scope of the project become much larger than I initially planned. So we wanted:&lt;/p&gt;</description></item></channel></rss>