我们拥有:
http.HandleFunc("/smth", smthPage)
http.HandleFunc("/", homePage)
用户在尝试错误的URL时会看到一个普通的“未找到404页”。如何返回该情况的自定义页面?
关于大猩猩/mux的update 对于使用纯NET/HTTP软件包的人来说是可以的答案。
如果您使用大猩猩/Mux,则应使用类似的东西:
func main() {
r := mux.NewRouter()
r.NotFoundHandler = http.HandlerFunc(notFound)
}
并根据需要实现
func notFound(w http.ResponseWriter, r *http.Request)
。
我通常这样做:
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", homeHandler)
http.HandleFunc("/smth/", smthHandler)
http.ListenAndServe(":12345", nil)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
errorHandler(w, r, http.StatusNotFound)
return
}
fmt.Fprint(w, "welcome home")
}
func smthHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/smth/" {
errorHandler(w, r, http.StatusNotFound)
return
}
fmt.Fprint(w, "welcome smth")
}
func errorHandler(w http.ResponseWriter, r *http.Request, status int) {
w.WriteHeader(status)
if status == http.StatusNotFound {
fmt.Fprint(w, "custom 404")
}
}
我选择的方法是遵循的方法。它是基于代码段,因为我丢失了浏览器书签,因此我无法承认。
样本代码:(我将其放在我的主包中)
errorHandler
求职自定义
type hijack404 struct {
http.ResponseWriter
R *http.Request
Handle404 func (w http.ResponseWriter, r *http.Request) bool
}
func (h *hijack404) WriteHeader(code int) {
if 404 == code && h.Handle404(h.ResponseWriter, h.R) {
panic(h)
}
h.ResponseWriter.WriteHeader(code)
}
func Handle404(handler http.Handler, handle404 func (w http.ResponseWriter, r *http.Request) bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
hijack := &hijack404{ ResponseWriter:w, R: r, Handle404: handle404 }
defer func() {
if p:=recover(); p!=nil {
if p==hijack {
return
}
panic(p)
}
}()
handler.ServeHTTP(hijack, r)
})
}
func fire404(res http.ResponseWriter, req *http.Request) bool{
fmt.Fprintf(res, "File not found. Please check to see if your URL is correct.");
return true;
}
func main(){
handler_statics := http.StripPrefix("/static/", http.FileServer(http.Dir("/Path_To_My_Static_Files")));
var v_blessed_handler_statics http.Handler = Handle404(handler_statics, fire404);
http.Handle("/static/", v_blessed_handler_statics);
// add other handlers using http.Handle() as necessary
if err := http.ListenAndServe(":8080", nil); err != nil{
log.Fatal("ListenAndServe: ", err);
}
}
func fire404
如果我只是一个新手,请谨校正代码。谢谢
我认为干净的方式是:
func main(){
handler_statics := http.StripPrefix("/static/", http.FileServer(http.Dir("/Path_To_My_Static_Files")));
var v_blessed_handler_statics http.Handler = Handle404(handler_statics, fire404);
r := mux.NewRouter();
r.PathPrefix("/static/").Handler(v_blessed_handler_statics);
// add other handlers with r.HandleFunc() if necessary...
http.Handle("/", r);
log.Fatal(http.ListenAndServe(":8080", nil));
}
如果地址不是 /calulator或 /历史记录,则它可以处理NotFoundHandler函数。
随机线程,但我只是做了一些要拦截的线程,在这里可能很重要。func main() {
http.HandleFunc("/calculator", calculatorHandler)
http.HandleFunc("/history", historyHandler)
http.HandleFunc("/", notFoundHandler)
log.Fatal(http.ListenAndServe(":80", nil))
}
http://golang.org/src/pkg/net/http/server.go
IT似乎几乎不可能指定Custo notfound()函数:notfoundhandler()返回一个名为notfound()的硬编码函数。
可能,您应该在此提交一个问题。
为了解决方法,您可以使用“/”处理程序,如果找不到其他处理程序(因为它是最短的),这将是后备。因此,该处理程序中存在检查页面并返回自定义404错误。您只需要创建自己的未发现处理程序,然后用thangefunc注册它,以确保您不处理的路径。
如果您需要对路由逻辑的最大控制权,则需要使用自定义服务器和自己的自定义处理程序类型。
Http://golang.org/pkg/net/http/#handler
简而言之,只需检查R.URL.Path是否匹配您期望找到的URL,例如通过循环浏览一系列页面即可。 Requiring an exact URL match, you avoid the catchall problem pointed out by @RomaH
现在我在一个称为drawpage的函数中执行此操作:
package main
//GAE POC originally inspired by https://thornelabs.net/2017/03/08/use-google-app-engine-and-golang-to-host-a-static-website-with-same-domain-redirects.html
import (
"net/http"
)
func init() {
http.HandleFunc("/", handler)
}
// HeaderWriter is a wrapper around http.ResponseWriter which manipulates headers/content based on upstream response
type HeaderWriter struct {
original http.ResponseWriter
done bool
}
func (hw *HeaderWriter) Header() http.Header {
return hw.original.Header()
}
func (hw *HeaderWriter) Write(b []byte) (int, error) {
if hw.done {
//Silently let caller think they are succeeding in sending their boring 404...
return len(b), nil
}
return hw.original.Write(b)
}
func (hw *HeaderWriter) WriteHeader(s int) {
if hw.done {
//Hmm... I don't think this is needed...
return
}
if s < 400 {
//Set CC header when status is < 400...
//TODO: Use diff header if static extensions
hw.original.Header().Set("Cache-Control", "max-age=60, s-maxage=2592000, public")
}
hw.original.WriteHeader(s)
if s == 404 {
hw.done = true
hw.original.Write([]byte("This be custom 404..."))
}
}
func handler(w http.ResponseWriter, r *http.Request) {
urls := map[string]string{
"/example-post-1.html": "https://example.com/post/example-post-1.html",
"/example-post-2.html": "https://example.com/post/example-post-2.html",
"/example-post-3.html": "https://example.com/post/example-post-3.html",
}
w.Header().Set("Strict-Transport-Security", "max-age=15768000")
//TODO: Put own logic
if value, ok := urls[r.URL.Path]; ok {
http.Redirect(&HeaderWriter{original: w}, r, value, 301)
} else {
http.ServeFile(&HeaderWriter{original: w}, r, "static/"+r.URL.Path)
}
}
last部分取自 @许晨峰
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/" {
writer.WriteHeader(404)
writer.Write([]byte(`not found, da xiong dei !!!`))
return
}
})
您可以简单地使用以下内容:
is404 := true // assume the worst
// start loop through a data structure of all my pages
if (r.URL.Path == data.Options[i].URL) { is404 = false }
// end loop
if is404 { // failed our test
w.WriteHeader(404)
w.Write([]byte(`404 not found`))
return
}
// draw the page we found
如果您需要获得标准,只需写:
http.HandleFunc("/smth", smthPage)
http.HandleFunc("/{$}", homePage) // {$} represents the end of the URL
http.HandleFunc("/", custom404Page)
你会得到:
func Handle404(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "404 error\n")
}
func main(){
http.HandleFunc("/", routes.Handle404)
}