1
0
mirror of https://github.com/kataras/iris.git synced 2026-01-08 12:31:58 +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:
Gerasimos Maropoulos
2018-03-14 07:17:35 +02:00
parent 1e0c707366
commit 56215eeb71
28 changed files with 20453 additions and 67 deletions

View File

@@ -13,7 +13,7 @@ import (
const (
// Version is the string representation of the current local Iris Web Framework version.
Version = "10.3.0"
Version = "10.4.0"
)
// CheckForUpdates checks for any available updates

View File

@@ -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 != "/" {

View File

@@ -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
}

View File

@@ -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]
}

View File

@@ -9,6 +9,8 @@ func TestCleanPath(t *testing.T) {
path string
expected string
}{
{"/",
"/"},
{"noslashPrefix",
"/noslashPrefix"},
{"slashSuffix/",