I have looked around and cannot find a solution for what I have in hands at the moment.
I have a go project I am setting up (deployed into a docker image) and I have some HTML templating that needs to be done. The templating part works well using the embed declaration, however the same does not seem to work for the files that the HTML requires, e.g., css files.
Here is a simple example I have setup in order to try to play with embed and see what is going wrong, but no luck.
Project directory
|
|- main.go
\- templates
|- page.html
\- static
|- style.css
\- stylesheets
\- style.css (preferred location)
main.go
package main
import (
"embed"
"net/http"
"simple-server/handlers"
)
//go:embed templates
var templatesFs embed.FS
//go:embed templates/static
var staticFiles embed.FS
func main() {
http.Handle("/hello", handlers.HelloHandler{
TemplatesFs: templatesFs,
})
http.Handle(
"/static/",
// the following works
http.FileServer(http.Dir("./templates")),
// the following does not work
//http.StripPrefix("/static/", http.FileServer(http.FS(staticFiles))),
)
err := http.ListenAndServe(":8001", nil)
if err != nil {
panic(err)
}
}
hello.go
package handlers
import (
"embed"
"fmt"
"html/template"
"net/http"
)
type HelloHandler struct {
TemplatesFs embed.FS
}
func (h HelloHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
tmpl, err := template.ParseFS(h.TemplatesFs, "templates/page.html")
if err != nil {
fmt.Printf("failed to parse the template: %s", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
err = tmpl.ExecuteTemplate(w, "page.html", nil)
if err != nil {
fmt.Printf("failed to execute the template: %s", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
page.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/static/style.css">
<title>Session {{ .Number }}</title>
</head>
<body>
<div class="text">Page HTML template</div>
</body>
</html>
style.css
.text {
color: #0088ff;
}
As per the comment on the main.go
file, if the file is served through http.Dir
, it works. But this is going to be served through a docker file, so I need the http.FileServer(http.FS(staticFiles))
, however in doing so, the style.css
file always returns a 404.
Am I missing something? What is it?
Many thanks in advance 👍
It is probably taking relative path corresponding to where is it created and NOT the root of your embedded filesystem. So I feel the issue is at http.FS(staticFiles)
May be you can first create a fileSystem rooted at templates/static
, like following
staticFs, err := fs.Sub(staticFiles, "templates/static")
// Handle the err
and then do
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFs))))
Let me know if it works or not!