英文:
Using FileServer to serve my single html page
问题
我正在尝试构建一个示例的Web应用程序,使用Go作为后端,演示REST技术。后端服务处理基于JSON的请求,前端使用JavaScript和jQuery(我没有使用html/template包)。
FileServer函数“返回一个处理程序,该处理程序使用以root为根的文件系统的内容来提供HTTP请求”。
假设我发布了一个包含index.html和scripts文件夹(其中包含一些JavaScript文件)的static文件夹。
我该如何防止客户端查看我的JavaScript文件(只发布index.html在/路径下)?
英文:
I'm trying to build a sample web application demonstrating [tag:rest] techniques using [tag:go] at the back-end, serving [tag:json] based requests and [tag:javascript], [tag:jquery] in the front-end (I'm not using html/template
package).
FileServer "returns a handler that serves HTTP requests with the contents of the file system rooted at root."
supose that I'm publishing my static
folder that contains index.html
and scripts
folder holding some javascript
files.
How can I prevent the client from viewing my js
files (publishing just the index.html
at /
) ?
答案1
得分: 6
你可以通过在FileServer
周围包装另一个HttpHandler
来轻松限制FileServer
的功能。例如,可以使用以下包装器,仅允许提供*.js
文件:
func GlobFilterHandler(h http.Handler, pattern string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
fileName := filepath.Base(path)
if ok, err := filepath.Match(pattern, fileName); !ok || err != nil {
if err != nil {
log.Println("Error in pattern match:", err)
}
http.NotFound(w, r)
return
}
h.ServeHTTP(w, r)
})
}
func main() {
fileHandler := http.FileServer(http.Dir("/tmp/dtest"))
wrappedHandler := GlobFilterHandler(fileHandler, "*.js")
}
你可以在这里找到一篇博文,其中很好地描述了基本思想。
另一个选择是扩展http.Dir
并创建自己的http.FileSystem
实现,以实现你想要的功能:
type GlobDir struct {
Dir http.Dir
Pattern string
}
func (d GlobDir) Open(name string) (http.File, error) {
baseName := filepath.Base(name)
if ok, err := filepath.Match(d.Pattern, baseName); !ok || err != nil {
if err != nil {
return nil, err
}
return nil, fmt.Errorf("%s不匹配GlobDir模式。", baseName)
}
return d.Dir.Open(name)
}
func main() {
fileHandler := http.FileServer(GlobDir{
Dir: http.Dir("/tmp/dtest"),
Pattern: "*.js",
})
http.ListenAndServe(":8080", fileHandler)
}
第二种解决方案实现了http.FileSystem
接口,该接口被http.FileServer
接受。
它检查输入的文件名是否与提供的模式匹配,然后将控制权传递给原始的http.Dir
。这可能是你想要的方式。
英文:
You can easily restrict the FileServer
, which is a HttpHandler
by wrapping another HttpHandler
around that. For example, take this wrapper which ONLY allows *.js
files to be served:
func GlobFilterHandler(h http.Handler, pattern string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
fileName := filepath.Base(path)
if ok, err := filepath.Match(pattern, fileName); !ok || err != nil {
if err != nil {
log.Println("Error in pattern match:", err)
}
http.NotFound(w, r)
return
}
h.ServeHTTP(w, r)
})
}
func main() {
fileHandler := http.FileServer(http.Dir("/tmp/dtest"))
wrappedHandler := GlobFilterHandler(fileHandler, "*.js")
}
You can find a blog post here which describes the basic idea pretty good.
Another option you have is to extend on http.Dir
and make your own http.FileSystem
implementation which does exactly what you want:
type GlobDir struct {
Dir http.Dir
Pattern string
}
func (d GlobDir) Open(name string) (http.File, error) {
baseName := filepath.Base(name)
if ok, err := filepath.Match(d.Pattern, baseName); !ok || err != nil {
if err != nil {
return nil, err
}
return nil, fmt.Errorf("%s not match GlobDir pattern.", baseName)
}
return d.Dir.Open(name)
}
func main() {
fileHandler := http.FileServer(GlobDir{
Dir: http.Dir("/tmp/dtest"),
Pattern: "*.js",
})
http.ListenAndServe(":8080", fileHandler)
}
The second solution implements the http.FileSystem
interface which is accepted by http.FileServer
.
It checks whether the input file name matches the supplied pattern and then hands control down to the original http.Dir
. This is probably the way you want to go here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论