英文:
Golang serve homepage and serve templated pages
问题
我可以帮你翻译这段代码。以下是翻译的结果:
package main
import (
"html/template"
"log"
"net/http"
"os"
"path"
)
func main() {
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
http.HandleFunc("/", serveTemplate)
http.HandleFunc("/file", serveFile) // 添加处理单个HTML文件的处理函数
log.Println("Listening...")
http.ListenAndServe(":5000", nil)
}
func serveTemplate(w http.ResponseWriter, r *http.Request) {
lp := path.Join("templates", "layout.html")
fp := path.Join("templates", r.URL.Path)
// 如果模板不存在,返回404错误
info, err := os.Stat(fp)
if err != nil {
if os.IsNotExist(err) {
http.NotFound(w, r)
return
}
}
// 如果请求的是目录,返回404错误
if info.IsDir() {
http.NotFound(w, r)
return
}
templates, err := template.ParseFiles(lp, fp)
if err != nil {
log.Print(err)
http.Error(w, "500 Internal Server Error", 500)
return
}
templates.ExecuteTemplate(w, "layout", nil)
}
func serveFile(w http.ResponseWriter, r *http.Request) {
// 处理单个HTML文件的逻辑
// 你可以在这里添加你的代码
}
这段代码在原有的基础上添加了一个名为serveFile
的处理函数,用于处理单个HTML文件的逻辑。你可以在serveFile
函数中添加你需要的代码。同时,你需要在main
函数中添加http.HandleFunc("/file", serveFile)
这一行,以将该处理函数与对应的URL路径关联起来。这样,当访问/file
时,就会调用serveFile
函数来处理请求。希望这能帮到你!
英文:
I'm looking to have a static landing page at url="/" and then have any files url="/"+file be served using a template.
I have the template working fine with this code
package main
import (
"html/template"
"log"
"net/http"
"os"
"path"
)
func main() {
fs := http.FileServer(http.Dir("static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
http.HandleFunc("/", serveTemplate)
log.Println("Listening...")
http.ListenAndServe(":5000", nil)
}
func serveTemplate(w http.ResponseWriter, r *http.Request) {
lp := path.Join("templates", "layout.html")
fp := path.Join("templates", r.URL.Path)
// Return a 404 if the template doesn't exist
info, err := os.Stat(fp)
if err != nil {
if os.IsNotExist(err) {
http.NotFound(w, r)
return
}
}
// Return a 404 if the request is for a directory
if info.IsDir() {
http.NotFound(w, r)
return
}
templates, err := template.ParseFiles(lp, fp)
if err != nil {
log.Print(err)
http.Error(w, "500 Internal Server Error", 500)
return
}
templates.ExecuteTemplate(w, "layout", nil)
}
So this works fine. Basically, I think I need to do two things. One, add another http.Handle or http.HandlerFunc in my main() function which handles a single html file, and then have my error checkers to redirect there instead of throwing a 404 error.
Please help how I may do this or provide a better solution?
答案1
得分: 2
我建议阅读:http://golang.org/doc/articles/wiki/#tmp_6 - 它涵盖了很多内容。
具体来说:
- 每次请求读取文件系统时都会阻塞(不好!);
- 然后在每次请求时解析模板文件(慢);
- 直接从URL路径中读取文件系统是一个巨大的安全问题(即使Go试图转义它,也要预料到有人会攻破它)。对此要非常小心。
你还应该在程序启动时解析模板(即在main()
的开始处)只解析一次。使用tmpl := template.Must(template.ParseGlob("/dir"))
提前从目录中读取所有模板,这样你就可以从路由中查找模板了。html/template文档对此有很好的介绍。
请注意,你需要编写一些逻辑来捕获在处理程序中找不到要匹配的模板的情况。
如果你想要更多功能,我还建议使用gorilla/mux。你可以编写一个未找到处理程序,它会使用302(临时重定向)将请求重定向到/
,而不是返回404。
r := mux.NewRouter()
r.HandleFunc("/:name", nameHandler)
r.HandleFunc("/", rootHandler)
r.NotFoundHandler(redirectToRoot)
http.Handle("/", r)
log.Fatal(http.ListenAndServe(":8000", nil))
func redirectToRoot(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusSeeOther)
}
希望对你有所帮助。
英文:
I'd suggest reading through: http://golang.org/doc/articles/wiki/#tmp_6 - it covers much of this.
Specifically:
- You are blocking on every request to read the file system (bad!);
- You're then parsing your template files (slow) on every request;
- Using a part of the URL path to directly read from the filesystem is a huge security problem (even if Go tries to escape it, expect someone to beat it). Be very careful about this
You should also parse your templates during program startup (i.e. at the start of your main()
) once only. Read all the templates in ahead of time from a dir using tmpl := template.Must(template.ParseGlob("/dir"))
- which will allow you to look-up your templates from your route. The html/template docs cover this well.
Note that you'll need to write some logic to catch when a template you are trying to match from the route does not exist in your handler.
I'd also look at using gorilla/mux if you want a few more features. You could write a not found handler that re-directs to /
with a 302 (temp. re-direct) instead of raising a 404.
r := mux.NewRouter()
r.HandleFunc("/:name", nameHandler)
r.HandleFunc("/", rootHandler)
r.NotFoundHandler(redirectToRoot)
http.Handle("/", r)
log.Fatal(http.ListenAndServe(":8000", nil))
func redirectToRoot(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusSeeOther)
}
Hope that helps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论