<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://rafallorenz.com/feed.xml" rel="self" type="application/atom+xml" /><link href="http://rafallorenz.com/" rel="alternate" type="text/html" /><updated>2026-08-01T10:02:46+00:00</updated><id>http://rafallorenz.com/feed.xml</id><title type="html">Rafał Lorenz</title><subtitle>Software Engineer</subtitle><entry><title type="html">How to customize Go’s HTTP client</title><link href="http://rafallorenz.com/go/customize-http-client/" rel="alternate" type="text/html" title="How to customize Go’s HTTP client" /><published>2020-10-15T00:00:00+00:00</published><updated>2020-10-15T00:00:00+00:00</updated><id>http://rafallorenz.com/go/customize-http-client</id><content type="html" xml:base="http://rafallorenz.com/go/customize-http-client/"><![CDATA[<p>In this article we are going to learn how to build extendable HTTP client for our application while working with multiple external APIs. We will take advantage of <a href="https://golang.org/pkg/net/http/#Client">http.Client</a> and <a href="https://golang.org/pkg/net/http/#RoundTripper">http.RoundTripper</a>. For the purpose of this article lets assume we are going to work with only two different external APIs. Our HTTP client should let us:</p>

<ol>
  <li>allow us to handle HTTP errors using our application error types</li>
  <li>allow to extend the logic with custom addons per each API</li>
</ol>

<h1 id="custom-http-client">Custom HTTP client</h1>

<p>To take a full advantage of Go native libraries while tweaking it to our needs lets define our <code class="language-plaintext highlighter-rouge">Client</code> type as follow:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Options</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">ApiURL</span>          <span class="kt">string</span>
	<span class="n">Verbose</span>         <span class="kt">bool</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">Client</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">httpClient</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Client</span>
	<span class="n">options</span>    <span class="o">*</span><span class="n">Options</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">New</span><span class="p">(</span><span class="n">httpClient</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Client</span><span class="p">,</span> <span class="n">options</span> <span class="n">Options</span><span class="p">)</span> <span class="o">*</span><span class="n">Client</span> <span class="p">{</span>
	<span class="k">return</span> <span class="o">&amp;</span><span class="n">Client</span><span class="p">{</span>
		<span class="n">httpClient</span><span class="o">:</span> <span class="n">httpClient</span><span class="p">,</span>
		<span class="n">options</span><span class="o">:</span>    <span class="o">&amp;</span><span class="n">options</span><span class="p">,</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Doing so we can reuse our <code class="language-plaintext highlighter-rouge">Client</code> type for multiple external APIs by providing different options which holds <code class="language-plaintext highlighter-rouge">ApiURL</code> value and other configuration parameters. On top of that <code class="language-plaintext highlighter-rouge">Options</code> itself can be extended to hold much more complex configuration as needed. Depending on your use case you might want to add more.</p>

<p>We want our client to conform to the following interface:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">HTTPClient</span> <span class="k">interface</span> <span class="p">{</span>
	<span class="n">Get</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">path</span> <span class="kt">string</span><span class="p">,</span> <span class="n">v</span> <span class="k">interface</span><span class="p">{})</span> <span class="kt">error</span>
	<span class="n">Post</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">path</span> <span class="kt">string</span><span class="p">,</span> <span class="n">payload</span> <span class="k">interface</span><span class="p">{},</span> <span class="n">v</span> <span class="k">interface</span><span class="p">{})</span> <span class="kt">error</span>
	<span class="n">Put</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">path</span> <span class="kt">string</span><span class="p">,</span> <span class="n">payload</span> <span class="k">interface</span><span class="p">{},</span> <span class="n">v</span> <span class="k">interface</span><span class="p">{})</span> <span class="kt">error</span>
	<span class="n">Delete</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">path</span> <span class="kt">string</span><span class="p">,</span> <span class="n">payload</span> <span class="k">interface</span><span class="p">{},</span> <span class="n">v</span> <span class="k">interface</span><span class="p">{})</span> <span class="kt">error</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As you can probably notice we want to be able to pass <code class="language-plaintext highlighter-rouge">path</code> with optional <code class="language-plaintext highlighter-rouge">payload</code> and <code class="language-plaintext highlighter-rouge">v</code> objects into which response body should be parsed. This will allow us to implement quickly API calls that are specific for our service, without unnecessary duplications. To keep this post short I am going to implement one method:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">c</span> <span class="o">*</span><span class="n">Client</span><span class="p">)</span> <span class="n">Get</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">path</span> <span class="kt">string</span><span class="p">,</span> <span class="n">v</span> <span class="k">interface</span><span class="p">{})</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="n">req</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">c</span><span class="o">.</span><span class="n">newRequest</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">MethodGet</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="no">nil</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to create GET request: %w"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">if</span> <span class="n">_</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">c</span><span class="o">.</span><span class="n">doRequest</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">v</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">err</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Other methods should look very similar, with a small change of a HTTP method used. Internal implementation of our client is divided into two parts:</p>

<ul>
  <li>new request</li>
  <li>do request</li>
</ul>

<p>Notice that <code class="language-plaintext highlighter-rouge">GET</code> method has no payload therefore last value passed to <code class="language-plaintext highlighter-rouge">newRequest</code> is nil.</p>

<p>Example usage of client methods by our service would look something like this:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">s</span> <span class="o">*</span><span class="n">Service</span><span class="p">)</span> <span class="n">CreateUser</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">u</span> <span class="n">User</span><span class="p">)</span> <span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">var</span> <span class="n">user</span> <span class="n">User</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">s</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Post</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="s">"/users"</span><span class="p">,</span> <span class="n">u</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">user</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">user</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to create user %+v: %w"</span><span class="p">,</span> <span class="n">u</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">user</span><span class="p">,</span> <span class="no">nil</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">s</span> <span class="o">*</span><span class="n">Service</span><span class="p">)</span> <span class="n">GetUser</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">id</span> <span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">var</span> <span class="n">user</span> <span class="n">User</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">s</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Get</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"/users/%s"</span><span class="p">,</span> <span class="n">id</span><span class="p">),</span> <span class="o">&amp;</span><span class="n">user</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">user</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to get user %s: %w"</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">user</span><span class="p">,</span> <span class="no">nil</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">s</span> <span class="o">*</span><span class="n">Service</span><span class="p">)</span> <span class="n">DeleteUser</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">id</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">s</span><span class="o">.</span><span class="n">client</span><span class="o">.</span><span class="n">Delete</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"/users/%s"</span><span class="p">,</span> <span class="n">id</span><span class="p">),</span> <span class="no">nil</span><span class="p">,</span> <span class="no">nil</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to delete user %s: %w"</span><span class="p">,</span> <span class="n">id</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="new-request">New request</h2>

<p>Implementation of this method is trivial, we need to simply create new HTTP request using <a href="https://golang.org/pkg/net/http/#NewRequest">http.NewRequest</a> with body if payload is provided.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">c</span> <span class="o">*</span><span class="n">Client</span><span class="p">)</span> <span class="n">newRequest</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">path</span> <span class="kt">string</span><span class="p">,</span> <span class="n">payload</span> <span class="k">interface</span><span class="p">{})</span> <span class="p">(</span><span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">var</span> <span class="n">reqBody</span> <span class="n">io</span><span class="o">.</span><span class="n">Reader</span>
<span class="k">if</span> <span class="n">payload</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
	<span class="n">bodyBytes</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">json</span><span class="o">.</span><span class="n">Marshal</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="no">nil</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to marshal request body: %w"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="n">reqBody</span> <span class="o">=</span> <span class="n">bytes</span><span class="o">.</span><span class="n">NewReader</span><span class="p">(</span><span class="n">bodyBytes</span><span class="p">)</span>
<span class="p">}</span>

<span class="n">req</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">NewRequest</span><span class="p">(</span><span class="n">method</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s%s"</span><span class="p">,</span> <span class="n">c</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">ApiURL</span><span class="p">,</span> <span class="n">path</span><span class="p">),</span> <span class="n">reqBody</span><span class="p">)</span>
<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
	<span class="k">return</span> <span class="no">nil</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to create HTTP request: %w"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">if</span> <span class="n">c</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">Verbose</span> <span class="p">{</span>
	<span class="n">body</span><span class="p">,</span> <span class="n">_</span> <span class="o">:=</span> <span class="n">httputil</span><span class="o">.</span><span class="n">DumpRequest</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="no">true</span><span class="p">)</span>
	<span class="n">log</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s"</span><span class="p">,</span> <span class="kt">string</span><span class="p">(</span><span class="n">body</span><span class="p">)))</span>
<span class="p">}</span>

<span class="n">req</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="n">WithContext</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
<span class="k">return</span> <span class="n">req</span><span class="p">,</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p>At this stage we also set request’s context to given one, context will be responsible for timeouts etc.</p>

<h2 id="do-request">Do request</h2>

