programming

08 How to Understanding File Server in Golang

Introduction to File Server

Golang has a feature called FileServer. With this we can create a Handler in Golang Web that we have used as a static file server and this FileServer does not need to be manually loaded again. So we can add it to http.Server or http.ServeMux.

Apply to Project Handler

In the previous project we created a Handler that we can run. So we will try to change and add this FileServer to the handler that we have created.

We will fix the program in the main.go file to be like this.

func main() {
	directory := http.Dir("./resources")
	fileServer := http.FileServer(directory)

	mux := http.NewServeMux()
	mux.Handle("/static/", fileServer)

    ...
    ...
    ...

    server := http.Server{
		Addr:    "localhost:8080",
		Handler: mux,
	}

	err := server.ListenAndServe()
	if err != nil {
		panic(err)
	}
}

Make sure the program code runs well by building and running the program.

go build && ./learn-golang-web

If it is running we will try to access the URL path of our FileServer which we have added to the program.

http://localhost:8080/static

404 Not Found occurred

When our program runs and opens /static/index.html or /static/index.js a 404 Not found error occurs. Why did it happen? Because FileServer will read the URL and then look for the file based on the URL. For example, if we open /static/index.html, then FileServer will look for the file in /resources/static/index.html, if it is not found it will cause a 404 Not Found error. Therefore, we can use the http.StripPrefix() function to remove the prefix from the URL.

So we need to change the program code to be like this.

	mux.Handle("/static/", http.StripPrefix("/static", fileServer))

When we try to open the file again, the file we have created can automatically be accessed and opened by the browser.

Combining FileServer with Golang Embed

In the previous article we discussed Introduction to Embeded Implementation. So to get to know a folder and read all the files in that folder, we can also use Embed. So, then how do you do it?

First we will add this Embed to our program as below.

//go:embed resources
var resources embed.FS

func main() {
	fileServer := http.FileServer(http.FS(resources))

	mux := http.NewServeMux()
	mux.Handle("/static/", http.StripPrefix("/static", fileServer))

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "hello world")
	})

	mux.HandleFunc("/hi", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Hi")
	})

	mux.HandleFunc("/req", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, r.Method)
		fmt.Fprintln(w, r.RequestURI)
	})

	mux.HandleFunc("/set-cookie", SetCookieHandler)
	mux.HandleFunc("/get-cookie", GetCookieHandler)

	server := http.Server{
		Addr:    "localhost:8080",
		Handler: mux,
	}

	err := server.ListenAndServe()
	if err != nil {
		panic(err)
	}
}

Then we run our program and open the browser and re-access the URL we created earlier. If a 404 error occurs because Golang embed will read the folder name following the path of the URL so if we save it in the resources folder then to open the file in that folder we need to add the folder name to the URL path to be like this /static /resources/index.css.

And how do we not want to add the folder name to our web URL path? So, we can use the fs.Sub() function to get the sub directory.

	directory, _ := fs.Sub(resources, "resources")
	fileServer := http.FileServer(http.FS(directory))

Run the program that we have created again and open the browser and access the file path, so now the file can be opened without having to add a folder path name.

comments powered by Disqus