fiber
fiber copied to clipboard
🐛 [Bug]: staticConfig.FS won't accept http.FileSystem in v3
Bug Description
v3 removes the filesystem middleware and replaces it with static saying that static now does everything filesystem used to, however, you can't provide an http.FileSystem to the static.Config.FS parameter (what used to be 'Root'.
How to Reproduce
Steps to reproduce the behavior:
See the code snippets for a "v2 that works" and "v3 that doesn't" sample.
Expected Behavior
You should be able to replace filesystem.Config with static.Config without having to alter how you construct the embed you pass to it from an http.FileSystem to a non-http.FileSystem.
Template package Version
v3.0.0-beta.3
Code Snippet (optional)
Here's what worked in V2:
package main
import (
"fmt"
"log"
"os"
"embed"
"io/fs"
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/goccy/go-json"
)
// Embed the build directory from the frontend.
//go:embed public/*
var BuildFs embed.FS
// Get the subtree of the embedded files with `build` directory as a root.
func BuildHTTPFS() http.FileSystem {
public, err := fs.Sub(BuildFs, "public")
if err != nil {
log.Fatal(err)
}
return http.FS(public)
}
func handleHello(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"message": "hello from the fiber server"})
}
func main() {
app := fiber.New(fiber.Config{
JSONEncoder: json.Marshal,
JSONDecoder: json.Unmarshal,
})
app.Get("/*", filesystem.New(filesystem.Config{
Root: BuildHTTPFS(),
NotFoundFile: "404.html",
}))
app.Get("/hello.json", handleHello)
log.Fatal(app.Listen(fmt.Sprintf(":%s", os.Getenv("APP_PORT"))))
}
The minimal changes I expected based on docs (simply replace filesystem with static... NotFoundFile with NotFoundHandler, etc... won't compile):
package main
import (
"fmt"
"log"
"os"
"embed"
"io/fs"
"net/http"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/static"
"github.com/goccy/go-json"
)
// Embed the build directory from the frontend.
//go:embed public/*
var BuildFs embed.FS
// Get the subtree of the embedded files with `build` directory as a root.
func BuildHTTPFS() http.FileSystem {
public, err := fs.Sub(BuildFs, "public")
if err != nil {
log.Fatal(err)
}
return http.FS(public)
}
func handle404(c fiber.Ctx) error {
return c.JSON(fiber.Map{"message": "page not found"})
}
func handleHello(c fiber.Ctx) error {
return c.JSON(fiber.Map{"message": "hello from the fiber server"})
}
func main() {
app := fiber.New(fiber.Config{
JSONEncoder: json.Marshal,
JSONDecoder: json.Unmarshal,
})
app.Get("/*", static.New("", static.Config{
FS: BuildHTTPFS(),
NotFoundHandler: handle404,
}))
app.Get("/hello.json", handleHello)
log.Fatal(app.Listen(fmt.Sprintf(":%s", os.Getenv("APP_PORT"))))
}
Here's the error which references the "API change" that's not something I expected:
ss go run main.go v1.22.4 4m39s411ms
# command-line-arguments
./main.go:45:21: cannot use BuildHTTPFS() (value of type http.FileSystem) as fs.FS value in struct literal: http.FileSystem does not implement fs.FS (wrong type for method Open)
have Open(string) (http.File, error)
want Open(string) (fs.File, error)
### Checklist:
- [X] I agree to follow Fiber's [Code of Conduct](https://github.com/gofiber/fiber/blob/master/.github/CODE_OF_CONDUCT.md).
- [X] I have checked for existing issues that describe my problem prior to opening this one.
- [X] I understand that improperly formatted bug reports may be closed without explanation.
Moving to core, doesnt belong here.
Thanks for opening your first issue here! 🎉 Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord
@idearat Why not use BuildFs directly in static.Config, it's supported. What benefit you get from adding http.FileSystem?
@idearat any updates?
You can use fs.Sub directly without converting it to http.FS. New static middleware accepts fs.FS as FS config property. I don't think you need that part.
Tested, it works.
package main
import (
"embed"
"io/fs"
"log"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/static"
)
// Embed the build directory from the frontend.
//
//go:embed fiber/* fiber/public/*
var BuildFs embed.FS
// Get the subtree of the embedded files with `build` directory as a root.
func BuildHTTPFS() fs.FS {
public, err := fs.Sub(BuildFs, "fiber/public")
if err != nil {
log.Fatal(err)
}
return public
}
func main() {
app := fiber.New(fiber.Config{})
app.Get("/*", static.New("", static.Config{
FS: BuildHTTPFS(),
Browse: true,
}))
log.Fatal(app.Listen(":3000"))
}