home blog portfolio Ian Fisher

You are viewing the Markdown source of this page. Return to the main page.


# HTTP servers in Go
*This example is for plain HTTP. You should use HTTPS, either in Go directly or by putting the Go server behind a reverse proxy.*

```go
import (
	"fmt"
	"log"
	"net/http"
)

func handleIndex(writer http.ResponseWriter, req *http.Request) {
	// req.URL.Query()
	// req.URL.Path
	// req.Header["Hostname"]
	// req.RemoteAddr

	// writer.WriteHeader(http.StatusInternalServerError)
	// writer.Header().Set("Content-Type", "application/json")
}

handler := &http.ServeMux{}
handler.HandleFunc("/", handleIndex)
addr := fmt.Sprintf(":%d", port)
server := &http.Server{
	ReadHeaderTimeout: readHeaderTimeout,
	ReadTimeout:       readTimeout,
	WriteTimeout:      writeTimeout,
	IdleTimeout:       idleTimeout,
	Addr:              addr,
	Handler:           handler,
}
log.Fatal("server failed", server.ListenAndServe())
```

- **Use your own `http.ServeMux`** rather than `http.HandleFunc` and `http.ListenAndServe`; libraries like `net/http/pprof` can add their own endpoints to the latter, which you don't want to accidentally expose to the public.
- Each request is handled in **its own goroutine**. So you must **synchronize access** to shared state. Panics are caught by the framework and transformed into HTTP 500 errors.
- Handlers that do long-running work should terminate when the **`req.Context().Done()` channel** is closed.
- URL patterns ending with `/` **match a prefix, not a whole path**. So the URL pattern `/static/` matches not just `/static/` but also `/static/index.js` (unless already matched by a more specific pattern).

## Links
- [`net/http` docs](https://pkg.go.dev/net/http)
- ["REST Servers in Go"](https://eli.thegreenplace.net/2021/rest-servers-in-go-part-1-standard-library/) (Eli Bendersky, 2021)
- ["On concurrency in Go HTTP servers"](https://eli.thegreenplace.net/2019/on-concurrency-in-go-http-servers) (Eli Bendersky, 2019)
- ["Graceful shutdown of a TCP server in Go"](https://eli.thegreenplace.net/2020/graceful-shutdown-of-a-tcp-server-in-go/) (Eli Bendersky, 2020)
- ["So you want to expose Go on the Internet"](https://blog.cloudflare.com/exposing-go-on-the-internet/) (Filippo Valsorda @ Cloudflare, 2016)
- ["Make resilient Go net/http servers"](https://ieftimov.com/posts/make-resilient-golang-net-http-servers-using-timeouts-deadlines-context-cancellation/) (Ilija Eftimov, 2020)

Examples:

- [`fast-concordance`](https://github.com/iafisher/fast-concordance)
	- [Server implementation](https://github.com/iafisher/fast-concordance/blob/master/cmd/server/main.go)
	- [IP rate limiter](https://github.com/iafisher/fast-concordance/blob/master/internal/ratelimiter/ratelimiter.go)