介绍
Go语言自1.7版本起,标准库中提供了一个名为“net/http”的库,可以轻松地开发HTTP客户端和服务器。其中包含了许多有用的函数和类型,例如:HTTP服务器、客户端、Cookie、header等。本文将介绍如何使用HTTP服务器函数实现静态文件的下载。
实现静态文件下载
当用户向Web服务器发送HTTP请求时,HTTP服务器必须能够识别请求,分析请求,查找请求的文件或数据,然后返回数据。在Go语言中,可以使用以下函数开发HTTP服务器:
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
其中,"http.HandleFunc"函数是用来设置HTTP路由器,第一个参数是路由规则,即该路由被匹配时执行哪个函数。第二个参数是要处理的请求的处理器。而http.ListenAndServe则是我们需要创建的HTTP服务器。
接下来,我们需要实现一个handler函数,该函数用于处理客户端的HTTP请求,并读取和返回请求的静态文件。handler函数的代码如下:
func handler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path[1:]
if path == "" {
path = "index.html"
}
data, err := ioutil.ReadFile(path)
if err != nil {
http.NotFound(w, r)
return
}
http.ServeContent(w, r, "", time.Now(), bytes.NewReader(data))
}
代码中的第一行将HTTP请求的URL路径转换为文件路径的字符串。我们将从filepath包中使用函数来处理路径,以确保路径在所有操作系统上的兼容性。如果请求的URL路径为/,则默认返回index.html文件。接下来,我们使用ioutil包中的ReadFile函数来读取文件数据,如果遇到错误,则返回404错误。
最后,我们使用http.ServeContent函数来返回文件内容,该函数的参数分别为:响应Writer、请求、文件名、文件最后修改时间和文件数据的io.Reader。然后,我们将该函数用于handler函数。
为什么使用ServeContent而不使用ServeFile?
如果您熟悉Go语言中的net/http包,则可能会注意到该包中还提供了另一个函数,即http.ServeFile。该函数的功能与http.ServeContent函数类似。ServeFile函数的签名如下:
func ServeFile(w ResponseWriter, r *Request, name string)
该函数的功能是提供文件服务,将文件传输到客户端,指示Chrome/Edge/Firefox/ie/Opera浏览器下载。
然而,正如我们在文档中看到的那样,ServeFile存在一个严重的漏洞:一旦客户端发送一个返回指向服务器上敏感文件的请求,则可以访问该文件,即使该文件不在ServeFile的根目录中。这个漏洞是由于有人忘记了对文件名进行清理而导致的,从而在请求文件时使目录遍历成为可能(例如localhost:8080/../../etc/shadow)。这是一个危险的问题。
为此,我们建议在Go语言中使用http.ServeContent函数实现静态文件下载,以避免此漏洞。
运行程序
最后,我们需要编写主函数以启动Web服务器,并获取来自客户端的HTTP请求。代码如下:
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
运行程序,打开浏览器并输入"http://localhost:8080",您将看到网站目录的列表,您可以单击列表中的任何文件名以下载该文件。
总结
利用Go语言的"net/http"包,我们可以轻松地实现HTTP服务器。在本文中,我们展示了如何使用HTTP服务器函数实现静态文件的下载。我们提供了一个简单的处理程序,该程序能够处理从客户端接收到的文件并将其返回给客户端。通过此简单的应用程序,您可以了解如何使用Go语言实现HTTP服务器并处理HTTP请求。