<p>To keep our logic simple and readable in this stage lets handle response parsing and defer request processing deeper. We could also at this stage add here retry on error logic, before we parse response body.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">c</span> <span class="o">*</span><span class="n">Client</span><span class="p">)</span> <span class="n">doRequest</span><span class="p">(</span><span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">,</span> <span class="n">v</span> <span class="k">interface</span><span class="p">{})</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="n">resp</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">c</span><span class="o">.</span><span class="n">do</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">err</span>
	<span class="p">}</span>

	<span class="k">if</span> <span class="n">resp</span> <span class="o">==</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="no">nil</span>
	<span class="p">}</span>
	<span class="k">defer</span> <span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>

	<span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="no">nil</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="n">buf</span> <span class="n">bytes</span><span class="o">.</span><span class="n">Buffer</span>
	<span class="n">dec</span> <span class="o">:=</span> <span class="n">json</span><span class="o">.</span><span class="n">NewDecoder</span><span class="p">(</span><span class="n">io</span><span class="o">.</span><span class="n">TeeReader</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">buf</span><span class="p">))</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">dec</span><span class="o">.</span><span class="n">Decode</span><span class="p">(</span><span class="n">v</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"could not parse response body: %w [%s:%s] %s"</span><span class="p">,</span> <span class="n">err</span><span class="p">,</span> <span class="n">r</span><span class="o">.</span><span class="n">Method</span><span class="p">,</span> <span class="n">r</span><span class="o">.</span><span class="n">URL</span><span class="o">.</span><span class="n">String</span><span class="p">(),</span> <span class="n">buf</span><span class="o">.</span><span class="n">String</span><span class="p">())</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="handling-errors">Handling errors</h1>

<p>Most of the time, every application has defined its own error types, something like <code class="language-plaintext highlighter-rouge">ErrNotFound</code> or <code class="language-plaintext highlighter-rouge">ErrUserAccessDenied</code>. This allows us to leverage <a href="https://golang.org/pkg/errors/#Is">errors.Is</a> method and apply custom behavior in an easy resilient way while handling them. We already have our client type, lets implement logic to do request and return proper application error.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="p">(</span>
	<span class="n">ErrUserAccessDenied</span>  <span class="o">=</span> <span class="n">errors</span><span class="o">.</span><span class="n">New</span><span class="p">(</span><span class="s">"you do not have access to the requested resource"</span><span class="p">)</span>
	<span class="n">ErrNotFound</span>          <span class="o">=</span> <span class="n">errors</span><span class="o">.</span><span class="n">New</span><span class="p">(</span><span class="s">"the requested resource not found"</span><span class="p">)</span>
	<span class="n">ErrTooManyRequests</span>   <span class="o">=</span> <span class="n">errors</span><span class="o">.</span><span class="n">New</span><span class="p">(</span><span class="s">"you have exceeded throttle"</span><span class="p">)</span>
<span class="p">)</span>

<span class="k">func</span> <span class="p">(</span><span class="n">c</span> <span class="o">*</span><span class="n">Client</span><span class="p">)</span> <span class="n">do</span><span class="p">(</span><span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Response</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">resp</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">c</span><span class="o">.</span><span class="n">httpClient</span><span class="o">.</span><span class="n">Do</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="no">nil</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to make request [%s:%s]: %w"</span><span class="p">,</span> <span class="n">r</span><span class="o">.</span><span class="n">Method</span><span class="p">,</span> <span class="n">r</span><span class="o">.</span><span class="n">URL</span><span class="o">.</span><span class="n">String</span><span class="p">(),</span> <span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">if</span> <span class="n">c</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">Verbose</span> <span class="p">{</span>
		<span class="n">body</span><span class="p">,</span> <span class="n">_</span> <span class="o">:=</span> <span class="n">httputil</span><span class="o">.</span><span class="n">DumpResponse</span><span class="p">(</span><span class="n">resp</span><span class="p">,</span> <span class="no">true</span><span class="p">)</span>
		<span class="n">log</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s"</span><span class="p">,</span> <span class="kt">string</span><span class="p">(</span><span class="n">body</span><span class="p">)))</span>
	<span class="p">}</span>

	<span class="k">switch</span> <span class="n">resp</span><span class="o">.</span><span class="n">StatusCode</span> <span class="p">{</span>
	<span class="k">case</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusOK</span><span class="p">,</span>
		<span class="n">http</span><span class="o">.</span><span class="n">StatusCreated</span><span class="p">,</span>
		<span class="n">http</span><span class="o">.</span><span class="n">StatusNoContent</span><span class="o">:</span>
		<span class="k">return</span> <span class="n">resp</span><span class="p">,</span> <span class="no">nil</span>
	<span class="p">}</span>

	<span class="k">defer</span> <span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>

	<span class="k">switch</span> <span class="n">resp</span><span class="o">.</span><span class="n">StatusCode</span> <span class="p">{</span>
	<span class="k">case</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusNotFound</span><span class="o">:</span>
		<span class="k">return</span> <span class="n">ErrNotFound</span>
	<span class="k">case</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusUnauthorized</span><span class="p">,</span>
		<span class="n">http</span><span class="o">.</span><span class="n">StatusForbidden</span><span class="o">:</span>
		<span class="k">return</span> <span class="n">ErrUserAccessDenied</span>
	<span class="k">case</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusTooManyRequests</span><span class="o">:</span>
		<span class="k">return</span> <span class="n">ErrTooManyRequests</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="no">nil</span><span class="p">,</span> <span class="n">fmr</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"failed to do request, %d status code received"</span><span class="p">,</span> <span class="n">resp</span><span class="o">.</span><span class="n">StatusCode</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>My method for the purpose of the example handles only couple of request status codes, but your implementation can handle much more, or maybe even you could introduce <code class="language-plaintext highlighter-rouge">RequestError</code> error type, which can hold information such as <strong>request path, method, response status code</strong> and maybe even <strong>body</strong>.</p>

<h1 id="usage">Usage</h1>

<p>Now since we have our client implemented lets use it, at the very beginning we have said that we are going to work with two different external APIs. Each of them can have different/custom logic for authorization, rate limit handling etc.</p>

<p>Lets begin with service <strong>A</strong>, for the purpose of our example this service will provide as with an <em>API key</em> which we have to use to call their API. This key needs to be inserted in a custom header <code class="language-plaintext highlighter-rouge">X-AUTH-API-KEY</code>.
To add custom (service specific logic) to our HTTP client we will use custom transport implementing (<a href="https://golang.org/pkg/net/http/#RoundTripper">http.RoundTripper</a> interface.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="p">(</span>
	<span class="n">apiVersion</span> <span class="o">=</span> <span class="s">"v1"</span>
	<span class="n">baseUrl</span>    <span class="o">=</span> <span class="s">"https://api.serbvice-a.com"</span>
<span class="p">)</span>

<span class="k">type</span> <span class="n">Service</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">client</span> <span class="o">*</span><span class="n">client</span><span class="o">.</span><span class="n">Client</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">New</span><span class="p">(</span><span class="n">key</span> <span class="kt">string</span><span class="p">)</span> <span class="o">*</span><span class="n">Service</span> <span class="p">{</span>
	<span class="n">t</span> <span class="o">:=</span> <span class="n">transport</span><span class="p">{</span>
		<span class="n">apiKey</span><span class="o">:</span> <span class="n">key</span><span class="p">,</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="o">&amp;</span><span class="n">Service</span><span class="p">{</span>
		<span class="n">client</span><span class="o">:</span> <span class="n">client</span><span class="o">.</span><span class="n">New</span><span class="p">(</span>
			<span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Client</span><span class="p">{</span><span class="n">Transport</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">t</span><span class="p">},</span>
			<span class="n">client</span><span class="o">.</span><span class="n">Options</span><span class="p">{</span>
				<span class="n">ApiURL</span><span class="o">:</span>  <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s/%s"</span><span class="p">,</span> <span class="n">baseUrl</span><span class="p">,</span> <span class="n">apiVersion</span><span class="p">),</span>
				<span class="n">Verbose</span><span class="o">:</span> <span class="n">os</span><span class="o">.</span><span class="n">Getenv</span><span class="p">(</span><span class="s">"VERBOSE"</span><span class="p">)</span> <span class="o">!=</span> <span class="s">""</span><span class="p">,</span>
			<span class="p">},</span>
		<span class="p">),</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">transport</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">apiKey</span>    <span class="kt">string</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">t</span> <span class="o">*</span><span class="n">transport</span><span class="p">)</span> <span class="n">RoundTrip</span><span class="p">(</span><span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Response</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">r</span> <span class="o">:=</span> <span class="n">req</span><span class="o">.</span><span class="n">Clone</span><span class="p">(</span><span class="n">req</span><span class="o">.</span><span class="n">Context</span><span class="p">())</span>
	<span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"Content-Type"</span><span class="p">,</span> <span class="s">"application/json"</span><span class="p">)</span>
	<span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"Accept"</span><span class="p">,</span> <span class="s">"application/json"</span><span class="p">)</span>
	<span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"Accept-Charset"</span><span class="p">,</span> <span class="s">"UTF-8"</span><span class="p">)</span>

	<span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"X-AUTH-API-KEY"</span><span class="p">,</span> <span class="n">t</span><span class="o">.</span><span class="n">apiKey</span><span class="p">)</span>

	<span class="k">return</span> <span class="n">http</span><span class="o">.</span><span class="n">DefaultTransport</span><span class="o">.</span><span class="n">RoundTrip</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Service <strong>B</strong> could for example be using <code class="language-plaintext highlighter-rouge">oauth2</code> protocol for an authentication, in this case our implementation could look as follow:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="p">(</span>
	<span class="n">apiVersion</span> <span class="o">=</span> <span class="s">"v1"</span>
	<span class="n">baseUrl</span>    <span class="o">=</span> <span class="s">"https://api.serbvice-b.com"</span>
<span class="p">)</span>

<span class="k">var</span> <span class="p">(</span>
	<span class="n">authConfig</span> <span class="o">=</span> <span class="n">oauth2</span><span class="o">.</span><span class="n">Config</span><span class="p">{</span>
		<span class="n">ClientID</span><span class="o">:</span>     <span class="s">"XXXX-XXXX-XXXX-XXXX"</span><span class="p">,</span>
		<span class="n">ClientSecret</span><span class="o">:</span> <span class="s">"YYYY-YYYY-YYYY-YYYY"</span><span class="p">,</span>
		<span class="n">RedirectURL</span><span class="o">:</span>  <span class="s">"https://api.our-service.com/oauth/callback"</span><span class="p">,</span>
		<span class="n">Scopes</span><span class="o">:</span>       <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"all"</span><span class="p">},</span>
		<span class="n">Endpoint</span><span class="o">:</span> <span class="n">oauth2</span><span class="o">.</span><span class="n">Endpoint</span><span class="p">{</span>
			<span class="n">AuthStyle</span><span class="o">:</span> <span class="n">oauth2</span><span class="o">.</span><span class="n">AuthStyleInParams</span><span class="p">,</span>
			<span class="n">AuthURL</span><span class="o">:</span>   <span class="s">"https://api.serbvice-b.com/oauth/authorize"</span><span class="p">,</span>
			<span class="n">TokenURL</span><span class="o">:</span>  <span class="s">"https://api.serbvice-b.com/oauth/access_token"</span><span class="p">,</span>
		<span class="p">},</span>
	<span class="p">}</span>
<span class="p">)</span>

<span class="k">type</span> <span class="n">Service</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">client</span> <span class="o">*</span><span class="n">client</span><span class="o">.</span><span class="n">Client</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">New</span><span class="p">(</span><span class="n">t</span> <span class="o">*</span><span class="n">Token</span><span class="p">)</span> <span class="o">*</span><span class="n">Service</span> <span class="p">{</span>
	<span class="n">httpClient</span> <span class="o">:=</span> <span class="n">authConfig</span><span class="o">.</span><span class="n">Client</span><span class="p">(</span>
		<span class="n">context</span><span class="o">.</span><span class="n">WithValue</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">(),</span> <span class="n">oauth2</span><span class="o">.</span><span class="n">HTTPClient</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Client</span><span class="p">{</span><span class="n">Transport</span><span class="o">:</span> <span class="o">&amp;</span><span class="n">transport</span><span class="p">{}}),</span>
		<span class="n">t</span><span class="p">,</span>
	<span class="p">)</span>

	<span class="k">return</span> <span class="o">&amp;</span><span class="n">Service</span><span class="p">{</span>
		<span class="n">client</span><span class="o">:</span> <span class="n">client</span><span class="o">.</span><span class="n">New</span><span class="p">(</span>
			<span class="n">httpClient</span><span class="p">,</span>
			<span class="n">client</span><span class="o">.</span><span class="n">Options</span><span class="p">{</span>
				<span class="n">ApiURL</span><span class="o">:</span>  <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s/%s"</span><span class="p">,</span> <span class="n">baseUrl</span><span class="p">,</span> <span class="n">apiVersion</span><span class="p">),</span>
				<span class="n">Verbose</span><span class="o">:</span> <span class="n">os</span><span class="o">.</span><span class="n">Getenv</span><span class="p">(</span><span class="s">"VERBOSE"</span><span class="p">)</span> <span class="o">!=</span> <span class="s">""</span><span class="p">,</span>
			<span class="p">},</span>
		<span class="p">),</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">transport</span> <span class="k">struct</span> <span class="p">{}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">t</span> <span class="o">*</span><span class="n">transport</span><span class="p">)</span> <span class="n">RoundTrip</span><span class="p">(</span><span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Response</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">r</span> <span class="o">:=</span> <span class="n">req</span><span class="o">.</span><span class="n">Clone</span><span class="p">(</span><span class="n">req</span><span class="o">.</span><span class="n">Context</span><span class="p">())</span>
	<span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"Content-Type"</span><span class="p">,</span> <span class="s">"application/json"</span><span class="p">)</span>
	<span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"Accept"</span><span class="p">,</span> <span class="s">"application/json"</span><span class="p">)</span>

	<span class="k">return</span> <span class="n">http</span><span class="o">.</span><span class="n">DefaultTransport</span><span class="o">.</span><span class="n">RoundTrip</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Service <strong>B</strong> custom transport sets headers for content type only, because we are using <em>oauth2</em> HTTP client, they already append token and handle auto-refresh as necessary for us.</p>

<h1 id="conclusion">Conclusion</h1>

<p>We have learned today how to take advantage of Go’s <a href="https://golang.org/pkg/net/http/#Client">http.Client</a> and leverage <a href="https://golang.org/pkg/net/http/#RoundTripper">http.RoundTripper</a> to apply custom logic to our customized HTTP client.</p>

<p>With the help of code snippets presented in this post, I hope you have grasped the idea of how to customize HTTP client and apply custom, service specific logic. If the API provider would return header with a retry delay time would you be able to add rate limit logic? Try to do it yourself, if you need help leave a comment and lets play in Go’s playground.</p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[In this article we are going to learn how to build extendable HTTP client for our application while working with multiple external APIs. We will take advantage of http.Client and http.RoundTripper. For the purpose of this article lets assume we are going to work with only two different external APIs. Our HTTP client should let us:]]></summary></entry><entry><title type="html">How to rate limit HTTP requests</title><link href="http://rafallorenz.com/go/http-rate-limiter/" rel="alternate" type="text/html" title="How to rate limit HTTP requests" /><published>2020-06-19T00:00:00+00:00</published><updated>2020-06-19T00:00:00+00:00</updated><id>http://rafallorenz.com/go/http-rate-limiter</id><content type="html" xml:base="http://rafallorenz.com/go/http-rate-limiter/"><![CDATA[<p>In this article we are going to learn how to use <a href="https://en.wikipedia.org/wiki/Rate_limiting">rate limiting</a> middleware to protect our server against <a href="https://en.wikipedia.org/wiki/Denial-of-service_attack">DoS attacks</a>.</p>

<blockquote>
  <p>rate limiting is used to control the rate of requests sent or received by a network interface controller</p>
</blockquote>

<p>We will do few things:</p>

<ol>
  <li>get user IP address from request</li>
  <li>write http middleware for rate limit</li>
  <li>
    <p>expose rate limit information via <a href="https://golang.org/pkg/expvar/">exparv</a></p>

    <p>If you are familiar with my blog, in my previous article: <a href="https://rafallorenz.com/go/go-profiling-http-service-with-pprof-and-expvar/">Profiling Go HTTP service with pprof and expvar</a> I have already mentioned <strong>exparv</strong> and how to create middleware to expose this data. We will use that today.</p>
  </li>
</ol>

<h1 id="user-ip">User IP</h1>

<p>lets create simple function to get <strong>IP address</strong> from <a href="https://golang.org/pkg/net/http/#Request">http.Request</a></p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">IpAddress</span><span class="p">(</span><span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">(</span><span class="n">net</span><span class="o">.</span><span class="n">IP</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">addr</span> <span class="o">:=</span> <span class="n">r</span><span class="o">.</span><span class="n">RemoteAddr</span>
	<span class="k">if</span> <span class="n">xReal</span> <span class="o">:=</span> <span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Get</span><span class="p">(</span><span class="s">"X-Real-Ip"</span><span class="p">);</span> <span class="n">xReal</span> <span class="o">!=</span> <span class="s">""</span> <span class="p">{</span>
		<span class="n">addr</span> <span class="o">=</span> <span class="n">xReal</span>
	<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="n">xForwarded</span> <span class="o">:=</span> <span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Get</span><span class="p">(</span><span class="s">"X-Forwarded-For"</span><span class="p">);</span> <span class="n">xForwarded</span> <span class="o">!=</span> <span class="s">""</span> <span class="p">{</span>
		<span class="n">addr</span> <span class="o">=</span> <span class="n">xForwarded</span>
	<span class="p">}</span>

	<span class="n">ip</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">net</span><span class="o">.</span><span class="n">SplitHostPort</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="no">nil</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"addr: %q is not IP:port"</span><span class="p">,</span> <span class="n">addr</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="n">userIP</span> <span class="o">:=</span> <span class="n">net</span><span class="o">.</span><span class="n">ParseIP</span><span class="p">(</span><span class="n">ip</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">userIP</span> <span class="o">==</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="no">nil</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"ip: %q is not a valid IP address"</span><span class="p">,</span> <span class="n">ip</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">userIP</span><span class="p">,</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">IpAddress</code> returns user’s IP address from request, it checks for <code class="language-plaintext highlighter-rouge">X-Real-IP</code> and <code class="language-plaintext highlighter-rouge">X-Forwarded-For</code> headers (we assume our proxy is going to be trusted if any). Unless you have a trusted reverse proxy, you shouldn’t use this function, the client can set headers to any arbitrary value it wants.</p>

<h1 id="middleware">Middleware</h1>

<p>As usual we want a function that will return <a href="https://golang.org/pkg/net/http/#Handler">Handler</a> wrapper.
Before we write our rate limiter lets see how should our middleware look like:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">RateLimit</span><span class="p">(</span><span class="n">r</span> <span class="n">rate</span><span class="o">.</span><span class="n">Limit</span><span class="p">,</span> <span class="n">b</span> <span class="kt">int</span><span class="p">,</span> <span class="n">frequency</span> <span class="n">time</span><span class="o">.</span><span class="n">Duration</span><span class="p">)</span> <span class="k">func</span><span class="p">(</span><span class="n">next</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span><span class="p">)</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span> <span class="p">{</span>
	<span class="k">return</span> <span class="k">func</span><span class="p">(</span><span class="n">next</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span><span class="p">)</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span> <span class="p">{</span>
		<span class="k">if</span> <span class="n">r</span> <span class="o">==</span> <span class="n">rate</span><span class="o">.</span><span class="n">Inf</span> <span class="p">{</span>
			<span class="k">return</span> <span class="n">next</span>
		<span class="p">}</span>

		<span class="n">rl</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">rateLimiter</span><span class="p">{</span>
			<span class="n">rate</span><span class="o">:</span>     <span class="n">r</span><span class="p">,</span>
			<span class="n">burst</span><span class="o">:</span>    <span class="n">b</span><span class="p">,</span>
			<span class="n">visitors</span><span class="o">:</span> <span class="nb">make</span><span class="p">(</span><span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="o">*</span><span class="n">visitor</span><span class="p">),</span>
		<span class="p">}</span>

		<span class="k">go</span> <span class="n">rl</span><span class="o">.</span><span class="n">cleanup</span><span class="p">(</span><span class="n">frequency</span><span class="p">)</span>

		<span class="n">fn</span> <span class="o">:=</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">ip</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">request</span><span class="o">.</span><span class="n">IpAddress</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
			<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
				<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusText</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">),</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
				<span class="k">return</span>
			<span class="p">}</span>

			<span class="k">if</span> <span class="n">rl</span><span class="o">.</span><span class="n">allow</span><span class="p">(</span><span class="kt">string</span><span class="p">(</span><span class="n">ip</span><span class="p">))</span> <span class="p">{</span>
				<span class="n">next</span><span class="o">.</span><span class="n">ServeHTTP</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
			<span class="p">}</span>

			<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusText</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">StatusTooManyRequests</span><span class="p">),</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusTooManyRequests</span><span class="p">)</span>
			<span class="k">return</span>
		<span class="p">}</span>

		<span class="k">return</span> <span class="n">http</span><span class="o">.</span><span class="n">HandlerFunc</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>So what is going on here ? <code class="language-plaintext highlighter-rouge">RateLimit</code> returns a new HTTP middleware that allows request per visitor (IP address). If limit is set (<code class="language-plaintext highlighter-rouge">0</code> is a valid value and will block all requests) then the instance of <code class="language-plaintext highlighter-rouge">rateLimiter</code> is created and cleanup goroutine is spawned. It controls how frequently user requests are allowed to happen. In any large enough time, the <code class="language-plaintext highlighter-rouge">RateLimit</code> limits the rate to <code class="language-plaintext highlighter-rouge">r</code> requests per second with a maximum burst size of <code class="language-plaintext highlighter-rouge">b</code> requests. As a special case, if <code class="language-plaintext highlighter-rouge">r == Inf</code> (the infinite rate), middleware ignores limits. <code class="language-plaintext highlighter-rouge">frequency</code> decides how often map will be cleanup from expired entries.</p>

<p>See https://en.wikipedia.org/wiki/Token_bucket for more about token buckets.</p>

<h2 id="implementing-ratelimiter">Implementing rateLimiter</h2>

<p>At the time when I was writing this post there was already plenty of tools written by other people. We will use <a href="https://pkg.go.dev/golang.org/x/time/rate?tab=doc">golang.org/x/time/rate</a></p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">(</span>
	<span class="s">"net/http"</span>
	<span class="s">"sync"</span>
	<span class="s">"time"</span>

	<span class="s">"golang.org/x/time/rate"</span>
<span class="p">)</span>

