17 May 2022

go

Serving static files in Go

Author

Gurleen Sethi

Serving static files in Go

Getting started #

In this article, you are going to learn how to serve static files in GO over HTTP. We will first learn how to achieve this using GO's inbuilt http.Dir type and http.FileServer function.

Preparing code directory #

Let's assume we have the following directory structure (I encourage you to replicate this and run the examples on your machine šŸ‘ØšŸ»ā€šŸ’»).

- main.go
- /static
	- styles.css

We have a simple main.go file and folder called static which contains a styles.css file with the following content.

/* styles.css */

body {
    background: bisque;
    color: black;
    font-family: sans-serif;
}

Serving static files #

Serving static files with built-in GO functions is so simple, that it can be covered in a single example.

package main

import (
	"log"
	"net/http"
)

func main() {
	dir := http.Dir("./static")
	
	fs := http.FileServer(dir)

	mux := http.NewServeMux()

	mux.Handle("/", fs)

	err := http.ListenAndServe(":5555", mux)
	if err != nil {
		log.Fatal(err)
	}
}

Execute go run main.go and open localhost:5555 in your browser, you will see static file serving in action!

Clicking on styles.css will reveal its content.

Breakdown of the above example:

  • dir := http.Dir("./static") Providing path to the static folder that we want to serve.
  • fs := http.FileServer(dir) Using GO's inbuilt FileServer to server files, under the hood it is a http.Handler that tries to read files. fs is an http.Handler.
  • mux := http.NewServeMux() Creating a new ServeMux.
  • mux.Handle("/", fs) Telling our serve mux to call the fs handler when the path is /.
Email Newsletter Icon
Don't miss new articles
Get notified once/twice per month when new articles are published.

Auto serving index.html #

If the folder you are serving has an index.html file, GO will automatically detect the presense of this file and serve it by default.

Add a new file in the static folder called index.html with the following content.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home</title>
</head>
<body>
    <h1>Hello World :D</h1>
</body>
</html>

Now opening the browser would reveal our beautiful html file.

Let's link the styles.css with the index.html file, we know that styles.css file is available at localhost:5555/styles.css.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="styles.css" /> <!--šŸ‘ˆ linking to styles.css -->
    <title>Home</title>
</head>
<body>
    <h1>Hello World :D</h1>
</body>
</html>

styles.css takes effect.

Serving at different route #

Till now we have been serving the files at the root route path (/). Let's try to serve files at another route /files, so basically when we enter the url localhost:5555/files we should see our index.html page.

Let's make the adjustments to the main.go file.

package main

import (
	"log"
	"net/http"
)

func main() {
	dir := http.Dir("./static")
	
	fs := http.FileServer(dir)

	mux := http.NewServeMux()

	mux.Handle("/files/", fs) // šŸ‘ˆ changing the route path

	err := http.ListenAndServe(":5555", mux)
	if err != nil {
		log.Fatal(err)
	}
}

āŒ If you try to run the above code and visit localhost:5555/files/ you will see a 404 Not Found page.

What is the issue? The file server tries to look for Directory Path + Route Path to serve files, so the path it is looking for becomes ./static/files/, which is wrong, our files are localted in the ./static folder. We need remove the /files/ when the route reaches the file server, GO provides a function called http.StripPrefix which will remove the specified prefix from a route before passing it on to another route handler.

package main

import (
	"log"
	"net/http"
)

func main() {
	dir := http.Dir("./static")

	fs := http.FileServer(dir)

	mux := http.NewServeMux()

	// šŸ‘‡ stripping the prefix `/files/`
	mux.Handle("/files/", http.StripPrefix("/files/", fs))

	err := http.ListenAndServe(":5555", mux)
	if err != nil {
		log.Fatal(err)
	}
}

Now if you visit localhost:5555/files/ you will see the index.html page and localhost:5555/files/styles.css will display the css file āœ….

  • File path before prefix removal šŸ‘‰ ./static/files/index.html.
  • File path after prefix removal šŸ‘‰ ./static/index.html.

There is still one thing wrong, our link to css files from index.html is broken, since we updated the path at which we are serving files at we need to update its usage as well.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/files/styles.css" /> <!--šŸ‘ˆ updating the path -->
    <title>Home</title>
</head>
<body>
    <h1>Hello World :D</h1>
</body>
</html>

Thank you for reading this article šŸ™šŸ», I hope you learned something from it!

Table of Contents
TheDeveloperCafe