Originally posted by @zikaeroh in #41191 (comment)
Trying this out now; one wart with the go:embed directive is that if I embed build/*, the filenames still have the prefix build/. If I want to then serve that directory via http.FS, there's no easy way to add the prefix that's required to access them if needed (without writing a wrapper, which then hits the problem of needing to list out every potential method that the FS may have...).
e.g.:
//go:embed build/*
var buildDir embed.FS
// Serve some SPA build dir as the app; oops, needs to be build/index.html
http.Handle("/", http.FileServer(http.FS(buildDir)))
// or
//go:embed static/*
var staticDir embed.FS
// Oops; needs to have a static prefix.
http.Handle("/static/*, http.StripPrefix("/static", http.FileServer(http.FS(staticDir))))
// Could be this, but only because the prefix happens to match:
http.Handle("/static/*, http.FileServer(http.FS(staticDir)))
I know the intent is that one could write go:embed foo/* bar/* baz.ext and get all of those files, but I think it's going to be very common to simply embed a directory and serve it as static assets via the http package. I expect this to be a gotcha as people switch from things like http.Dir("static") or pkger.Dir("/internal/web/static") where the prefix is already handled, to the new embed.FS.
I'm not really sure how to file this, as it's sort of an interplay with embed, io/fs, and net/http.
My comment on @zikaeroh's comment:
I think the best way to resolve this is by adding a general purpose fs.WithPrefix helper that creates a new FS that is restricted to the given subdirectory prefix. The example above would become:
//go:embed build/*
var buildDir embed.FS
http.Handle("/", http.FileServer(http.FS(fs.WithPrefix("build", buildDir))))
I think this should be in FS so that it can implement optional interfaces as they're invented. I think it will have general applicability for things like creating a zipfile FS and restricting it to a subdirectory and whatnot.
Originally posted by @zikaeroh in #41191 (comment)
Trying this out now; one wart with the
go:embeddirective is that if I embedbuild/*, the filenames still have the prefixbuild/. If I want to then serve that directory viahttp.FS, there's no easy way to add the prefix that's required to access them if needed (without writing a wrapper, which then hits the problem of needing to list out every potential method that the FS may have...).e.g.:
I know the intent is that one could write
go:embed foo/* bar/* baz.extand get all of those files, but I think it's going to be very common to simply embed a directory and serve it as static assets via the http package. I expect this to be a gotcha as people switch from things likehttp.Dir("static")orpkger.Dir("/internal/web/static")where the prefix is already handled, to the newembed.FS.I'm not really sure how to file this, as it's sort of an interplay with
embed,io/fs, andnet/http.My comment on @zikaeroh's comment:
I think the best way to resolve this is by adding a general purpose fs.WithPrefix helper that creates a new FS that is restricted to the given subdirectory prefix. The example above would become:
I think this should be in FS so that it can implement optional interfaces as they're invented. I think it will have general applicability for things like creating a zipfile FS and restricting it to a subdirectory and whatnot.