I have a go project which uses VueJS
to provide web interface. While build the project, I first use npm run build
to compile the frontend code, which is generated under gui/dist
of my project dir. Then I use this code to serve the static contents:
//go:embed gui/dist/*
var dist embed.FS
gui := http.FileServer(http.FS(dist))
http.Handle("/", gui)
http.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
msg := fmt.Sprintf("TODO: %s", r.URL)
http.Error(w, msg, http.StatusNotImplemented)
})
svr := http.Server{
Addr: fmt.Sprintf(":%v", cf.HTTPPort),
ReadTimeout: time.Minute,
WriteTimeout: time.Minute,
}
assert(svr.ListenAndServe())
The problem is, when open the site in browser, it shows me a browse file interface, i.e. starting with gui, and then into dist, then shows the index.html
file, which is a blank page, because it requires files such as /css/...
, while the go web server serves it at /gui/dist/css/...
.
I tried to use http.StripPrefix()
but apparently it is not intended to handle this situation, or I didn't use it correctly:
http.Handle("/", http.StripPrefix("/gui/dist", gui))
which generated a 404 page not found
.
In Go 1.16 version, using package “embed” we can easily embed files in Go programs. The embed file content variable should be of type string, []byte, or FS only. And running the program using beta version of Go 1.16. go1.16beta1 run embed-file.go //OUTPUT Hello, Gophers! Reading file content in bytes format.
In Go 1.16, StripPrefix trims both fields. If there are escaped characters in the prefix part of the request URL the handler serves a 404 instead of its previous behavior of invoking the underlying handler with a mismatched Path / RawPath pair.
The new Golang v1.16 embed directive helps us keep a single binary and bundle out static content. This post will cover how to work with embed directive by applying it to a demo application. One of the benefits of using Go is having your application compiled into a single self-contained binary.
One of the most anticipated features of Go 1.16 is the support for embedding files and folders into the application binary at compile-time without using an external tool. This feature is also known as go:embed, and it gets its name from the compiler directive that makes this functionality possible: //go:embed.
You may use fs.Sub(dist, "gui/dist")
(docs), try it:
package main
import (
"embed"
"fmt"
"io/fs"
"log"
"net/http"
)
func main() {
http.Handle("/", http.FileServer(getFileSystem()))
http.HandleFunc("/api/", api)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
}
func getFileSystem() http.FileSystem {
fsys, err := fs.Sub(dist, "gui/dist")
if err != nil {
log.Fatal(err)
}
return http.FS(fsys)
}
func api(w http.ResponseWriter, r *http.Request) {
msg := fmt.Sprintf("TODO: %s", r.URL)
http.Error(w, msg, http.StatusNotImplemented)
}
//go:embed gui/dist/*
var dist embed.FS
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With