<span class="k">type</span> <span class="n">visitor</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="o">*</span><span class="n">rate</span><span class="o">.</span><span class="n">Limiter</span>

	<span class="n">lastSeen</span> <span class="n">time</span><span class="o">.</span><span class="n">Time</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">rateLimiter</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">sync</span><span class="o">.</span><span class="n">RWMutex</span>

	<span class="n">burst</span>    <span class="kt">int</span>
	<span class="n">rate</span>     <span class="n">rate</span><span class="o">.</span><span class="n">Limit</span>
	<span class="n">visitors</span> <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="o">*</span><span class="n">visitor</span>
<span class="p">}</span>

<span class="c">// allow checks if given ip has not exceeded rate limit</span>
<span class="k">func</span> <span class="p">(</span><span class="n">l</span> <span class="o">*</span><span class="n">rateLimiter</span><span class="p">)</span> <span class="n">allow</span><span class="p">(</span><span class="n">ip</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
	<span class="n">l</span><span class="o">.</span><span class="n">RLock</span><span class="p">()</span>
	<span class="n">v</span><span class="p">,</span> <span class="n">exists</span> <span class="o">:=</span> <span class="n">l</span><span class="o">.</span><span class="n">visitors</span><span class="p">[</span><span class="n">ip</span><span class="p">]</span>
	<span class="n">l</span><span class="o">.</span><span class="n">RUnlock</span><span class="p">()</span>

	<span class="k">if</span> <span class="o">!</span><span class="n">exists</span> <span class="p">{</span>
		<span class="n">v</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">visitor</span><span class="p">{</span>
			<span class="n">Limiter</span><span class="o">:</span> <span class="n">rate</span><span class="o">.</span><span class="n">NewLimiter</span><span class="p">(</span><span class="n">l</span><span class="o">.</span><span class="n">rate</span><span class="p">,</span> <span class="n">l</span><span class="o">.</span><span class="n">burst</span><span class="p">),</span>
		<span class="p">}</span>
		<span class="n">l</span><span class="o">.</span><span class="n">Lock</span><span class="p">()</span>
		<span class="n">l</span><span class="o">.</span><span class="n">visitors</span><span class="p">[</span><span class="n">ip</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>
		<span class="n">l</span><span class="o">.</span><span class="n">Unlock</span><span class="p">()</span>
	<span class="p">}</span>

	<span class="n">v</span><span class="o">.</span><span class="n">lastSeen</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">Now</span><span class="p">()</span>

	<span class="n">m</span><span class="o">.</span><span class="n">rl</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="m">1</span><span class="p">)</span>

	<span class="k">return</span> <span class="n">v</span><span class="o">.</span><span class="n">Allow</span><span class="p">()</span>
<span class="p">}</span>

<span class="c">// cleanup deletes old entries</span>
<span class="k">func</span> <span class="p">(</span><span class="n">l</span> <span class="o">*</span><span class="n">rateLimiter</span><span class="p">)</span> <span class="n">cleanup</span><span class="p">(</span><span class="n">frequency</span> <span class="n">time</span><span class="o">.</span><span class="n">Duration</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">for</span> <span class="p">{</span>
		<span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="n">frequency</span><span class="p">)</span>

		<span class="n">l</span><span class="o">.</span><span class="n">Lock</span><span class="p">()</span>
		<span class="k">for</span> <span class="n">ip</span><span class="p">,</span> <span class="n">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">l</span><span class="o">.</span><span class="n">visitors</span> <span class="p">{</span>
			<span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">Since</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">lastSeen</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">frequency</span> <span class="p">{</span>
				<span class="nb">delete</span><span class="p">(</span><span class="n">l</span><span class="o">.</span><span class="n">visitors</span><span class="p">,</span> <span class="n">ip</span><span class="p">)</span>

				<span class="n">m</span><span class="o">.</span><span class="n">rl</span><span class="o">.</span><span class="n">Delete</span><span class="p">(</span><span class="n">ip</span><span class="p">)</span>
			<span class="p">}</span>
		<span class="p">}</span>
		<span class="n">l</span><span class="o">.</span><span class="n">Unlock</span><span class="p">()</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Our <code class="language-plaintext highlighter-rouge">rateLimiter</code> exposes two methods internally: <code class="language-plaintext highlighter-rouge">allow</code> and <code class="language-plaintext highlighter-rouge">cleanup</code>. As you can see our code sample already includes two lines for <a href="https://golang.org/pkg/expvar/">exparv</a> metrics we are going to expose.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">m</span><span class="o">.</span><span class="n">rl</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="m">1</span><span class="p">)</span>
</code></pre></div></div>

<p>and</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">m</span><span class="o">.</span><span class="n">rl</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="m">1</span><span class="p">)</span>
</code></pre></div></div>

<h1 id="expose-rate-limits">Expose rate limits</h1>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="s">"expvar"</span>

<span class="k">var</span> <span class="n">m</span> <span class="o">=</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">rl</span>  <span class="o">*</span><span class="n">expvar</span><span class="o">.</span><span class="n">Map</span>
<span class="p">}{</span>
	<span class="n">rl</span><span class="o">:</span>  <span class="n">expvar</span><span class="o">.</span><span class="n">NewMap</span><span class="p">(</span><span class="s">"rateLimits"</span><span class="p">),</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We create global variable (which we have used in previous snippet) with a <a href="https://golang.org/pkg/expvar/#Map">Map</a> property.</p>

<blockquote>
  <p>Map is a string-to-Var map variable that satisfies the Var interface.</p>
</blockquote>

<p>You can read more <a href="https://rafallorenz.com/go/go-profiling-http-service-with-pprof-and-expvar/#usage">how to expose this data via HTTP debug server</a>. Following this instructions you can see exported <code class="language-plaintext highlighter-rouge">rateLimits</code> at http://localhost:6060/debug/vars in your browser.</p>

<h1 id="conclusion">Conclusion</h1>

<p>We learned today how to use <a href="https://en.wikipedia.org/wiki/Rate_limiting">rate limiting</a> middleware to protect our server against <a href="https://en.wikipedia.org/wiki/Denial-of-service_attack">DoS attacks</a>. Simple yet powerful way of exposing this information via HTTP interface, allows us to easily verify IP suspicious addresses.</p>

<p>If you liked my post or maybe you didn’t ? Either way please leave some feedback in a comment below.</p>

<p>Full code snippet available <a href="https://gist.github.com/vardius/d06c255982a0f95261956d06a5774eb8">here</a> you can run it on <a href="https://play.golang.org/p/NVhqAJ4s_oq">The Go Playground</a>.</p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[In this article we are going to learn how to use rate limiting middleware to protect our server against DoS attacks.]]></summary></entry><entry><title type="html">How to handle signals with Go to graceful shutdown HTTP server</title><link href="http://rafallorenz.com/go/handle-signals-to-graceful-shutdown-http-server/" rel="alternate" type="text/html" title="How to handle signals with Go to graceful shutdown HTTP server" /><published>2020-06-18T00:00:00+00:00</published><updated>2020-06-18T00:00:00+00:00</updated><id>http://rafallorenz.com/go/handle-signals-to-graceful-shutdown-http-server</id><content type="html" xml:base="http://rafallorenz.com/go/handle-signals-to-graceful-shutdown-http-server/"><![CDATA[<p>In this article we are going to learn how to handle os incoming <a href="https://golang.org/pkg/os/signal">signals</a> for performing graceful shutdown of http server. To do so we are going to take advantage of <a href="https://golang.org/pkg/os/signal">os/signal</a> package.</p>

<blockquote>
  <p>Signals are primarily used on Unix-like systems.</p>
</blockquote>

<h1 id="types-of-signals">Types of signals</h1>

<p>We are going to focus on asynchronous signals. They are not triggered by program errors, but are instead sent from the kernel or from some other program.</p>

<p>Of the asynchronous signals:</p>

<ul>
  <li>the <code class="language-plaintext highlighter-rouge">SIGHUP</code> signal is sent when a program loses its controlling terminal</li>
  <li>the <code class="language-plaintext highlighter-rouge">SIGINT</code> signal is sent when the user at the controlling terminal presses the interrupt character, which by default is <strong>^C (Control-C)</strong></li>
  <li>The <code class="language-plaintext highlighter-rouge">SIGQUIT</code> signal is sent when the user at the controlling terminal presses the quit character, which by default is <strong>^\ (Control-Backslash)</strong></li>
