从根服务主页和静态内容

在Golang中,如何在根目录中提供静态内容,同时还有用于提供主页的根目录处理程序。

以下面简单的Web服务器为例:

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") } 

如果我做

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

我收到一个恐慌,说我有两个“/”的注册。 我在互联网上find的每个Golang示例都build议从不同目录中提供静态内容,但对于sitemap.xml,favicon.ico,robots.txt和其他文件被授权始终从根开始服务。

我所寻找的行为是在大多数Web服务器(如Apache,Nginx或IIS)中find的行为,它首先遍历规则,如果找不到规则,则查找实际文件,如果找不到文件404。 我的猜测是,而不是编写一个http.HandlerFunc ,我需要编写一个http.Handler ,检查是否引用一个扩展名的文件,如果是的话,检查文件的存在和服务的文件,否则404或服务主页是请求为“/”。 不幸的是,我不确定如何开始这样的任务。

我的一部分说,我大大过度复杂的情况,使我觉得我失去了一些东西? 任何指导将不胜感激。

我想到的一件事可能会帮助你,你可以创build自己的ServeMux。 我添加到您的示例,以便chttp是ServeMux,您可以提供静态文件。 HomeHandler然后检查是否应该提供文件。 我只是检查一个“。” 但是你可以做很多事情。 只是一个想法,可能不是你在找什么。

 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") } } 

另一种(不使用ServeMux )解决scheme是明确地提供位于根目录中的每个文件。 背后的想法是保持根文件的数量非常小。 sitemap.xml , favicon.ico , robots.txt的确被授权从根服务:

 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) } 

请将所有其他资源(CSS,JS等)移动到适当的子目录,例如/static/

使用大猩猩复合包 :

 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)