Search code examples
gohttpstatic-files

Go web endpoint does not find static index.html file


This is my code:

package main

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

const customPort = "3001"

func main() {
    fileServer := http.FileServer(http.Dir("./static"))
    port:= fmt.Sprintf(":%s", customPort)
    http.Handle("/", fileServer)

    fmt.Printf("Starting front end service on port %s", port)
    err := http.ListenAndServe(port, nil)
    if err != nil {
        log.Panic(err)
    }
}

The top level folder is microservices and is set up as a go workspace. This web service will be one of many services. It is in the following folder:

microservices
 |--frontend
    |--cmd
       |--web
          |--static
             |--index.html
       |--main.go

I am in the top level microservices folder, and I am starting it with: go run ./frontend/cmd/web. It starts up fine with no errors. But when I go to chrome and type http://localhost:3001 I get 404 page not found. Even http://localhost:3001/index.html gives 404 page not found. I am just learning go and not sure why it is not finding the ./static folder?


Solution

  • According to your command the path has to be ./frontend/cmd/web/static, not just ./static. That's not portable; the path changes with the working directory.

    Consider embedding the static directory instead. Otherwise you'll have to make the path configurable (flag, environment variable, etc.)

    The downside with embedding is that you have to rebuild your program after any change to the static files.

    You can also use a hybrid approach. If the flag (or whatever) is set, use it to serve from disk, else use the embedded filesystem. The flag is convenient during development and the embedded filesystem makes deployment easy because you only have to copy the program binary.

    package main
    
    import (
        "embed"
        "flag"
        "io/fs"
        "net/http"
        "os"
    )
    
    //go:embed web/static
    var embeddedAssets embed.FS
    
    func main() {
        var staticDir string
    
        flag.StringVar(&staticDir, "static-dir", staticDir, "Path to directory containing static assets. If empty embedded assets are used.")
        flag.Parse()
    
        var staticFS fs.FS = embeddedAssets
        if staticDir != "" {
            staticFS = os.DirFS(staticDir)
        }
    
        http.Handle("/", http.FileServer(http.FS(staticFS)))
    
        // ...
    }