</ul>

<p>In general you can cause a program to simply exit by pressing ^C, and you can cause it to exit with a stack dump by pressing ^.</p>

<h1 id="default-behavior-of-signals-in-go-programs">Default behavior of signals in Go programs</h1>

<blockquote>
  <p>By default, a synchronous signal is converted into a run-time panic. A <code class="language-plaintext highlighter-rouge">SIGHUP</code>, <code class="language-plaintext highlighter-rouge">SIGINT</code>, or <code class="language-plaintext highlighter-rouge">SIGTERM</code> signal causes the program to exit.
If the Go program is started with either SIGHUP or SIGINT ignored (signal handler set to SIG_IGN), they will remain ignored.
If the Go program is started with a non-empty signal mask, that will generally be honored. However, some signals are explicitly unblocked: the synchronous signals.</p>
</blockquote>

<p>You can read more about it on the <a href="https://golang.org/pkg/os/signal/#hdr-Default_behavior_of_signals_in_Go_programs">package documentation</a></p>

<h1 id="handling-signals">Handling signals</h1>

<p>The idea is to catch incoming signal and perform graceful stop of our http application. We can create signal channel using, and use it to notify on incoming signal. <code class="language-plaintext highlighter-rouge">signal.Notify</code> disables the default behavior for a given set of asynchronous signals and instead delivers them over one or more registered channels.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">signalChan</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="n">os</span><span class="o">.</span><span class="n">Signal</span><span class="p">,</span> <span class="m">1</span><span class="p">)</span>

	<span class="n">signal</span><span class="o">.</span><span class="n">Notify</span><span class="p">(</span>
		<span class="n">signalChan</span><span class="p">,</span>
		<span class="n">syscall</span><span class="o">.</span><span class="n">SIGHUP</span><span class="p">,</span>  <span class="c">// kill -SIGHUP XXXX</span>
		<span class="n">syscall</span><span class="o">.</span><span class="n">SIGINT</span><span class="p">,</span>  <span class="c">// kill -SIGINT XXXX or Ctrl+c</span>
		<span class="n">syscall</span><span class="o">.</span><span class="n">SIGQUIT</span><span class="p">,</span> <span class="c">// kill -SIGQUIT XXXX</span>
	<span class="p">)</span>

	<span class="o">&lt;-</span><span class="n">signalChan</span>
	<span class="n">log</span><span class="o">.</span><span class="n">Print</span><span class="p">(</span><span class="s">"os.Interrupt - shutting down...</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

	<span class="c">// terminate after second signal before callback is done</span>
	<span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
		<span class="o">&lt;-</span><span class="n">signalChan</span>
		<span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="s">"os.Kill - terminating...</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
	<span class="p">}()</span>

	<span class="c">// PERFORM GRACEFUL SHUTDOWN HERE</span>

	<span class="n">os</span><span class="o">.</span><span class="n">Exit</span><span class="p">(</span><span class="m">0</span><span class="p">)</span>
</code></pre></div></div>

<p>When signal is received we will call a callback followed after by <code class="language-plaintext highlighter-rouge">os.Exit(0)</code>, if second signal is received will terminate process by a call to <code class="language-plaintext highlighter-rouge">os.Exit(1)</code>.</p>

<h1 id="server">Server</h1>

<h2 id="graceful-shutdown">Graceful shutdown</h2>

<p>To gracefully shutdown <a href="https://golang.org/pkg/net/http/#Server">http.Server</a> we can use <a href="https://golang.org/pkg/net/http/#Server.Shutdown">Shutdown</a> method.</p>

<blockquote>
  <p>Shutdown gracefully shuts down the server without interrupting any active connections. Shutdown works by first closing all open listeners, then closing all idle connections, and then waiting indefinitely for connections to return to idle and then shut down. If the provided context expires before the shutdown is complete, Shutdown returns the context’s error, otherwise it returns any error returned from closing the Server’s underlying Listener(s).</p>
</blockquote>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">ctx</span><span class="p">,</span> <span class="n">cancel</span> <span class="o">:=</span> <span class="n">context</span><span class="o">.</span><span class="n">WithTimeout</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">(),</span> <span class="m">5</span><span class="o">*</span><span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">)</span>
  <span class="k">defer</span> <span class="n">cancel</span><span class="p">()</span>

  <span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">httpServer</span><span class="o">.</span><span class="n">Shutdown</span><span class="p">(</span><span class="n">ctx</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
    <span class="n">log</span><span class="o">.</span><span class="n">Fatalf</span><span class="p">(</span><span class="s">"shutdown error: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="n">log</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"gracefully stopped</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
  <span class="p">}</span>
</code></pre></div></div>

<blockquote>
  <p>Shutdown does not attempt to close nor wait for hijacked connections such as WebSockets. The caller of Shutdown should separately notify such long-lived connections of shutdown and wait for them to close, if desired. See <a href="https://golang.org/pkg/net/http/#Server.RegisterOnShutdown">RegisterOnShutdown</a> for a way to register shutdown notification functions.</p>
</blockquote>

<h2 id="handling-hijacked-connections">Handling hijacked connections</h2>

<blockquote>
  <p><a href="https://golang.org/pkg/net/http/#Server.RegisterOnShutdown">RegisterOnShutdown</a> registers a function to call on Shutdown. This can be used to gracefully shutdown connections that have undergone ALPN protocol upgrade or that have been hijacked. This function should start protocol-specific graceful shutdown, but should not wait for shutdown to complete.</p>
</blockquote>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	<span class="n">ctx</span><span class="p">,</span> <span class="n">cancel</span> <span class="o">:=</span> <span class="n">context</span><span class="o">.</span><span class="n">WithCancel</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">())</span>

	<span class="n">httpServer</span><span class="o">.</span><span class="n">RegisterOnShutdown</span><span class="p">(</span><span class="n">cancel</span><span class="p">)</span>
</code></pre></div></div>

<p>We want to ask context passed down to the socket handlers/goroutines to stop. To do so we can set <code class="language-plaintext highlighter-rouge">BaseContext</code> property on <a href="https://golang.org/pkg/net/http/#Server">http.Server</a>.</p>

<blockquote>
  <p>BaseContext optionally specifies a function that returns the base context for incoming requests on this server. The provided Listener is the specific Listener that’s about to start accepting requests. If BaseContext is nil, the default is context.Background(). If non-nil, it must return a non-nil context.</p>
</blockquote>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	<span class="n">ctx</span><span class="p">,</span> <span class="n">cancel</span> <span class="o">:=</span> <span class="n">context</span><span class="o">.</span><span class="n">WithCancel</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">())</span>

	<span class="n">httpServer</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Server</span><span class="p">{</span>
		<span class="n">Addr</span><span class="o">:</span>        <span class="s">":8080"</span><span class="p">,</span>
		<span class="n">Handler</span><span class="o">:</span>     <span class="n">mux</span><span class="p">,</span>
		<span class="n">BaseContext</span><span class="o">:</span> <span class="k">func</span><span class="p">(</span><span class="n">_</span> <span class="n">net</span><span class="o">.</span><span class="n">Listener</span><span class="p">)</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span> <span class="p">{</span> <span class="k">return</span> <span class="n">ctx</span> <span class="p">},</span>
	<span class="p">}</span>
	<span class="n">httpServer</span><span class="o">.</span><span class="n">RegisterOnShutdown</span><span class="p">(</span><span class="n">cancel</span><span class="p">)</span>
</code></pre></div></div>

<p>Keep in mind that doing so will make <a href="https://golang.org/pkg/net/http/#Server.Shutdown">Shutdown</a> cancel context via <code class="language-plaintext highlighter-rouge">RegisterOnShutdown</code> which will terminate all handlers using <code class="language-plaintext highlighter-rouge">BaseContext</code> immediately.</p>

<p>Full correct solution would require you to separate base context for WeSocket connections and other HTTP handlers. Also seems like introducing simple timeout to cancel <code class="language-plaintext highlighter-rouge">BaseContext</code> will not be enough, connections idleness has to be checked as well.</p>

<p>If you do not care about notifying long-lived connections during shutdown and don’t want to wait for them to close gracefully. Quick solution would be to manually cancel <code class="language-plaintext highlighter-rouge">BaseContext</code> instead of using <code class="language-plaintext highlighter-rouge">RegisterOnShutdown</code> which makes context get canceled as the first procedure during shutdown.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	<span class="n">ctx</span><span class="p">,</span> <span class="n">cancel</span> <span class="o">:=</span> <span class="n">context</span><span class="o">.</span><span class="n">WithCancel</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">())</span>

	<span class="n">httpServer</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Server</span><span class="p">{</span>
		<span class="n">Addr</span><span class="o">:</span>        <span class="s">":8080"</span><span class="p">,</span>
		<span class="n">Handler</span><span class="o">:</span>     <span class="n">mux</span><span class="p">,</span>
		<span class="n">BaseContext</span><span class="o">:</span> <span class="k">func</span><span class="p">(</span><span class="n">_</span> <span class="n">net</span><span class="o">.</span><span class="n">Listener</span><span class="p">)</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span> <span class="p">{</span> <span class="k">return</span> <span class="n">ctx</span> <span class="p">},</span>
	<span class="p">}</span>
	
	<span class="c">// GRACEFULLY SHUTDOWN</span>

	<span class="n">cancel</span><span class="p">()</span>
</code></pre></div></div>

<h1 id="gluing-up-all-pieces-together">Gluing up all pieces together</h1>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
	<span class="s">"context"</span>
	<span class="s">"fmt"</span>
	<span class="s">"log"</span>
	<span class="s">"net"</span>
	<span class="s">"net/http"</span>
	<span class="s">"os"</span>
	<span class="s">"os/signal"</span>
	<span class="s">"syscall"</span>
	<span class="s">"time"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">ctx</span><span class="p">,</span> <span class="n">cancel</span> <span class="o">:=</span> <span class="n">context</span><span class="o">.</span><span class="n">WithCancel</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">())</span>

	<span class="n">mux</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">NewServeMux</span><span class="p">()</span>
	<span class="n">mux</span><span class="o">.</span><span class="n">HandleFunc</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Hello!"</span><span class="p">)</span>
	<span class="p">})</span>

	<span class="n">httpServer</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Server</span><span class="p">{</span>
		<span class="n">Addr</span><span class="o">:</span>        <span class="s">":8080"</span><span class="p">,</span>
		<span class="n">Handler</span><span class="o">:</span>     <span class="n">mux</span><span class="p">,</span>
		<span class="n">BaseContext</span><span class="o">:</span> <span class="k">func</span><span class="p">(</span><span class="n">_</span> <span class="n">net</span><span class="o">.</span><span class="n">Listener</span><span class="p">)</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span> <span class="p">{</span> <span class="k">return</span> <span class="n">ctx</span> <span class="p">},</span>
	<span class="p">}</span>
	<span class="c">// if your BaseContext is more complex you might want to use this instead of doing it manually</span>
	<span class="c">// httpServer.RegisterOnShutdown(cancel)</span>

	<span class="c">// Run server</span>
	<span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
		<span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">httpServer</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">();</span> <span class="n">err</span> <span class="o">!=</span> <span class="n">http</span><span class="o">.</span><span class="n">ErrServerClosed</span> <span class="p">{</span>
			<span class="c">// it is fine to use Fatal here because it is not main gorutine</span>
			<span class="n">log</span><span class="o">.</span><span class="n">Fatalf</span><span class="p">(</span><span class="s">"HTTP server ListenAndServe: %v"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}()</span>

	<span class="n">signalChan</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="n">os</span><span class="o">.</span><span class="n">Signal</span><span class="p">,</span> <span class="m">1</span><span class="p">)</span>

	<span class="n">signal</span><span class="o">.</span><span class="n">Notify</span><span class="p">(</span>
		<span class="n">signalChan</span><span class="p">,</span>
		<span class="n">syscall</span><span class="o">.</span><span class="n">SIGHUP</span><span class="p">,</span>  <span class="c">// kill -SIGHUP XXXX</span>
		<span class="n">syscall</span><span class="o">.</span><span class="n">SIGINT</span><span class="p">,</span>  <span class="c">// kill -SIGINT XXXX or Ctrl+c</span>
		<span class="n">syscall</span><span class="o">.</span><span class="n">SIGQUIT</span><span class="p">,</span> <span class="c">// kill -SIGQUIT XXXX</span>
	<span class="p">)</span>

	<span class="o">&lt;-</span><span class="n">signalChan</span>
	<span class="n">log</span><span class="o">.</span><span class="n">Print</span><span class="p">(</span><span class="s">"os.Interrupt - shutting down...</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

	<span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
		<span class="o">&lt;-</span><span class="n">signalChan</span>
		<span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="s">"os.Kill - terminating...</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
	<span class="p">}()</span>

	<span class="n">gracefullCtx</span><span class="p">,</span> <span class="n">cancelShutdown</span> <span class="o">:=</span> <span class="n">context</span><span class="o">.</span><span class="n">WithTimeout</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">(),</span> <span class="m">5</span><span class="o">*</span><span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">)</span>
	<span class="k">defer</span> <span class="n">cancelShutdown</span><span class="p">()</span>

	<span class="k">if</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">httpServer</span><span class="o">.</span><span class="n">Shutdown</span><span class="p">(</span><span class="n">gracefullCtx</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">log</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"shutdown error: %v</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
		<span class="k">defer</span> <span class="n">os</span><span class="o">.</span><span class="n">Exit</span><span class="p">(</span><span class="m">1</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="n">log</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"gracefully stopped</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="c">// manually cancel context if not using httpServer.RegisterOnShutdown(cancel)</span>
	<span class="n">cancel</span><span class="p">()</span>

	<span class="k">defer</span> <span class="n">os</span><span class="o">.</span><span class="n">Exit</span><span class="p">(</span><span class="m">0</span><span class="p">)</span>
	<span class="k">return</span>
<span class="p">}</span>
</code></pre></div></div>

