<p>When I first set out to build Gophish 5 years ago, I used it as an opportunity to learn Golang.</p>
<p>One of the things that makes Go so powerful is the batteries-included standard library, which makes it a breeze to write servers. In this post, we’ll walk through how to build web servers, starting from a basic <em>Hello World</em> and ending with a web server that:</p>
<ul>
<li><ahref="#adding-let-s-encrypt">Uses Let’s Encrypt for HTTPS</a></li>
<li><ahref="#adding-fancy-routes">Implements an API subrouter</a></li>
<li><ahref="#graceful-shutdown">Shuts down gracefully</a>
<!-- more --></li>
</ul>
<p>If you just want the final code, you can find it in my <ahref="https://github.com/jordan-wright/http-boilerplate">http-boilerplate</a> repo on Github.</p>
<h3id="hello-world">Hello World!</h3>
<p>It’s incredibly quick to create an HTTP server in Go. Here’s a simple example that implements a single handler that returns “Hello World!”:</p>
<divclass="highlight"><prestyle="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><codeclass="language-golang"data-lang="golang"><spanstyle="color:#2838b0">package</span> main
http<spanstyle="color:#888">.</span>HandleFunc<spanstyle="color:#888">(</span><spanstyle="color:#b83838">"/"</span><spanstyle="color:#888">,</span><spanstyle="color:#2838b0;font-style:italic">func</span><spanstyle="color:#888">(</span>w http<spanstyle="color:#888">.</span>ResponseWriter<spanstyle="color:#888">,</span> r <spanstyle="color:#666">*</span>http<spanstyle="color:#888">.</span>Request<spanstyle="color:#888">)</span><spanstyle="color:#888">{</span>
<p>This example uses the <ahref="https://golang.org/pkg/net/http/"><code>net/http</code></a> package, which is the backbone for building HTTP clients and servers in Go. To better understand what we’re building, we should very briefly cover three important concepts: <ahref="https://golang.org/pkg/net/http/#Handler"><code>http.Handler</code></a>, <ahref="https://golang.org/pkg/net/http/#ServeMux"><code>http.ServeMux</code></a>, and <ahref="https://golang.org/pkg/net/http/#Server"><code>http.Server</code></a>.</p>
<h4id="http-handlers">HTTP Handlers</h4>
<p>When a request is received, a <em>handler</em> processes it and writes out a response. Go implements handlers as an interface with the following signature:</p>
<p>Our first example uses the helper function <ahref="https://golang.org/pkg/net/http/#HandleFunc"><code>http.HandleFunc</code></a>, which wraps a function that takes an <code>http.ResponseWriter</code> and <code>http.Request</code> in a <code>ServeHTTP</code> function so that it can be used as a handler.</p>
<p>Having handlers as an interface is <strong>really</strong> powerful. For example, we’ll see later on that implementing middleware is done by simply making a handler whose <code>ServeHTTP</code> does <em>something</em>, then calls another handler’s <code>ServeHTTP</code> method.</p>
<p>So handlers are responsible for processing requests, but how do we know which handler to use?</p>
<h4id="routing-requests">Routing Requests</h4>
<p>To determine which handler should process a request, Go uses an HTTP multiplexer. Some libraries may call this a “muxer” or a “router”, but the idea is the same. A router determines which handler to execute based on the path received. In our example above, we’re using the basic <ahref="https://golang.org/pkg/net/http/#ServeMux">default multiplexer</a>.</p>
<p>If you need more advanced routing support, you might consider using a third-party library. The <ahref="https://github.com/gorilla/mux"><code>gorilla/mux</code></a> or <ahref="https://github.com/go-chi/chi"><code>go-chi/chi</code></a> libraries are good alternatives that make it easy to set up middleware, wildcard routing, and more. And, most importantly, they work with the standard HTTP handlers which keeps things simple and easy to change later on.</p>
<p><strong>Be careful when using complex web frameworks.</strong> These are typically very opinionated, and make it difficult to work with standard handlers. In my experience, the standard library mixed with a lightweight router is good enough for most applications.</p>
<p>Finally, we need something that can listen for incoming connections, sending each request to the router so that it can be processed by the right handler. This is the <ahref="https://golang.org/pkg/net/http/#Server"><code>http.Server</code></a>.</p>
<p>As we’ll see later, the server is responsible for all the connection handling. This includes things like handling TLS, if configured. In our example, the call to <ahref="https://golang.org/pkg/net/http/#ListenAndServe"><code>http.ListenAndServe</code></a> uses the default HTTP server.</p>
<p>With this background out of the way, let’s dive into some more complex examples.</p>
<p>Our original example serves requests over HTTP. It’s always recommended to use HTTPS, where possible, and fortunately Go makes that easy.</p>
<p>If you already have a private key and certificate, you can change the server to use <ahref="https://golang.org/pkg/net/http/#ListenAndServeTLS"><code>ListenAndServeTLS</code></a> and providing the correct filepaths:</p>
<p><ahref="https://letsencrypt.org/">Let’s Encrypt</a> is a free certificate authority that lets you renew certificates automatically. We can use the <ahref="https://godoc.org/golang.org/x/crypto/acme/autocert"><code>autocert</code></a> package to configure our server with Let’s Encrypt support.</p>
<p>The easiest way to get this set up is to use the <ahref="https://godoc.org/golang.org/x/crypto/acme/autocert#NewListener"><code>autocert.NewListener</code></a> helper with the <code>http.Serve</code> method. This gathers and renews the TLS certificates via Let’s Encrypt, while letting the underlying HTTP server handle the requests:</p>
<p>Opening your browser to <code>https://example.com</code> will show the “Hello World!” response served over HTTPS.</p>
<p>If you need more customization, you can create an instance of <ahref="https://godoc.org/golang.org/x/crypto/acme/autocert#Manager"><code>autocert.Manager</code></a>. Then, you can create your own instance of <code>http.Server</code> (remember: we’ve been using the default one so far) and add the manager as the server’s <code>TLSConfig</code>:</p>
<p>The default router included with the standard library is good, but simple. It’s common to want more complex logic, such as setting up subrouters, creating wildcard routes, and adding parameters or pattern matching into routes.</p>
<p>This is where libraries like <ahref="https://github.com/gorilla/mux"><code>gorilla/mux</code></a> and <ahref="https://github.com/go-chi/chi"><code>go-chi/chi</code></a> can be useful. Here’s an example of showing how to set up some very basic API routes using the <code>chi</code> library:</p>
<p>First, assume we have a file called <code>api/v1/api.go</code> that contains the routes for our API:</p>
<divclass="highlight"><prestyle="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><codeclass="language-go"data-lang="go"><spanstyle="color:#888;font-style:italic">// HelloResponse is the JSON representation for a customized message
<spanstyle="color:#888;font-style:italic">// HelloName returns a personalized JSON message
</span><spanstyle="color:#888;font-style:italic"></span><spanstyle="color:#2838b0;font-style:italic">func</span> HelloName<spanstyle="color:#888">(</span>w http<spanstyle="color:#888">.</span>ResponseWriter<spanstyle="color:#888">,</span> r <spanstyle="color:#666">*</span>http<spanstyle="color:#888">.</span>Request<spanstyle="color:#888">)</span><spanstyle="color:#888">{</span>
name <spanstyle="color:#666">:=</span> chi<spanstyle="color:#888">.</span>URLParam<spanstyle="color:#888">(</span>r<spanstyle="color:#888">,</span><spanstyle="color:#b83838">"name"</span><spanstyle="color:#888">)</span>
<p>We can then mount this to our main router under the <code>api/v1/</code> prefix back in our main application:</p>
<divclass="highlight"><prestyle="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><codeclass="language-go"data-lang="go"><spanstyle="color:#888;font-style:italic">// NewRouter returns a new HTTP handler that implements the main server routes
<p>Middleware is just wrapping an HTTP handler in another handler. This lets us implement authentication, logging, compression, and more.</p>
<p>The pattern for middleware is straightfoward due to the simplicity of the <code>http.Handler</code> interface. We can just write a function that takes a handler and wraps it in another handler. Here’s an example, showing how an authentication handler might be implemented:</p>
<spanstyle="color:#2838b0">return</span> http<spanstyle="color:#888">.</span>HandlerFunc<spanstyle="color:#888">(</span><spanstyle="color:#2838b0;font-style:italic">func</span><spanstyle="color:#888">(</span>w http<spanstyle="color:#888">.</span>ResponseWriter<spanstyle="color:#888">,</span> r <spanstyle="color:#666">*</span>http<spanstyle="color:#888">.</span>Request<spanstyle="color:#888">)</span><spanstyle="color:#888">{</span>
<p>Golang has support in the standard library for serving static files, such as images, Javascript, and stylesheets. This is done by using a function, <ahref="https://golang.org/pkg/net/http/#FileServer"><code>http.FileServer</code></a>, which returns a handler that serves files from a directory.</p>
<p>Here’s a simple example using our router from the previous example:</p>
<p><strong>Be careful!</strong> The default <ahref="https://golang.org/pkg/net/http/#Dir"><code>http.Dir</code></a> filesystem used by Go lists the contents of directories if no <code>index.html</code> exists. This could expose sensitive information. I have a package called <ahref="https://github.com/jordan-wright/unindexed"><code>unindexed</code></a> which can be used as a drop-in replacement to prevent this.</p>
<h3id="graceful-shutdown">Graceful Shutdown</h3>
<p>Go version 1.8 introduced the ability to gracefully shutdown an HTTP server by calling the <ahref="https://golang.org/pkg/net/http/#Server.Shutdown"><code>Shutdown()</code></a> method. We can use this by starting our server in a goroutine and listening on a channel for a signal interrupt (e.g. pressing CTRL+C). Once this is received, we can give the server a few seconds to gracefully shutdown.</p>
<p>The Go standard library is incredibly powerful. This post shows how we can take advantage of the flexible interfaces and built-in functionality to quickly create robust HTTP servers.</p>
<p>While this is a great start, I recommend checking out <ahref="https://blog.cloudflare.com/exposing-go-on-the-internet/">Cloudflare’s post</a> on other precautions to take before exposing a Go HTTP server to the Internet. In the next part to this series, we’ll walk through how to add context (such as a database connection) and configuration to our servers.</p>
<p>If you’re interested in seeing an example of these techniques that you can use for your own application, check out the <ahref="https://github.com/jordan-wright/http-boilerplate">http-boilerplate</a> project on Github.</p>
<p><strong>Finally, if you want to see these techniques (and more!) applied in a full product, be sure to check out <ahref="https://github.com/gophish/gophish">Gophish</a> on Github.</strong></p>
<sectionclass="poweredby">Proudly generated by <aclass="icon-hugo"href="http://gohugo.io">HUGO</a>, with <aclass="icon-theme"href="https://github.com/vjeantet/hugo-theme-casper">Casper</a> theme</section>