mirror of
https://github.com/kataras/iris.git
synced 2026-01-08 20:41:57 +00:00
Release of version 10.4.0 - x8 faster embedded file server | Star and Read HISTORY.md
Former-commit-id: 4f8b8c95c1b107a9be3b1ef6835ece949a75ceb6
This commit is contained in:
@@ -627,18 +627,6 @@ func (api *APIBuilder) StaticContent(reqPath string, cType string, content []byt
|
||||
return api.registerResourceRoute(reqPath, h)
|
||||
}
|
||||
|
||||
// StaticEmbeddedHandler returns a Handler which can serve
|
||||
// embedded into executable files.
|
||||
//
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
func (api *APIBuilder) StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) context.Handler {
|
||||
// Notes:
|
||||
// This doesn't need to be APIBuilder's scope,
|
||||
// but we'll keep it here for consistently.
|
||||
return StaticEmbeddedHandler(vdir, assetFn, namesFn)
|
||||
}
|
||||
|
||||
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
|
||||
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
|
||||
// Second parameter is the (virtual) directory path, for example "./assets"
|
||||
@@ -647,8 +635,25 @@ func (api *APIBuilder) StaticEmbeddedHandler(vdir string, assetFn func(name stri
|
||||
//
|
||||
// Returns the GET *Route.
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/file-server/embedding-files-into-app
|
||||
func (api *APIBuilder) StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) *Route {
|
||||
return api.staticEmbedded(requestPath, vdir, assetFn, namesFn, false)
|
||||
}
|
||||
|
||||
// StaticEmbeddedGzip registers a route which can serve embedded gziped files
|
||||
// that are embedded using the https://github.com/kataras/bindata tool and only.
|
||||
// It's 8 times faster than the `StaticEmbeddedHandler` with `go-bindata` but
|
||||
// it sends gzip response only, so the client must be aware that is expecting a gzip body
|
||||
// (browsers and most modern browsers do that, so you can use it without fair).
|
||||
//
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/file-server/embedding-gziped-files-into-app
|
||||
func (api *APIBuilder) StaticEmbeddedGzip(requestPath string, vdir string, gzipAssetFn func(name string) ([]byte, error), gzipNamesFn func() []string) *Route {
|
||||
return api.staticEmbedded(requestPath, vdir, gzipAssetFn, gzipNamesFn, true)
|
||||
}
|
||||
|
||||
// look fs.go#StaticEmbeddedHandler
|
||||
func (api *APIBuilder) staticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string, assetsGziped bool) *Route {
|
||||
fullpath := joinPath(api.relativePath, requestPath)
|
||||
// if subdomain,
|
||||
// here we get the full path of the path only,
|
||||
@@ -656,9 +661,10 @@ func (api *APIBuilder) StaticEmbedded(requestPath string, vdir string, assetFn f
|
||||
// and we need that path to call the `StripPrefix`.
|
||||
_, fullpath = splitSubdomainAndPath(fullpath)
|
||||
|
||||
requestPath = joinPath(fullpath, WildcardParam("file"))
|
||||
paramName := "file"
|
||||
requestPath = joinPath(requestPath, WildcardParam(paramName))
|
||||
|
||||
h := api.StaticEmbeddedHandler(vdir, assetFn, namesFn)
|
||||
h := StaticEmbeddedHandler(vdir, assetFn, namesFn, assetsGziped)
|
||||
|
||||
if fullpath != "/" {
|
||||
h = StripPrefix(fullpath, h)
|
||||
@@ -745,16 +751,17 @@ func (api *APIBuilder) Favicon(favPath string, requestPath ...string) *Route {
|
||||
//
|
||||
// Returns the GET *Route.
|
||||
func (api *APIBuilder) StaticWeb(requestPath string, systemPath string) *Route {
|
||||
paramName := "file"
|
||||
|
||||
fullpath := joinPath(api.relativePath, requestPath)
|
||||
|
||||
// if subdomain,
|
||||
// here we get the full path of the path only,
|
||||
// because a subdomain can have parties as well
|
||||
// and we need that path to call the `StripPrefix`.
|
||||
_, fullpath = splitSubdomainAndPath(fullpath)
|
||||
|
||||
requestPath = joinPath(fullpath, WildcardParam(paramName))
|
||||
paramName := "file"
|
||||
requestPath = joinPath(requestPath, WildcardParam(paramName))
|
||||
|
||||
h := NewStaticHandlerBuilder(systemPath).Listing(false).Build()
|
||||
|
||||
if fullpath != "/" {
|
||||
|
||||
@@ -21,12 +21,11 @@ import (
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
// StaticEmbeddedHandler returns a Handler which can serve
|
||||
// embedded into executable files.
|
||||
//
|
||||
// StaticEmbeddedHandler returns a Handler which can serve embedded files
|
||||
// that are embedded using the go-bindata tool(assetsGziped = false) or the kataras/bindata tool (assetsGziped = true).
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) context.Handler {
|
||||
func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string, assetsGziped bool) context.Handler {
|
||||
// Depends on the command the user gave to the go-bindata
|
||||
// the assset path (names) may be or may not be prepended with a slash.
|
||||
// What we do: we remove the ./ from the vdir which should be
|
||||
@@ -63,6 +62,7 @@ func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error
|
||||
|
||||
modtime := time.Now()
|
||||
h := func(ctx context.Context) {
|
||||
|
||||
reqPath := strings.TrimPrefix(ctx.Request().URL.Path, "/"+vdir)
|
||||
// i.e : /css/main.css
|
||||
|
||||
@@ -80,9 +80,17 @@ func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error
|
||||
|
||||
buf, err := assetFn(path) // remove the first slash
|
||||
|
||||
if assetsGziped {
|
||||
// this will add the "Vary" : "Accept-Encoding"
|
||||
// and "Content-Encoding": "gzip"
|
||||
// headers.
|
||||
context.AddGzipHeaders(ctx.ResponseWriter())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ctx.ContentType(cType)
|
||||
if _, err := ctx.WriteWithExpiration(buf, modtime); err != nil {
|
||||
ctx.StatusCode(http.StatusInternalServerError)
|
||||
@@ -93,7 +101,6 @@ func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error
|
||||
|
||||
// not found or error
|
||||
ctx.NotFound()
|
||||
|
||||
}
|
||||
|
||||
return h
|
||||
@@ -140,6 +147,7 @@ type fsHandler struct {
|
||||
// user options, only directory is required.
|
||||
directory http.Dir
|
||||
listDirectories bool
|
||||
gzip bool
|
||||
// these are init on the Build() call
|
||||
filesystem http.FileSystem
|
||||
once sync.Once
|
||||
@@ -183,18 +191,17 @@ func NewStaticHandlerBuilder(dir string) StaticHandlerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
// Gzip if enable is true then gzip compression is enabled for this static directory
|
||||
// Defaults to false
|
||||
// Gzip if enable is true then gzip compression is enabled for this static directory.
|
||||
//
|
||||
// Defaults to false.
|
||||
func (w *fsHandler) Gzip(enable bool) StaticHandlerBuilder {
|
||||
w.begin = append(w.begin, func(ctx context.Context) {
|
||||
ctx.Gzip(true)
|
||||
ctx.Next()
|
||||
})
|
||||
w.gzip = enable
|
||||
return w
|
||||
}
|
||||
|
||||
// Listing turn on/off the 'show files and directories'.
|
||||
// Defaults to false
|
||||
//
|
||||
// Defaults to false.
|
||||
func (w *fsHandler) Listing(listDirectoriesOnOff bool) StaticHandlerBuilder {
|
||||
w.listDirectories = listDirectoriesOnOff
|
||||
return w
|
||||
@@ -243,9 +250,15 @@ func (w *fsHandler) Build() context.Handler {
|
||||
|
||||
// Note the request.url.path is changed but request.RequestURI is not
|
||||
// so on custom errors we use the requesturi instead.
|
||||
// this can be changed
|
||||
// this can be changed.
|
||||
|
||||
// take the gzip setting.
|
||||
gzipEnabled := w.gzip
|
||||
if !gzipEnabled {
|
||||
// if false then check if the dev did something like `ctx.Gzip(true)`.
|
||||
_, gzipEnabled = ctx.ResponseWriter().(*context.GzipResponseWriter)
|
||||
}
|
||||
|
||||
_, gzipEnabled := ctx.ResponseWriter().(*context.GzipResponseWriter)
|
||||
_, prevStatusCode := serveFile(ctx,
|
||||
w.filesystem,
|
||||
path.Clean(upath),
|
||||
@@ -272,15 +285,10 @@ func (w *fsHandler) Build() context.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
// go to the next middleware
|
||||
// go to the next middleware, if any.
|
||||
ctx.Next()
|
||||
}
|
||||
if len(w.begin) > 0 {
|
||||
handlers := append(w.begin[0:], fileserver)
|
||||
w.handler = func(ctx context.Context) {
|
||||
ctx.Do(handlers)
|
||||
}
|
||||
}
|
||||
|
||||
w.handler = fileserver
|
||||
})
|
||||
|
||||
@@ -294,10 +302,10 @@ func (w *fsHandler) Build() context.Handler {
|
||||
// replying with an HTTP 404 not found error.
|
||||
//
|
||||
// Usage:
|
||||
// fileserver := iris.StaticHandler("./static_files", false, false)
|
||||
// fileserver := Party#StaticHandler("./static_files", false, false)
|
||||
// h := router.StripPrefix("/static", fileserver)
|
||||
// app.Get("/static", h)
|
||||
//
|
||||
// app.Get("/static/{f:path}", h)
|
||||
// app.Head("/static/{f:path}", h)
|
||||
func StripPrefix(prefix string, h context.Handler) context.Handler {
|
||||
if prefix == "" {
|
||||
return h
|
||||
@@ -821,7 +829,7 @@ func serveFile(ctx context.Context, fs http.FileSystem, name string, redirect bo
|
||||
|
||||
// try to find and send the correct content type based on the filename
|
||||
// and the binary data inside "f".
|
||||
detectOrWriteContentType(ctx, d.Name(), f)
|
||||
// detectOrWriteContentType(ctx, d.Name(), f)
|
||||
|
||||
return "", http.StatusOK
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func joinPath(path1 string, path2 string) string {
|
||||
// cleanPath applies the following rules
|
||||
// iteratively until no further processing can be done:
|
||||
//
|
||||
// 1. Replace multiple slashes with a single slash.
|
||||
// 1. Replace multiple slashes with a single slash.
|
||||
// 2. Replace '\' with '/'
|
||||
// 3. Replace "\\" with '/'
|
||||
// 4. Ignore anything inside '{' and '}'
|
||||
@@ -87,7 +87,7 @@ func cleanPath(s string) string {
|
||||
return "/"
|
||||
}
|
||||
|
||||
// remove suffix "/".
|
||||
// remove suffix "/", if it's root "/" then it will add it as a prefix below.
|
||||
if lidx := len(s) - 1; s[lidx] == '/' {
|
||||
s = s[:lidx]
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ func TestCleanPath(t *testing.T) {
|
||||
path string
|
||||
expected string
|
||||
}{
|
||||
{"/",
|
||||
"/"},
|
||||
{"noslashPrefix",
|
||||
"/noslashPrefix"},
|
||||
{"slashSuffix/",
|
||||
|
||||
Reference in New Issue
Block a user