<p>When Shutdown is called, <code class="language-plaintext highlighter-rouge">Serve</code>, <code class="language-plaintext highlighter-rouge">ListenAndServe</code>, and <code class="language-plaintext highlighter-rouge">ListenAndServeTLS</code> immediately return <code class="language-plaintext highlighter-rouge">ErrServerClosed</code>. Make sure the program doesn’t exit and waits instead for Shutdown to return.</p>

<p><strong>Note</strong>: that we are deferring <code class="language-plaintext highlighter-rouge">os.Exit()</code> followed by <code class="language-plaintext highlighter-rouge">return</code>. Defers don’t run on <code class="language-plaintext highlighter-rouge">Fatal()</code>.</p>

<blockquote>
  <p>Calling Goexit from the main goroutine terminates that goroutine without func main returning. Since func main has not returned, the program continues execution of other goroutines. If all other goroutines exit, the program crashes.</p>
</blockquote>

<p>You can read conversation about it <a href="https://www.reddit.com/r/golang/comments/hbalgf/how_to_handle_signals_with_go_to_graceful/fv800rj?utm_source=share&amp;utm_medium=web2x">here</a></p>

<p>Run this example on <a href="https://play.golang.org/p/6w3yFxU1N24">The Go Playground</a></p>

<h1 id="conclusion">Conclusion</h1>

<p>By using tools provided by go environment, we can easily handle graceful shutdown of our application. We could simply create a package to handle that for us, in fact I already have created one if you are interested. <a href="https://github.com/vardius/shutdown">shutdown</a> - is a simple go signals handler for performing graceful shutdown by executing callback function.</p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[In this article we are going to learn how to handle os incoming signals for performing graceful shutdown of http server. To do so we are going to take advantage of os/signal package.]]></summary></entry><entry><title type="html">Profiling Go HTTP service with pprof and expvar</title><link href="http://rafallorenz.com/go/go-profiling-http-service-with-pprof-and-expvar/" rel="alternate" type="text/html" title="Profiling Go HTTP service with pprof and expvar" /><published>2020-06-12T00:00:00+00:00</published><updated>2020-06-12T00:00:00+00:00</updated><id>http://rafallorenz.com/go/go-profiling-http-service-with-pprof-and-expvar</id><content type="html" xml:base="http://rafallorenz.com/go/go-profiling-http-service-with-pprof-and-expvar/"><![CDATA[<p>In this article I am going to show how to profile http service and expose public variables such as operation counters for debugging. We will take advantage of two packages:</p>

<ul>
  <li><a href="https://golang.org/pkg/net/http/pprof/">net/http/pprof</a>
    <blockquote>
      <p>Package pprof serves via its HTTP server runtime profiling data in the format expected by the pprof visualization tool.
The package is typically only imported for the side effect of registering its HTTP handlers. The handled paths all begin with <code class="language-plaintext highlighter-rouge">/debug/pprof/</code>.</p>
    </blockquote>
  </li>
  <li><a href="https://golang.org/pkg/expvar/">expvar</a>
    <blockquote>
      <p>Package expvar provides a standardized interface to public variables, such as operation counters in servers. It exposes these variables via HTTP at /debug/vars in JSON format.
The package is sometimes only imported for the side effect of registering its HTTP handler and the above variables.</p>
    </blockquote>
  </li>
</ul>

<h1 id="debug-middleware">Debug middleware</h1>

<p>Lets create a simple middleware for our server to expose some counters which we can debug later via <code class="language-plaintext highlighter-rouge">expvar</code> handler.
We want to count number or requests and the number of active goroutines.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">// m contains the global program counters for the application.</span>
<span class="k">var</span> <span class="n">m</span> <span class="o">=</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">gr</span>  <span class="o">*</span><span class="n">expvar</span><span class="o">.</span><span class="n">Int</span>
	<span class="n">req</span> <span class="o">*</span><span class="n">expvar</span><span class="o">.</span><span class="n">Int</span>
<span class="p">}{</span>
	<span class="n">gr</span><span class="o">:</span>  <span class="n">expvar</span><span class="o">.</span><span class="n">NewInt</span><span class="p">(</span><span class="s">"goroutines"</span><span class="p">),</span>
	<span class="n">req</span><span class="o">:</span> <span class="n">expvar</span><span class="o">.</span><span class="n">NewInt</span><span class="p">(</span><span class="s">"requests"</span><span class="p">),</span>
<span class="p">}</span>

<span class="c">// Metrics updates program counters.</span>
<span class="k">func</span> <span class="n">Metrics</span><span class="p">(</span><span class="n">next</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span><span class="p">)</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span> <span class="p">{</span>
    <span class="n">fn</span> <span class="o">:=</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">next</span><span class="o">.</span><span class="n">ServeHTTP</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>

        <span class="c">// Increment the request counter.</span>
        <span class="n">m</span><span class="o">.</span><span class="n">req</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="m">1</span><span class="p">)</span>

        <span class="c">// Update the count for the number of active goroutines every 100 requests.</span>
        <span class="k">if</span> <span class="n">m</span><span class="o">.</span><span class="n">req</span><span class="o">.</span><span class="n">Value</span><span class="p">()</span><span class="o">%</span><span class="m">100</span> <span class="o">==</span> <span class="m">0</span> <span class="p">{</span>
            <span class="n">m</span><span class="o">.</span><span class="n">gr</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="kt">int64</span><span class="p">(</span><span class="n">runtime</span><span class="o">.</span><span class="n">NumGoroutine</span><span class="p">()))</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">http</span><span class="o">.</span><span class="n">HandlerFunc</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="debug-server">Debug server</h1>

<p>We will create separate server instance, that is going to be run only in debug mode. We don’t want to run it at all times.</p>

<p>Our debug server will expose two routes:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">/debug/pprof</code> added to the default mux by importing the <code class="language-plaintext highlighter-rouge">net/http/pprof</code> package.</li>
  <li><code class="language-plaintext highlighter-rouge">/debug/vars</code> added to the default mux by importing the <code class="language-plaintext highlighter-rouge">expvar</code> package.</li>
</ul>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">(</span>
	<span class="s">"net/http"</span>
	<span class="n">_</span> <span class="s">"expvar"</span> <span class="c">// Register the expvar handlers</span>
	<span class="n">_</span> <span class="s">"net/http/pprof"</span> <span class="c">// Register the pprof handlers</span>
<span class="p">)</span>

<span class="k">type</span> <span class="n">DebugServer</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Server</span>
<span class="p">}</span>

<span class="c">// NewDebugServer provides new debug http server</span>
<span class="k">func</span> <span class="n">NewDebugServer</span><span class="p">(</span><span class="n">address</span> <span class="kt">string</span><span class="p">)</span> <span class="o">*</span><span class="n">DebugServer</span> <span class="p">{</span>
	<span class="k">return</span> <span class="o">&amp;</span><span class="n">DebugServer</span><span class="p">{</span>
		<span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Server</span><span class="p">{</span>
			<span class="n">Addr</span><span class="o">:</span>    <span class="n">address</span><span class="p">,</span>
			<span class="n">Handler</span><span class="o">:</span> <span class="n">http</span><span class="o">.</span><span class="n">DefaultServeMux</span><span class="p">,</span>
		<span class="p">},</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="usage">Usage</h1>

<p>After having our middleware and server done, we can use it as follow:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">var</span> <span class="n">isDebug</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">Getenv</span><span class="p">(</span><span class="s">"DEBUG"</span><span class="p">)</span> <span class="o">!=</span> <span class="s">""</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">mux</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">NewServeMux</span><span class="p">()</span>
	<span class="n">mux</span><span class="o">.</span><span class="n">HandleFunc</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Welcome to the home page!"</span><span class="p">)</span>
    <span class="p">})</span>

    <span class="n">httpServer</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Server</span><span class="p">{</span>
        <span class="n">Addr</span><span class="o">:</span>    <span class="s">":8080"</span><span class="p">,</span>
        <span class="n">Handler</span><span class="o">:</span> <span class="n">Metrics</span><span class="p">(</span><span class="n">mux</span><span class="p">),</span> <span class="c">// wrap our server with metrics middleware</span>
    <span class="p">}</span>

    <span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
		<span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">httpServer</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">())</span>
    <span class="p">}()</span>

	<span class="k">if</span> <span class="n">isDebug</span> <span class="p">{</span>
        <span class="n">debugServer</span> <span class="o">:=</span> <span class="n">NewDebugServer</span><span class="p">(</span><span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s:%d"</span><span class="p">,</span> <span class="s">"localhost"</span><span class="p">,</span> <span class="m">6060</span><span class="p">))</span>

		<span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
			<span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">debugServer</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">())</span>
		<span class="p">}()</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="counters">Counters</h2>

<p>To see exported counters open http://localhost:6060/debug/vars in your browser.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"cmdline"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="s2">"/var/folders/_4/81_0n4l57_scy27jfcxx1j300000gn/T/go-build888334884/b001/exe/main"</span><span class="w">
  </span><span class="p">],</span><span class="w">
  </span><span class="nl">"goroutines"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
  </span><span class="nl">"requests"</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w">
  </span><span class="nl">"memstats"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="err">...</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h2 id="pprof">pprof</h2>

<p>To view all available profiles, open http://localhost:6060/debug/pprof/ in your browser.</p>

<p><a href="/images/pprof.png"><img src="/images/pprof.png" alt="pprof" /></a></p>

<p>We can see visualization using <em>go tool</em> as follow:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go tool pprof http://localhost:6060/debug/pprof/heap
</code></pre></div></div>

<p>To see graph in browser lets type <em>web</em></p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>pprof<span class="o">)</span> web
failed to execute dot. Is Graphviz installed? Error: <span class="nb">exec</span>: <span class="s2">"dot"</span>: executable file not found <span class="k">in</span> <span class="nv">$PATH</span>
</code></pre></div></div>

<p>If you see error you can install it with:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew <span class="nb">install </span>graphviz
</code></pre></div></div>

<p>Repeat the sequence:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go tool pprof http://localhost:6060/debug/pprof/heap
<span class="o">(</span>pprof<span class="o">)</span> web
</code></pre></div></div>

<p>This will open browser with nice graph.</p>

<p><a href="/images/pprof001.svg"><img src="/images/pprof001.svg" alt="heap" /></a></p>

<blockquote>
  <p>Each box in the graph corresponds to a single function, and the boxes are sized according to the number of samples in which the function was running.</p>
</blockquote>

<p>You can read more about profiling Go programs on <a href="https://blog.golang.org/pprof">the go blog</a>.</p>

<h1 id="conclusion">Conclusion</h1>

<p>Most of the times we do not want to run debug server on production instance but there are times that we really need to see what is going on under the hood. Simply toggling environment flag allows us to quickly turn on debug server. This easy way we can enable or disable debug server instance and get access to detailed information about our application. Full code snippet available <a href="https://gist.github.com/vardius/c7861a3ee19cd04164165cfb5f2f95cc">here</a></p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[In this article I am going to show how to profile http service and expose public variables such as operation counters for debugging. We will take advantage of two packages:]]></summary></entry><entry><title type="html">Basic HTTP authentication with Go</title><link href="http://rafallorenz.com/go/go-basic-authentication/" rel="alternate" type="text/html" title="Basic HTTP authentication with Go" /><published>2020-06-08T00:00:00+00:00</published><updated>2020-06-08T00:00:00+00:00</updated><id>http://rafallorenz.com/go/go-basic-authentication</id><content type="html" xml:base="http://rafallorenz.com/go/go-basic-authentication/"><![CDATA[<p><a href="https://tools.ietf.org/html/rfc7235">RFC 7235</a> defines the HTTP authentication as follow:</p>

<blockquote>
  <p>HTTP provides a general framework for access control and authentication, via an extensible set of <a href="https://en.wikipedia.org/wiki/Challenge–response_authentication">challenge-response</a> authentication schemes, which can be used by a server to challenge a client request and by a client to provide authentication information.</p>
</blockquote>

<p>Basic access authentication is a method for an HTTP user agent (e.g. a web browser) to provide a user and password when making a request. Usually a client will present a password prompt to the user and will then issue the request including the correct Authorization header.</p>

<p>We can write simple middleware leveraging <a href="https://golang.org/pkg/net/http/#Request.BasicAuth">BasicAuth</a> method.</p>

<blockquote>
  <p>BasicAuth returns the username and password provided in the request’s Authorization header, if the request uses HTTP Basic Authentication.</p>
