Servir la page d’accueil et le contenu statique à partir de la racine

Dans Golang, comment servir du contenu statique à partir du répertoire racine tout en ayant un gestionnaire de répertoire racine pour servir la page d’accueil.

Utilisez le serveur Web simple suivant comme exemple:

package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", HomeHandler) // homepage http.ListenAndServe(":8080", nil) } func HomeHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "HomeHandler") } 

Si je fais

 http.Handle("/", http.FileServer(http.Dir("./"))) 

Je reçois une panique en disant que j’ai deux inscriptions pour “/”. Chaque exemple de Golang trouvé sur Internet suggère de servir leur contenu statique à partir de différents répertoires, mais cela n’aide pas beaucoup pour des choses comme sitemap.xml, favicon.ico, robots.txt et d’autres fichiers qui sont des mandaté pour toujours être servi à partir de la racine.

Le comportement que je recherche est le comportement que l’on trouve dans la plupart des serveurs Web tels qu’Apache, Nginx ou IIS, où il traverse d’abord vos règles. Si aucune règle n’est trouvée, il recherche un fichier réel et si aucun fichier n’est trouvé 404s. Je pense qu’au lieu d’écrire un http.HandlerFunc , je dois écrire un http.Handler qui vérifie si je référence un fichier avec une extension, et si oui, vérifie l’existence du fichier et sert le fichier, sinon il 404s ou sert le page d’accueil est la demande était pour “/”. Malheureusement, je ne suis pas certain de savoir comment commencer une telle tâche.

Une partie de moi dit que je complique énormément la situation, ce qui me fait penser que je manque quelque chose? Toute orientation serait appréciée.

Une chose à laquelle je pensais pourrait vous aider à créer votre propre ServeMux. J’ai ajouté à votre exemple pour que chttp soit un ServeMux que vous pouvez servir des fichiers statiques. Le HomeHandler vérifie ensuite s’il doit ou non servir un fichier. Je vérifie juste un “.” mais vous pourriez faire beaucoup de choses. Juste une idée, pourrait ne pas être ce que vous recherchez.

 package main import ( "fmt" "net/http" "ssortingngs" ) 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 (ssortingngs.Contains(r.URL.Path, ".")) { chttp.ServeHTTP(w, r) } else { fmt.Fprintf(w, "HomeHandler") } } 

Une solution alternative (ne pas utiliser ServeMux ) consiste à fournir explicitement chaque fichier situé dans le répertoire racine. L’idée est de garder le nombre de fichiers basés sur la racine très petit. sitemap.xml , favicon.ico , robots.txt doivent en effet être diffusés depuis la racine:

 package main import ( "fmt" "net/http" ) func HomeHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "HomeHandler") } func serveSingle(pattern ssortingng, filename ssortingng) { 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) } 

Veuillez déplacer toutes les autres ressources (CSS, JS, etc.) dans un sous-répertoire approprié, par exemple /static/ .

En utilisant le paquetage Gorilla mux :

 r := mux.NewRouter() //put your regular handlers here //then comes root handler r.HandleFunc("/", homePageHandler) //if a path not found until now, eg "/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)