kataras / iris

The fastest HTTP/2 Go Web Framework. New, modern and easy to learn. Fast development with Code you control. Unbeatable cost-performance ratio :rocket:
https://www.iris-go.com
BSD 3-Clause "New" or "Revised" License
25.23k stars 2.47k forks source link

[FEATURE REQUEST]Does iris support 'embed' package in Go 1.16 release? #1730

Closed yuanzicheng closed 2 years ago

yuanzicheng commented 3 years ago

The currently released new version 1.16 of Go provide package embed, so we can embed files like *.html and others into the compiled binary executable file.

I want to know how iris works with embed package when serving static files.

yuanzicheng commented 3 years ago

I find out a solution to serve static files with 'embed' package, what we need to do is coverting embed.FS to http.FileSystem. Note that we need to strip off the directory prefix from the embed.FS with fs.Sub so that it matches what is produced by the os.DirFS.

Reference: how-to-use-go-embed

The below are the code: embed build folder (a react.js single page application) to embed.FS

//go:embed build
var build embed.FS

GetFileSystem function in tools package to convert embed.FS to http.FileSystem

package tools

import (
    "io/fs"
    "log"
    "net/http"
    "os"
)

// GetFileSystem ..
func GetFileSystem(useOS bool, dir string, fsys fs.FS) http.FileSystem {
    if useOS {
        log.Print("using live mode")
        return http.FS(os.DirFS(dir))
    }

    log.Print("using embed mode")
    fsys, err := fs.Sub(fsys, dir)
    if err != nil {
        panic(err)
    }

    return http.FS(fsys)
}

serving static files in iris

app.HandleDir("/", tools.GetFileSystem(false, "build", build), iris.DirOptions{
    IndexName: "index.html",
    ShowList:  false,
    SPA:       true,
})

But i have no idea how to use Localization feature with 'embed' package in Go 1.16, without using go-bindata, except for your reply!

bladewhite commented 3 years ago

This is my way, looking forward to a better way.

//go:embed web var embedWeb embed.FS

type webFS struct { FS embed.FS }

func (e *webFS) Asset(name string) ([]byte, error) { return e.FS.ReadFile(name) }

func (e *webFS) AssetInfo(name string) (fs.FileInfo, error) { file, err := e.FS.Open(name) if err != nil { return nil, err } return file.Stat() }

// file list manually func (e *webFS) AssetNames() []string { names := []string{ "web/index.html", "web/public/js/app.js", "web/public/css/app.css", } return names }


server := iris.New()

myWebFS := &webFS{FS: embedWeb}

server.HandleDir("/", "./web", iris.DirOptions{ Asset: myWebFS.Asset, AssetInfo: myWebFS.AssetInfo, AssetNames: myWebFS.AssetNames, })

Sloaix commented 3 years ago

Try my way.

first update your iris to master latest. go get github.com/kataras/iris/v12@master

then

        //go:embed dist/*
        var embedWeb embed.FS

    fsys, _ := fs.Sub(embedWeb, "dist")
    app.RegisterView(iris.HTML(http.FS(fsys), ".html"))
    app.HandleDir("/", http.FS(fsys))

That works for me.

Sloaix commented 3 years ago

better way:

        //go:embed dist/*
        var embedWeb embed.FS

    fsys := iris.PrefixDir("dist", http.FS(embedWeb))
    app.RegisterView(iris.HTML(fsys, ".html"))
    app.HandleDir("/", fsys)
yuanzicheng commented 3 years ago

@Sloaix your code is really much more concise and clean than mine! and i will have a check if it works correctly.
About the further question, do u know how can the Localization feature of Iris works with the 'embed' package in Go 1.16 release?

axetroy commented 3 years ago

here is my solution, works fine for me.

        {
            app.OnErrorCode(http.StatusNotFound, func(c *irisContext.Context) {
                req := c.Request()
                req.URL.Path = "/frontend/dist" + req.URL.Path
                println(req.URL.Path)
                fs := http.FileServer(http.FS(EmbedWeb))
                fs.ServeHTTP(c.ResponseWriter(), req)
            })
        }
huyinghuan commented 3 years ago

@axetroy thanks! It works fine.

kataras commented 2 years ago

Hello @yuanzicheng, @Sloaix , @bladewhite, @huyinghuan , @yuanzicheng, @axetroy

This is directly supported to view engines (e.g. app.RegisterView(iris.HTML(..))) and File Server (app.HandleDir).

Please update:

go get github.com/kataras/iris/v12@master
go mod tidy