</blockquote>

<p>That is all we need. Our middleware will wrap <em>protected</em> handlers verifying username and password. Based on this information we can decide to grand or restrict access.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">var</span> <span class="p">(</span>
	<span class="n">requiredUser</span>     <span class="o">=</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">(</span><span class="s">"gordon"</span><span class="p">)</span>
	<span class="n">requiredPassword</span> <span class="o">=</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">(</span><span class="s">"secret!"</span><span class="p">)</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">BasicAuth</span><span class="p">(</span><span class="n">next</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span><span class="p">)</span> <span class="n">http</span><span class="o">.</span><span class="n">Handler</span> <span class="p">{</span>
	<span class="n">fn</span> <span class="o">:=</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
		<span class="c">// Get the Basic Authentication credentials</span>
		<span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">hasAuth</span> <span class="o">:=</span> <span class="n">r</span><span class="o">.</span><span class="n">BasicAuth</span><span class="p">()</span>

		<span class="k">if</span> <span class="o">!</span><span class="n">hasAuth</span> <span class="o">||</span> <span class="n">subtle</span><span class="o">.</span><span class="n">ConstantTimeCompare</span><span class="p">(</span><span class="n">requiredUser</span><span class="p">,</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">(</span><span class="n">user</span><span class="p">))</span> <span class="o">!=</span> <span class="m">1</span> <span class="o">||</span> <span class="n">subtle</span><span class="o">.</span><span class="n">ConstantTimeCompare</span><span class="p">(</span><span class="n">requiredPassword</span><span class="p">,</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">(</span><span class="n">password</span><span class="p">))</span> <span class="o">!=</span> <span class="m">1</span> <span class="p">{</span>
			<span class="n">w</span><span class="o">.</span><span class="n">Header</span><span class="p">()</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"WWW-Authenticate"</span><span class="p">,</span> <span class="s">"Basic realm=Restricted"</span><span class="p">)</span>
			<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusText</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">StatusUnauthorized</span><span class="p">),</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusUnauthorized</span><span class="p">)</span>
			<span class="k">return</span>
		<span class="p">}</span>

		<span class="n">next</span><span class="o">.</span><span class="n">ServeHTTP</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">http</span><span class="o">.</span><span class="n">HandlerFunc</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In this example our middleware uses const values for username and password pair. Real life applications most likely would verify this information against values stored in database. Please note that <a href="https://golang.org/pkg/crypto/subtle/#ConstantTimeCompare">subtle.ConstantTimeCompare</a> still depends on the length, so it is probably possible for attackers to work out the length of the username and password if you do it like this. To get around that you could hash them or add a fixed delay.</p>

<p>Lets create two routes with different handlers. One id going to be publicly accessible and the other one is going to be protected with basic authentication.</p>

<p>We could do it as follow:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">index</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">_</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Fprint</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Not protected!</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">protected</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">_</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Fprint</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Protected!</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">http</span><span class="o">.</span><span class="n">HandleFunc</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span>
	<span class="n">http</span><span class="o">.</span><span class="n">Handle</span><span class="p">(</span><span class="s">"/protected"</span><span class="p">,</span> <span class="n">BasicAuth</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">HandlerFunc</span><span class="p">(</span><span class="n">protected</span><span class="p">)))</span>

	<span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">(</span><span class="s">":8080"</span><span class="p">,</span> <span class="no">nil</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Trying to access index route <code class="language-plaintext highlighter-rouge">/</code> we are not required to provide user name and password. However <code class="language-plaintext highlighter-rouge">/protected</code> route should prompt us for authentication details.</p>

<h1 id="conclusion">Conclusion</h1>

<p>This simple example of how to use basic authentication method teaches us how simple it is and on top of that we learned how to create simple middleware function, to be reused with multiple handlers. Full code snippet available <a href="https://gist.github.com/vardius/a8da23717acb20c16cdf113647de0e2b">here</a></p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[RFC 7235 defines the HTTP authentication as follow:]]></summary></entry><entry><title type="html">Handling multidomain HTTP requests with simple host switch</title><link href="http://rafallorenz.com/go/go-multidomain-host-switch/" rel="alternate" type="text/html" title="Handling multidomain HTTP requests with simple host switch" /><published>2020-06-05T00:00:00+00:00</published><updated>2020-06-05T00:00:00+00:00</updated><id>http://rafallorenz.com/go/go-multidomain-host-switch</id><content type="html" xml:base="http://rafallorenz.com/go/go-multidomain-host-switch/"><![CDATA[<p>When writing <a href="http://golang.org">Go</a> HTTP services we might need to perform different logic based on host the request comes from or simply validate host value. We could implement simple host switch mechanism to take care of that.</p>

<h1 id="host-switch">Host Switch</h1>

<p>As difficult as host switch may sound, it is actually quite easy to implement. We need to implement the <a href="https://golang.org/pkg/net/http/#Handler">http.Handler</a> interface.
To do that we will create a type for which we implement the <code class="language-plaintext highlighter-rouge">ServeHTTP</code> method.
We will just use a map here, in which we map host names (with port) to http.Handlers.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">(</span>
    <span class="s">"fmt"</span>
    <span class="s">"log"</span>
    <span class="s">"net/http"</span>
<span class="p">)</span>

<span class="k">type</span> <span class="n">HostSwitch</span> <span class="k">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="n">http</span><span class="o">.</span><span class="n">Handler</span>

<span class="c">// Implement the ServerHTTP method</span>
<span class="k">func</span> <span class="p">(</span><span class="n">hs</span> <span class="n">HostSwitch</span><span class="p">)</span> <span class="n">ServeHTTP</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="n">handler</span><span class="p">,</span> <span class="n">ok</span> <span class="o">:=</span> <span class="n">hs</span><span class="p">[</span><span class="n">r</span><span class="o">.</span><span class="n">Host</span><span class="p">];</span> <span class="n">ok</span> <span class="o">&amp;&amp;</span> <span class="n">handler</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
        <span class="n">handler</span><span class="o">.</span><span class="n">ServeHTTP</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Forbidden"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusForbidden</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Our <code class="language-plaintext highlighter-rouge">HostSwitch</code> simply checks if a <a href="https://golang.org/pkg/net/http/#Handler">http.Handler</a> is registered for the given host, then uses it to handle request. Otherwise we return http error <code class="language-plaintext highlighter-rouge">http.StatusForbidden</code>. We could do a redirect here to another host, depends what we really need in real life example.</p>

<h1 id="usage">Usage</h1>

<p>Let’s say our switch will handle two hosts:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">example-one.local</code></li>
  <li><code class="language-plaintext highlighter-rouge">example-two.local</code></li>
</ul>

<p>And return forbidden response otherwise. We will use <a href="https://golang.org/pkg/net/http/#ServeMux">ServeMux</a> as a router for both hosts.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">mux</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">NewServeMux</span><span class="p">()</span>
	<span class="n">mux</span><span class="o">.</span><span class="n">HandleFunc</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Welcome to the first home page!"</span><span class="p">)</span>
	<span class="p">})</span>

	<span class="n">muxTwo</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">NewServeMux</span><span class="p">()</span>
	<span class="n">muxTwo</span><span class="o">.</span><span class="n">HandleFunc</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Welcome to the second home page!"</span><span class="p">)</span>
	<span class="p">})</span>

    <span class="n">hs</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="n">HostSwitch</span><span class="p">)</span>
    <span class="n">hs</span><span class="p">[</span><span class="s">"example-one.local:8080"</span><span class="p">]</span> <span class="o">=</span> <span class="n">mux</span>
    <span class="n">hs</span><span class="p">[</span><span class="s">"example-two.local:8080"</span><span class="p">]</span> <span class="o">=</span> <span class="n">muxTwo</span>

    <span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">(</span><span class="s">":8080"</span><span class="p">,</span> <span class="n">hs</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Example is very straightforward, after creating two routers, we make a new <code class="language-plaintext highlighter-rouge">HostSwitch</code> and insert each router for given host we want it to handle.
Then we listen and serve on both ports. We could use same router if what we want is to actually validate host value.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">mux</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">NewServeMux</span><span class="p">()</span>
	<span class="n">mux</span><span class="o">.</span><span class="n">HandleFunc</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="k">func</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"Welcome to the home page!"</span><span class="p">)</span>
	<span class="p">})</span>

    <span class="n">hs</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="n">HostSwitch</span><span class="p">)</span>
    <span class="n">hs</span><span class="p">[</span><span class="s">"example-one.local:8080"</span><span class="p">]</span> <span class="o">=</span> <span class="n">mux</span>
    <span class="n">hs</span><span class="p">[</span><span class="s">"example-two.local:8080"</span><span class="p">]</span> <span class="o">=</span> <span class="n">mux</span>

    <span class="k">go</span> <span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">(</span><span class="s">":8080"</span><span class="p">,</span> <span class="n">hs</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Even though we perform only read operation, it is always better to use mutexes while working with maps. Don’t forget to use <a href="https://golang.org/pkg/sync/#Mutex">mutexes</a> to make our <code class="language-plaintext highlighter-rouge">HostSwitch</code> concurrency safe.</p>

<h1 id="conclusion">Conclusion</h1>

<p>Today we have created a simple <code class="language-plaintext highlighter-rouge">HostSwitch</code> which allows us to handle requests only if they come from valid hosts or perform different logic per host. This example demonstrates how to handle multidomains with Go. Example on <a href="https://play.golang.org/p/bMbKPGE7LhT">The Go Playground</a></p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[When writing Go HTTP services we might need to perform different logic based on host the request comes from or simply validate host value. We could implement simple host switch mechanism to take care of that.]]></summary></entry><entry><title type="html">Errors with stack trace</title><link href="http://rafallorenz.com/go/go-error-stack-trace/" rel="alternate" type="text/html" title="Errors with stack trace" /><published>2020-06-02T00:00:00+00:00</published><updated>2020-06-02T00:00:00+00:00</updated><id>http://rafallorenz.com/go/go-error-stack-trace</id><content type="html" xml:base="http://rafallorenz.com/go/go-error-stack-trace/"><![CDATA[<p>Often when debugging Go code, errors stack trace is often built with following pattern:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"Failed to do something: %w"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>One error is wrapped with another, message is concatenated, with some delimiter in this case <code class="language-plaintext highlighter-rouge">:</code>. We end up with error information hard to pin to a place where it actualy happend, which results in long trail and many steps of going file by file, error to error until we actually find it. So how could we improve our error experiance ?Before we start lets rewind a little bit and answer a simple question. What is error ?</p>

<p><strong>Errors are values</strong>. This is very crucial thing to understand, if you come to Go from another enviroment you have to move one from a mental object of <em>try/catch</em>. Once you do that handling errors becomes clear and simple.</p>

<p>So what does it really mean ?</p>

<blockquote>
  <p>Values can be programmed, and since errors are values, errors can be programmed.</p>
</blockquote>

<p>Most common way of handling errors is simply comparing them with <code class="language-plaintext highlighter-rouge">nil</code> value. Because <strong>errors are values</strong>.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
    <span class="c">// something went wrong</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This also means we can add any information to error, for example stack trace.</p>

<h1 id="error-as-value">Error as value</h1>

<p><a href="https://golang.org/pkg/builtin/#error">error</a> type is simply an interface, which means by creating our custom error type that implements that interface we could add any extra information. Lets define our error as follow:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">AppError</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">trace</span> <span class="kt">string</span>
	<span class="n">err</span>   <span class="kt">error</span>
<span class="p">}</span>

<span class="c">// Error returns the string representation of the error message.</span>
<span class="k">func</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span><span class="n">AppError</span><span class="p">)</span> <span class="n">Error</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s</span><span class="se">\n</span><span class="s">%s"</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">trace</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">err</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span><span class="n">AppError</span><span class="p">)</span> <span class="n">Unwrap</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">e</span><span class="o">.</span><span class="n">err</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Our error will contain wrapped error, plus a stack trace where it happened. <em>AppError</em> type will implement two important methods: <a href="https://golang.org/pkg/builtin/#error">Error</a> and <a href="https://golang.org/pkg/errors/#Unwrap">Unwrap</a>. Since Go 1.13 introduces <a href="https://blog.golang.org/go1.13-errors">new features</a> to the errors and fmt standard library packages to simplify working with errors that contain other errors. It makes it even easier to handle them.</p>

<h2 id="unwrap">Unwrap</h2>
<p><em>Unwrap</em> method that returns its contained error:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span><span class="n">AppError</span><span class="p">)</span> <span class="n">Unwrap</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">e</span><span class="o">.</span><span class="n">err</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="adding-stack-trace">Adding stack trace</h1>

<p>To add stack trace to our error we will use <a href="https://golang.org/pkg/runtime/#Caller">runtime.Caller</a></p>

<blockquote>
  <p>Caller reports file and line number information about function invocations on the calling goroutine’s stack. The argument skip is the number of stack frames to ascend, with 0 identifying the caller of Caller. (For historical reasons the meaning of skip differs between Caller and Callers.) The return values report the program counter, file name, and line number within the file of the corresponding call. The boolean ok is false if it was not possible to recover the information.</p>
</blockquote>

