I am running this command "go run webapp/main.go." The reason is that app engine will call my app from the root directory, so I changed the paths to work from calling the file from root. I also do not mind if you have Go best practices tips.
└── webapp
├── app.yaml
├── assets
│ ├── css
│ │ └── index.css
│ └── img
├── main.go
├── main_test.go
└── templates
└── index.html
Confused on how something so trivial can be wrong. localhost:8080/css/index.css works fine. I also have another handler function to serve localhost:8080/static/css/index.css, but I get a 404 error. Everything was working smoothly when I was using the command "go run main.go" and remove "webapp" from the code. Still, how can it work with / and not /static/. As can be seen in this https://stackoverflow.com/a/47997908/6828897 answer, it should serve ./webapp/assets/static as a dir. I also have tried http.StripPrefix but no luck either.
package main
import (
"flag"
"log"
"net/http"
"os"
"path/filepath"
"sync"
"text/template"
)
type templateHandler struct {
once sync.Once
filename string
templ *template.Template
}
// ServeHTTP handles the HTTP request.
func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
t.once.Do(func() {
t.templ = template.Must(template.ParseFiles(filepath.Join("webapp", "templates", t.filename)))
})
if err := t.templ.Execute(w, r); err != nil {
log.Printf("Error executing template: %v", err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
}
}
func main() {
dir, err := os.Getwd()
if err != nil {
log.Printf(err.Error())
}
log.Printf("dir: %s", dir)
// command flags
var addr = flag.String("addr", ":8080", "The addr of the application.")
flag.Parse()
// env variables
envPort := os.Getenv("PORT")
if envPort != "" {
envPort = ":" + envPort
addr = &envPort
}
fs := http.FileServer(http.Dir("./webapp/assets"))
http.Handle("/static/", fs)
log.Printf("Listening on port %s", *addr)
// http.Handle("/", &templateHandler{filename: "index.html"})
if err := http.ListenAndServe(*addr, fs); err != nil {
log.Fatal(err)
}
}
"how can it work with / and not /static/"
Because you are passing
fs
directly toListenAndServe
, that means that theDefaultServeMux
which is used byhttp.Handle("/static/", fs)
is being ignored / overridden.http.Handle
:http.ListenAndServe
So in general what you should do is something like this:
If there are other issues in your setup it is possible that your app may not work as desired right away, however this change is certainly a requirement to get closer to that goal.