使用go静态文件服务器时,如何自定义处理找不到的文件? [英] How to custom handle a file not being found when using go static file server?

查看:80
本文介绍了使用go静态文件服务器时,如何自定义处理找不到的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我正在使用Go服务器来提供单个页面的Web应用程序.

So I'm using a go server to serve up a single page web application.

这适用于服务根路由上的所有资产.所有CSS和HTML均已正确提供.

This works for serving all the assets on the root route. All the CSS and HTML are served up correctly.

fs := http.FileServer(http.Dir("build"))
http.Handle("/", fs)

因此,当URL为http://myserverurl/index.htmlhttp://myserverurl/styles.css时,它将提供相应的文件.

So when the URL is http://myserverurl/index.html or http://myserverurl/styles.css, it serves the corresponding file.

但是对于http://myserverurl/myCustompage这样的URL,如果myCustompage不是构建文件夹中的文件,则会抛出404.

But for a URL like http://myserverurl/myCustompage, it throws 404 if myCustompage is not a file in the build folder.

如何使所有不存在文件的路由为index.html服务?

How do I make all routes for which a file does not exist serve index.html?

这是一个单页Web应用程序,一旦提供html和js,它将呈现适当的屏幕.但是index.html需要在没有文件的路由上提供.

It is a single page web application and it will render the appropriate screen once the html and js are served. But it needs index.html to be served on routes for which there is no file.

这怎么办?

推荐答案

http.FileServer() 不支持自定义,不支持提供自定义404页面或操作.

The handler returned by http.FileServer() does not support customization, it does not support providing a custom 404 page or action.

我们可以做的是包装http.FileServer()返回的处理程序,并且在我们的处理程序中,我们当然可以做我们想做的任何事情.在我们的包装处理程序中,我们将调用文件服务器处理程序,如果该处理程序将发送未找到的404响应,则不会将其发送到客户端,而是将其替换为重定向响应.

What we may do is wrap the handler returned by http.FileServer(), and in our handler we may do whatever we want of course. In our wrapper handler we will call the file server handler, and if that would send a 404 not found response, we won't send it to the client but replace it with a redirect response.

为此,我们在包装器中创建了一个包装器 http.ResponseWriter ,我们将传递给http.FileServer()返回的处理程序,在此包装响应编写器中,我们可以检查状态代码,如果它是404,我们可以采取行动 not 将响应发送给客户端,而是将重定向发送到/index.html.

To achieve that, in our wrapper we create a wrapper http.ResponseWriter which we will pass to the handler returned by http.FileServer(), and in this wrapper response writer we may inspect the status code, and if it's 404, we may act to not send the response to the client, but instead send a redirect to /index.html.

这是该包装器http.ResponseWriter看起来像的一个示例:

This is an example how this wrapper http.ResponseWriter may look like:

type NotFoundRedirectRespWr struct {
    http.ResponseWriter // We embed http.ResponseWriter
    status              int
}

func (w *NotFoundRedirectRespWr) WriteHeader(status int) {
    w.status = status // Store the status for our own use
    if status != http.StatusNotFound {
        w.ResponseWriter.WriteHeader(status)
    }
}

func (w *NotFoundRedirectRespWr) Write(p []byte) (int, error) {
    if w.status != http.StatusNotFound {
        return w.ResponseWriter.Write(p)
    }
    return len(p), nil // Lie that we successfully written it
}

包装http.FileServer()返回的处理程序可能如下所示:

And wrapping the handler returned by http.FileServer() may look like this:

func wrapHandler(h http.Handler) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        nfrw := &NotFoundRedirectRespWr{ResponseWriter: w}
        h.ServeHTTP(nfrw, r)
        if nfrw.status == 404 {
            log.Printf("Redirecting %s to index.html.", r.RequestURI)
            http.Redirect(w, r, "/index.html", http.StatusFound)
        }
    }
}

请注意,我使用的是http.StatusFound重定向状态代码,而不是http.StatusMovedPermanently,因为后者可能会被浏览器缓存,因此,如果稍后创建具有该名称的文件,浏览器将不会请求它,而是显示index.html立即.

Note that I used http.StatusFound redirect status code instead of http.StatusMovedPermanently as the latter may be cached by browsers, and so if a file with that name is created later, the browser would not request it but display index.html immediately.

现在使用main()函数:

func main() {
    fs := wrapHandler(http.FileServer(http.Dir(".")))
    http.HandleFunc("/", fs)
    panic(http.ListenAndServe(":8080", nil))
}

尝试查询不存在的文件,我们将在日志中看到这一点:

Attempting to query a non-existing file, we'll see this in the log:

2017/11/14 14:10:21 Redirecting /a.txt3 to /index.html.
2017/11/14 14:10:21 Redirecting /favicon.ico to /index.html.

请注意,我们的自定义处理程序(行为良好)也将请求重定向到/favico.icoindex.html,因为我的文件系统中没有favico.ico文件.如果您也没有,可以将其添加为例外.

Note that our custom handler (being well-behaviour) also redirected the request to /favico.ico to index.html because I do not have a favico.ico file in my file system. You may want to add this as an exception if you don't have it either.

完整的示例可在转到游乐场上找到.您无法在此处运行它,将其保存到本地Go工作区中并在本地运行.

The full example is available on the Go Playground. You can't run it there, save it to your local Go workspace and run it locally.

还要检查以下相关问题:在http.FileServer上登录404

Also check this related question: Log 404 on http.FileServer

这篇关于使用go静态文件服务器时,如何自定义处理找不到的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