<p>End result should look something like this:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"%s"</span><span class="p">,</span> <span class="n">AppenStackTrace</span><span class="p">(</span><span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"internal error"</span><span class="p">)))</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">AppenStackTrace</code> Simply wraps <code class="language-plaintext highlighter-rouge">error</code> using our <code class="language-plaintext highlighter-rouge">AppError</code> type and appends stack trace information:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">AppenStackTrace</span><span class="p">(</span><span class="n">err</span> <span class="kt">error</span><span class="p">)</span> <span class="o">*</span><span class="n">AppError</span> <span class="p">{</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">==</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="nb">panic</span><span class="p">(</span><span class="s">"nil error provided"</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="n">buf</span> <span class="n">bytes</span><span class="o">.</span><span class="n">Buffer</span>

	<span class="n">frame</span> <span class="o">:=</span> <span class="n">getFrame</span><span class="p">(</span><span class="m">2</span><span class="p">)</span>

	<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="s">"%s"</span><span class="p">,</span> <span class="n">frame</span><span class="o">.</span><span class="n">File</span><span class="p">)</span>
	<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="s">":%d"</span><span class="p">,</span> <span class="n">frame</span><span class="o">.</span><span class="n">Line</span><span class="p">)</span>
	<span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="s">" %s"</span><span class="p">,</span> <span class="n">frame</span><span class="o">.</span><span class="n">Function</span><span class="p">)</span>

	<span class="k">return</span> <span class="o">&amp;</span><span class="n">AppError</span><span class="p">{</span>
		<span class="n">err</span><span class="o">:</span>   <span class="n">err</span><span class="p">,</span>
		<span class="n">trace</span><span class="o">:</span> <span class="n">buf</span><span class="o">.</span><span class="n">String</span><span class="p">(),</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">getFrame</span><span class="p">(</span><span class="n">calldepth</span> <span class="kt">int</span><span class="p">)</span> <span class="o">*</span><span class="n">runtime</span><span class="o">.</span><span class="n">Frame</span> <span class="p">{</span>
	<span class="n">pc</span><span class="p">,</span> <span class="n">file</span><span class="p">,</span> <span class="n">line</span><span class="p">,</span> <span class="n">ok</span> <span class="o">:=</span> <span class="n">runtime</span><span class="o">.</span><span class="n">Caller</span><span class="p">(</span><span class="n">calldepth</span><span class="p">)</span>
	<span class="k">if</span> <span class="o">!</span><span class="n">ok</span> <span class="p">{</span>
		<span class="k">return</span> <span class="no">nil</span>
	<span class="p">}</span>

	<span class="n">frame</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">runtime</span><span class="o">.</span><span class="n">Frame</span><span class="p">{</span>
		<span class="n">PC</span><span class="o">:</span>   <span class="n">pc</span><span class="p">,</span>
		<span class="n">File</span><span class="o">:</span> <span class="n">file</span><span class="p">,</span>
		<span class="n">Line</span><span class="o">:</span> <span class="n">line</span><span class="p">,</span>
	<span class="p">}</span>

	<span class="n">funcForPc</span> <span class="o">:=</span> <span class="n">runtime</span><span class="o">.</span><span class="n">FuncForPC</span><span class="p">(</span><span class="n">pc</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">funcForPc</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">frame</span><span class="o">.</span><span class="n">Func</span> <span class="o">=</span> <span class="n">funcForPc</span>
		<span class="n">frame</span><span class="o">.</span><span class="n">Function</span> <span class="o">=</span> <span class="n">funcForPc</span><span class="o">.</span><span class="n">Name</span><span class="p">()</span>
		<span class="n">frame</span><span class="o">.</span><span class="n">Entry</span> <span class="o">=</span> <span class="n">funcForPc</span><span class="o">.</span><span class="n">Entry</span><span class="p">()</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">frame</span>
<span class="p">}</span>
</code></pre></div></div>

<p>To build complete stack trace, we could create a method as follow:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="p">(</span><span class="n">e</span> <span class="o">*</span><span class="n">AppError</span><span class="p">)</span> <span class="n">StackTrace</span><span class="p">()</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">var</span> <span class="n">buf</span> <span class="n">bytes</span><span class="o">.</span><span class="n">Buffer</span>

	<span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">trace</span> <span class="o">!=</span> <span class="s">""</span> <span class="p">{</span>
		<span class="k">if</span> <span class="n">_</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Fprintf</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buf</span><span class="p">,</span> <span class="s">"%s"</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">trace</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
			<span class="k">return</span> <span class="s">""</span><span class="p">,</span> <span class="n">err</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">err</span> <span class="o">==</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">buf</span><span class="o">.</span><span class="n">String</span><span class="p">(),</span> <span class="no">nil</span>
	<span class="p">}</span>

	<span class="k">var</span> <span class="n">next</span> <span class="o">*</span><span class="n">AppError</span>
	<span class="k">if</span> <span class="n">errors</span><span class="o">.</span><span class="n">As</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">err</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">next</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">stackTrace</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">next</span><span class="o">.</span><span class="n">StackTrace</span><span class="p">()</span>
		<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
			<span class="k">return</span> <span class="s">""</span><span class="p">,</span> <span class="n">err</span>
		<span class="p">}</span>

		<span class="n">buf</span><span class="o">.</span><span class="n">WriteString</span><span class="p">(</span><span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">%s"</span><span class="p">,</span> <span class="n">stackTrace</span><span class="p">))</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"%s</span><span class="se">\n</span><span class="s">%s"</span><span class="p">,</span> <span class="n">buf</span><span class="o">.</span><span class="n">String</span><span class="p">(),</span> <span class="n">e</span><span class="o">.</span><span class="n">err</span><span class="p">),</span> <span class="no">nil</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="n">buf</span><span class="o">.</span><span class="n">String</span><span class="p">(),</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We simply build buffer with each error information and then dig dipper into our error chain. We use <a href="https://golang.org/pkg/errors/#As">errors.As</a>.</p>
<blockquote>
  <p>The As function tests whether an error is a specific type.</p>
</blockquote>

<p>Running following example:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">err</span> <span class="o">:=</span> <span class="n">AppenStackTrace</span><span class="p">(</span><span class="n">testOne</span><span class="p">())</span>
	<span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"%s"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">testOne</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"testOne: %w"</span><span class="p">,</span> <span class="n">AppenStackTrace</span><span class="p">(</span><span class="n">testTwo</span><span class="p">()))</span>

<span class="p">}</span>

<span class="k">func</span> <span class="n">testTwo</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"testTwo: %w"</span><span class="p">,</span> <span class="n">AppenStackTrace</span><span class="p">(</span><span class="n">testThree</span><span class="p">()))</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">testThree</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
	<span class="k">return</span> <span class="n">AppenStackTrace</span><span class="p">(</span><span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"internal error"</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>should give us output:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/tmp/sandbox073776686/prog.go:74 main.main
testOne: /tmp/sandbox073776686/prog.go:82 main.testOne
testTwo: /tmp/sandbox073776686/prog.go:87 main.testTwo
/tmp/sandbox073776686/prog.go:91 main.testThree
internal error
</code></pre></div></div>

<p>Printing error uses <code class="language-plaintext highlighter-rouge">.Error()</code> method from <code class="language-plaintext highlighter-rouge">error</code> interface. Which under the hood unwraps each error using <code class="language-plaintext highlighter-rouge">Unwrap</code> method, because we wrapped them with <code class="language-plaintext highlighter-rouge">fmt.Errorf</code> and <code class="language-plaintext highlighter-rouge">%w</code> print format. Lets print our stack trace using our builtin <code class="language-plaintext highlighter-rouge">StackTrace</code> method:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">t</span><span class="p">,</span> <span class="n">_</span> <span class="o">:=</span> <span class="n">err</span><span class="o">.</span><span class="n">StackTrace</span><span class="p">()</span>
	<span class="n">fmt</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"%s"</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>output:</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/tmp/sandbox073776686/prog.go:74 main.main
/tmp/sandbox073776686/prog.go:82 main.testOne
/tmp/sandbox073776686/prog.go:87 main.testTwo
/tmp/sandbox073776686/prog.go:91 main.testThree
internal error
</code></pre></div></div>

<h1 id="conclusion">Conclusion</h1>

<p>Handling errors is pretty simple, having them as values allows us to do really powerful things. We can append any information we want, for example stack trace as we did in the example above. Defining custom type for error is great way of doing that, and not necessarily has to be done one the whole scope of application. Instead of calling our type <code class="language-plaintext highlighter-rouge">AppError</code> we could define many types, where each of them would hold different information. Let’s say <code class="language-plaintext highlighter-rouge">QueryError</code> to handle persistence model errors with query information or <code class="language-plaintext highlighter-rouge">HttpError</code> to store <em>http</em> response code and/or user error message (without stack trace).</p>

<p>As you can see simple check <code class="language-plaintext highlighter-rouge">err != nil</code> is not a drop in replacement of <em>try/catch</em>. It’s important to change a mental object of error handling while working with Go, which is not that hard and requires only a little of time getting used to it. Please see <a href="https://gist.github.com/vardius/56b224de0a69522a24f021642449db17">full code snippet here</a>.</p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[Often when debugging Go code, errors stack trace is often built with following pattern:]]></summary></entry><entry><title type="html">HTTP how to stream download response</title><link href="http://rafallorenz.com/go/go-http-stream-download/" rel="alternate" type="text/html" title="HTTP how to stream download response" /><published>2020-05-26T00:00:00+00:00</published><updated>2020-05-26T00:00:00+00:00</updated><id>http://rafallorenz.com/go/go-http-stream-download</id><content type="html" xml:base="http://rafallorenz.com/go/go-http-stream-download/"><![CDATA[<p>When writing download handler for files most of the times best solution is to use <code class="language-plaintext highlighter-rouge">io.Copy</code> which will handle big part of the logic for us. This works great however what if we need to generate bytes for our response while having the user downloading the file seeing how it is growing when we write to <code class="language-plaintext highlighter-rouge">ResponseWriter</code> ?</p>

<p><a href="/images/2020-5-26-go-http-stream-download.gif"><img src="/images/2020-5-26-go-http-stream-download.gif" alt="Stream response example" style="width: 400px;" /></a></p>

<p>I have seen questions online how to stream download response many times. Even though it seems pretty simple many people expect complex logic here.</p>

<p>Lets start from the begging.</p>

<h2 id="standard-example">Standard example</h2>

<p>Lets assume we have simple <code class="language-plaintext highlighter-rouge">main.go</code> file with one handler. <em>main</em> function could look as follow:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">mux</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">NewServeMux</span><span class="p">()</span>
	<span class="n">mux</span><span class="o">.</span><span class="n">HandleFunc</span><span class="p">(</span><span class="s">"/"</span><span class="p">,</span> <span class="n">downloadHandler</span><span class="p">)</span>

	<span class="n">http</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">(</span><span class="s">":3000"</span><span class="p">,</span> <span class="n">mux</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>and if we were using simple approach with  <code class="language-plaintext highlighter-rouge">io.Copy</code> it probably would look like this:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">downloadHandler</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">resp</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">Get</span><span class="p">(</span><span class="s">"https://golangcode.com/logo.svg"</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not write response"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span>
	<span class="k">defer</span> <span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>

	<span class="n">w</span><span class="o">.</span><span class="n">Header</span><span class="p">()</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"Content-Disposition"</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"attachment; filename=%s"</span><span class="p">,</span> <span class="s">"logo.svg"</span><span class="p">))</span>
	<span class="n">w</span><span class="o">.</span><span class="n">Header</span><span class="p">()</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"Content-Type"</span><span class="p">,</span> <span class="s">"image/svg+xml"</span><span class="p">)</span>
	<span class="n">w</span><span class="o">.</span><span class="n">Header</span><span class="p">()</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"Last-Modified"</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">Now</span><span class="p">()</span><span class="o">.</span><span class="n">UTC</span><span class="p">()</span><span class="o">.</span><span class="n">Format</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">TimeFormat</span><span class="p">))</span>

	<span class="n">n</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">io</span><span class="o">.</span><span class="n">Copy</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not read body"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In the example above we simply stream to user the file we got from the url. Works like a charm.</p>

<h2 id="csv-writer">CSV Writer</h2>

