In Golang, how do I serve static content out of the root directory while still having a root directory handler for serving the homepage.
Use the following simple web
Using Gorilla mux package :
r := mux.NewRouter()
//put your regular handlers here
//then comes root handler
r.HandleFunc("/", homePageHandler)
//if a path not found until now, e.g. "/image/tiny.png"
//this will look at "./public/image/tiny.png" at filesystem
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./public/")))
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
One thing I thought of that might help you is that you can create your own ServeMux. I added to your example so that chttp is a ServeMux that you can have serve static files. The HomeHandler then checks to see if it should serve a file or not. I just check for a "." but you could do a lot of things. Just an idea, might not be what you are looking for.
package main
import (
"fmt"
"net/http"
"strings"
)
var chttp = http.NewServeMux()
func main() {
chttp.Handle("/", http.FileServer(http.Dir("./")))
http.HandleFunc("/", HomeHandler) // homepage
http.ListenAndServe(":8080", nil)
}
func HomeHandler(w http.ResponseWriter, r *http.Request) {
if (strings.Contains(r.URL.Path, ".")) {
chttp.ServeHTTP(w, r)
} else {
fmt.Fprintf(w, "HomeHandler")
}
}
An alternative (not using ServeMux) solution is to serve explicitly each file located in the root directory. The idea behind is to keep the number of root-based files very small. sitemap.xml, favicon.ico, robots.txt are indeed mandated to be served out of the root :
package main
import (
"fmt"
"net/http"
)
func HomeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "HomeHandler")
}
func serveSingle(pattern string, filename string) {
http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filename)
})
}
func main() {
http.HandleFunc("/", HomeHandler) // homepage
// Mandatory root-based resources
serveSingle("/sitemap.xml", "./sitemap.xml")
serveSingle("/favicon.ico", "./favicon.ico")
serveSingle("/robots.txt", "./robots.txt")
// Normal resources
http.Handle("/static", http.FileServer(http.Dir("./static/")))
http.ListenAndServe(":8080", nil)
}
Please move all other resources (CSS, JS, etc.) to a proper subdirectory, e.g. /static/
.