<p>If its the case and we want to generate CSV file, best idea is to use</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">(</span>
	<span class="s">"encoding/csv"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">downloadHandler</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
    <span class="c">// previous code...</span>

    <span class="n">cw</span> <span class="o">:=</span> <span class="n">csv</span><span class="o">.</span><span class="n">NewWriter</span><span class="p">(</span><span class="n">w</span><span class="p">)</span>

	<span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">record</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">records</span> <span class="p">{</span>
		<span class="k">if</span> <span class="n">err</span> <span class="o">=</span> <span class="n">cw</span><span class="o">.</span><span class="n">Write</span><span class="p">(</span><span class="n">record</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
            <span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not write record"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
			<span class="k">return</span>
		<span class="p">}</span>
		<span class="n">cw</span><span class="o">.</span><span class="n">Flush</span><span class="p">()</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Write writes a single CSV record to w along with any necessary quoting. A record is a slice of strings with each string being one field. Writes are buffered, so Flush must eventually be called to ensure that the record is written to the underlying io.Writer.</p>

<h2 id="stream-response">Stream response</h2>

<p>But wait !? We want to generate buffer from chunks! How could we return them to user in a similar way csv writer does.</p>

<p>To not make things overly complicated lets say we reuse bytes of our file from before instead of generating them. Pretending we do some work and generate each byte then write it to response. Lets simply iterate over the bytes of our file and assume each byte is a chunk we generated. We will wait for about 200 microsecond to see some work being done (file we are using in this example is small).</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">chunk</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">body</span> <span class="p">{</span>
	<span class="k">if</span> <span class="n">_</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">rw</span><span class="o">.</span><span class="n">Write</span><span class="p">(</span><span class="n">chunk</span><span class="p">);</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not write chunk"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span>

	<span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">200</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Microsecond</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This should work just fine, our file will start download and we can see how its size grows in the browser.</p>

<h2 id="servecontent">ServeContent</h2>

<blockquote>
  <p><a href="https://godoc.org/net/http#ServeContent">ServeContent</a> replies to the request using the content in the provided ReadSeeker. The main benefit of ServeContent over io.Copy is that it handles Range requests properly, sets the MIME type, and handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, and If-Range requests.</p>
</blockquote>

<blockquote>
  <p>If the response’s Content-Type header is not set, ServeContent first tries to deduce the type from name’s file extension and, if that fails, falls back to reading the first block of the content and passing it to DetectContentType. The name is otherwise unused; in particular it can be empty and is never sent in the response.</p>
</blockquote>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">downloadHandler</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">resp</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">Get</span><span class="p">(</span><span class="s">"https://golangcode.com/logo.svg"</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not write response"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span>
	<span class="k">defer</span> <span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>

	<span class="n">body</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">ioutil</span><span class="o">.</span><span class="n">ReadAll</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not read body"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span>

	<span class="n">http</span><span class="o">.</span><span class="n">ServeContent</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="s">"logo.svg"</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">Now</span><span class="p">(),</span> <span class="n">bytes</span><span class="o">.</span><span class="n">NewReader</span><span class="p">(</span><span class="n">body</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>With that in mind we could implement our own <a href="https://golang.org/pkg/io/#Seeker">Seeker</a></p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Seeker</span> <span class="k">interface</span> <span class="p">{</span>
    <span class="n">Seek</span><span class="p">(</span><span class="n">offset</span> <span class="kt">int64</span><span class="p">,</span> <span class="n">whence</span> <span class="kt">int</span><span class="p">)</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<blockquote>
  <p>Seeker is the interface that wraps the basic Seek method.</p>
</blockquote>

<blockquote>
  <p>Seek sets the offset for the next Read or Write to offset, interpreted according to whence: SeekStart means relative to the start of the file, SeekCurrent means relative to the current offset, and SeekEnd means relative to the end. Seek returns the new offset relative to the start of the file and an error, if any.</p>
</blockquote>

<p>This way we could fetch each chunk at seek method and then return it during write operation. It could look like this:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">stream</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">chunk</span>     <span class="p">[]</span><span class="kt">byte</span>
	<span class="n">i</span>         <span class="kt">int64</span>                     <span class="c">// current reading index</span>
	<span class="n">fetch</span>     <span class="k">func</span><span class="p">(</span><span class="n">offset</span> <span class="kt">int64</span><span class="p">)</span> <span class="p">[]</span><span class="kt">byte</span> <span class="c">// fetch callback</span>
	<span class="n">totalSize</span> <span class="k">func</span><span class="p">()</span> <span class="kt">int64</span>              <span class="c">// total size callback</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">s</span> <span class="o">*</span><span class="n">stream</span><span class="p">)</span> <span class="n">Read</span><span class="p">(</span><span class="n">b</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="p">(</span><span class="n">n</span> <span class="kt">int</span><span class="p">,</span> <span class="n">err</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">chunk</span><span class="p">)</span> <span class="o">==</span> <span class="m">0</span> <span class="p">{</span>
		<span class="k">return</span> <span class="m">0</span><span class="p">,</span> <span class="n">io</span><span class="o">.</span><span class="n">EOF</span>
	<span class="p">}</span>

	<span class="c">// simply copy our chunk</span>
	<span class="n">n</span> <span class="o">=</span> <span class="nb">copy</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">s</span><span class="o">.</span><span class="n">chunk</span><span class="p">)</span>
	<span class="n">s</span><span class="o">.</span><span class="n">i</span> <span class="o">+=</span> <span class="kt">int64</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>

	<span class="k">return</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">s</span> <span class="o">*</span><span class="n">stream</span><span class="p">)</span> <span class="n">Seek</span><span class="p">(</span><span class="n">offset</span> <span class="kt">int64</span><span class="p">,</span> <span class="n">whence</span> <span class="kt">int</span><span class="p">)</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">var</span> <span class="n">abs</span> <span class="kt">int64</span>
	<span class="k">switch</span> <span class="n">whence</span> <span class="p">{</span>
	<span class="k">case</span> <span class="n">io</span><span class="o">.</span><span class="n">SeekStart</span><span class="o">:</span>
		<span class="n">abs</span> <span class="o">=</span> <span class="n">offset</span>
	<span class="k">case</span> <span class="n">io</span><span class="o">.</span><span class="n">SeekCurrent</span><span class="o">:</span>
		<span class="n">abs</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">i</span> <span class="o">+</span> <span class="n">offset</span>
	<span class="k">case</span> <span class="n">io</span><span class="o">.</span><span class="n">SeekEnd</span><span class="o">:</span>
		<span class="n">abs</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">totalSize</span><span class="p">()</span> <span class="o">+</span> <span class="n">offset</span>
	<span class="k">default</span><span class="o">:</span>
		<span class="k">return</span> <span class="m">0</span><span class="p">,</span> <span class="n">errors</span><span class="o">.</span><span class="n">New</span><span class="p">(</span><span class="s">"stream..Reader.Seek: invalid whence"</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">if</span> <span class="n">abs</span> <span class="o">&lt;</span> <span class="m">0</span> <span class="p">{</span>
		<span class="k">return</span> <span class="m">0</span><span class="p">,</span> <span class="n">errors</span><span class="o">.</span><span class="n">New</span><span class="p">(</span><span class="s">"stream..Reader.Seek: negative position"</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="n">s</span><span class="o">.</span><span class="n">i</span> <span class="o">=</span> <span class="n">abs</span>
	<span class="n">s</span><span class="o">.</span><span class="n">chunk</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">fetch</span><span class="p">(</span><span class="n">abs</span><span class="p">)</span> <span class="c">// fetch chunk and set to buffer</span>

	<span class="k">return</span> <span class="n">abs</span><span class="p">,</span> <span class="no">nil</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">downloadHandler</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">resp</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">http</span><span class="o">.</span><span class="n">Get</span><span class="p">(</span><span class="s">"https://golangcode.com/logo.svg"</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not write response"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span>
	<span class="k">defer</span> <span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>

	<span class="n">body</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">ioutil</span><span class="o">.</span><span class="n">ReadAll</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">Body</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
		<span class="n">http</span><span class="o">.</span><span class="n">Error</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="s">"could not read body"</span><span class="p">,</span> <span class="n">http</span><span class="o">.</span><span class="n">StatusInternalServerError</span><span class="p">)</span>
		<span class="k">return</span>
	<span class="p">}</span>

	<span class="n">s</span> <span class="o">:=</span> <span class="n">stream</span><span class="p">{</span>
		<span class="c">// this is our asynchronous callback to get each chunk</span>
		<span class="n">fetch</span><span class="o">:</span> <span class="k">func</span><span class="p">(</span><span class="n">offset</span> <span class="kt">int64</span><span class="p">)</span> <span class="p">[]</span><span class="kt">byte</span> <span class="p">{</span>
			<span class="k">return</span> <span class="n">body</span><span class="p">[</span><span class="n">offset</span><span class="o">:</span><span class="p">]</span>
		<span class="p">},</span>
		<span class="c">// this callback provides total size</span>
		<span class="n">totalSize</span><span class="o">:</span> <span class="k">func</span><span class="p">()</span> <span class="kt">int64</span> <span class="p">{</span>
			<span class="k">return</span> <span class="kt">int64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">body</span><span class="p">))</span>
		<span class="p">},</span>
	<span class="p">}</span>

	<span class="c">// we set the type as we know it and ServeContent doesn't have to guess it</span>
	<span class="c">// we as well do not want it to return whole content at once if it can not guess the type</span>
	<span class="n">w</span><span class="o">.</span><span class="n">Header</span><span class="p">()</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"Content-Type"</span><span class="p">,</span> <span class="s">"image/svg+xml"</span><span class="p">)</span>
	<span class="n">http</span><span class="o">.</span><span class="n">ServeContent</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="s">"logo.svg"</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">Now</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">s</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As before for simplicity we use our body bytes here assuming we would have some logic to generate them.</p>

<h2 id="conclusion">Conclusion</h2>

<p>There is no magic here, coming from another environment like PHP or Python I hear many question how to stream response. The answer simply is <strong>write to ResponseWriter</strong> I hope my post will help many those looking for answer while its right in front of them. Do not look for complicated logic.</p>

<p>Full working code snippet available on <a href="https://gist.github.com/vardius/ebdbd84d23d6e794edf322f7fd9e02fa">gist</a>.</p>]]></content><author><name></name></author><category term="Go" /><summary type="html"><![CDATA[When writing download handler for files most of the times best solution is to use io.Copy which will handle big part of the logic for us. This works great however what if we need to generate bytes for our response while having the user downloading the file seeing how it is growing when we write to ResponseWriter ?]]></summary></entry><entry><title type="html">Lightweight library providing peer to peer CDN - beta version!</title><link href="http://rafallorenz.com/javascript/peer-cdn-beta/" rel="alternate" type="text/html" title="Lightweight library providing peer to peer CDN - beta version!" /><published>2018-03-13T00:00:00+00:00</published><updated>2018-03-13T00:00:00+00:00</updated><id>http://rafallorenz.com/javascript/peer-cdn-beta</id><content type="html" xml:base="http://rafallorenz.com/javascript/peer-cdn-beta/"><![CDATA[<p>I have released <a href="https://github.com/vardius/peer-cdn/releases/tag/1.0.0-beta"><strong>beta</strong> version</a> of my <a href="https://github.com/vardius/peer-cdn">peer-cdn</a>. What I would expect out of this version is <strong>feedback</strong> on the matter of <strong>browser support</strong> and the issues I haven’t thing of. This version is released in case of finding out what is need to be done before actual release.</p>

<h1 id="overview">Overview</h1>
<p>The main idea of <strong><a href="https://github.com/vardius/peer-cdn">peer-cdn</a></strong> is to use <strong>WebRTC</strong> and <strong>Service Worker</strong> to allow assets such as <em>scripts</em>, <em>images</em>, <em>videos</em>, <em>styles</em> and other files to be shared between peers reducing server usage.</p>

<p>By importing <strong><a href="https://github.com/vardius/peer-cdn">peer-cdn</a></strong> into your service worker you get the access to exported <code class="language-plaintext highlighter-rouge">PeerCDN</code> class, <a href="https://github.com/vardius/peer-cdn/wiki/Plugins">Plugins</a> and <a href="https://github.com/vardius/peer-cdn/wiki/Strategies">Strategies</a>.</p>

<p><strong><a href="https://github.com/vardius/peer-cdn">peer-cdn</a></strong> allow you to register listeners and add middleware to fetch event. For more information, see <a href="https://github.com/vardius/peer-cdn/wiki/Middleware">Middleware</a>.</p>

<p>For full example please check <a href="https://github.com/vardius/peer-cdn/blob/master/example">this directory</a></p>

<h1 id="things-to-consider">Things to consider:</h1>
<ul>
  <li>peer matching algorithms (ways of improving - pick best direction to go from here, beta version keeps it simple - pick first)</li>
  <li>browser support <a href="https://webrtc.org">WebRTC</a></li>
  <li>browser support <a href="https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage#Browser_compatibility"><code class="language-plaintext highlighter-rouge">client.postMessage()</code></a></li>
  <li>media supported (there might be issues with range request)</li>
</ul>

<p>For now I know there might be some issues with:</p>
<ul>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage#Browser_compatibility"><code class="language-plaintext highlighter-rouge">client.postMessage()</code></a> problems on <strong>Google Chrome Version 64.0.3282.167 (Official Build) (64-bit)</strong> however works on <strong>Mozilla Firefox Quantum 58.0.2 (64-bit)</strong></li>
  <li><a href="https://github.com/vardius/peer-cdn/issues/7">range requests</a></li>
</ul>

<p>Would love to get any feedback nad/or contributions! Check <a href="https://github.com/vardius/peer-cdn/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22">help wanted</a> issues and <a href="https://github.com/vardius/peer-cdn/blob/master/CONTRIBUTING.md#development">contribute</a>. Also feel free to contact me.</p>

<h1 id="next-steps">Next steps:</h1>
<ul>
  <li>add more tests</li>
  <li>resolve browser support</li>
  <li>create web pack plugin</li>
  <li>improve signalling server</li>
</ul>

<p>Cheers guy!</p>]]></content><author><name></name></author><category term="Javascript" /><summary type="html"><![CDATA[I have released beta version of my peer-cdn. What I would expect out of this version is feedback on the matter of browser support and the issues I haven’t thing of. This version is released in case of finding out what is need to be done before actual release.]]></summary></entry></feed>