mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
New iris.DirOptions.PushTargetsRegexp
rel to: https://github.com/kataras/iris/issues/1562#issuecomment-659702891 Former-commit-id: 778cf9146b730d424040ea9e259ce6500f53b563
This commit is contained in:
parent
dab03102f3
commit
552f990358
17
HISTORY.md
17
HISTORY.md
|
@ -371,7 +371,20 @@ Other Improvements:
|
||||||
|
|
||||||
![DBUG routes](https://iris-go.com/images/v12.2.0-dbug2.png?v=0)
|
![DBUG routes](https://iris-go.com/images/v12.2.0-dbug2.png?v=0)
|
||||||
|
|
||||||
- Fix [#1562](https://github.com/kataras/iris/issues/1562)
|
- New `DirOptions.PushTargets` and `PushTargetsRegexp` to push index' assets to the client without additional requests. Inspirated by issue [#1562](https://github.com/kataras/iris/issues/1562). Example matching all `.js, .css and .ico` files (recursively):
|
||||||
|
|
||||||
|
```go
|
||||||
|
var opts = iris.DirOptions{
|
||||||
|
IndexName: "/index.html",
|
||||||
|
PushTargetsRegexp: map[string]*regexp.Regexp{
|
||||||
|
"/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$"),
|
||||||
|
// OR:
|
||||||
|
// "/": iris.MatchCommonAssets,
|
||||||
|
},
|
||||||
|
Compress: true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- Update jet parser to v4.0.2, closes [#1551](https://github.com/kataras/iris/issues/1551). It contains two breaking changes by its author:
|
- Update jet parser to v4.0.2, closes [#1551](https://github.com/kataras/iris/issues/1551). It contains two breaking changes by its author:
|
||||||
- Relative paths on `extends, import, include...` tmpl functions, e.g. `{{extends "../layouts/application.jet"}}` instead of `layouts/application.jet`
|
- Relative paths on `extends, import, include...` tmpl functions, e.g. `{{extends "../layouts/application.jet"}}` instead of `layouts/application.jet`
|
||||||
- the new [jet.Ranger](https://github.com/CloudyKit/jet/pull/165) interface now requires a `ProvidesIndex() bool` method too
|
- the new [jet.Ranger](https://github.com/CloudyKit/jet/pull/165) interface now requires a `ProvidesIndex() bool` method too
|
||||||
|
@ -380,7 +393,7 @@ Other Improvements:
|
||||||
- Fix [#1552](https://github.com/kataras/iris/issues/1552).
|
- Fix [#1552](https://github.com/kataras/iris/issues/1552).
|
||||||
|
|
||||||
- Proper listing of root directories on `Party.HandleDir` when its `DirOptions.ShowList` was set to true.
|
- Proper listing of root directories on `Party.HandleDir` when its `DirOptions.ShowList` was set to true.
|
||||||
- Customize the file/directory listing page through views, see [example](https://github.com/kataras/iris/tree/master/_examples/file-server/file-server)
|
- Customize the file/directory listing page through views, see [example](https://github.com/kataras/iris/tree/master/_examples/file-server/file-server).
|
||||||
|
|
||||||
- Socket Sharding as requested at [#1544](https://github.com/kataras/iris/issues/1544). New `iris.WithSocketSharding` Configurator and `SocketSharding bool` setting.
|
- Socket Sharding as requested at [#1544](https://github.com/kataras/iris/issues/1544). New `iris.WithSocketSharding` Configurator and `SocketSharding bool` setting.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12"
|
"github.com/kataras/iris/v12"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,13 +15,20 @@ var opts = iris.DirOptions{
|
||||||
//
|
//
|
||||||
// Note: Requires running server under TLS,
|
// Note: Requires running server under TLS,
|
||||||
// that's why we use `iris.TLS` below.
|
// that's why we use `iris.TLS` below.
|
||||||
PushTargets: map[string][]string{
|
// PushTargets: map[string][]string{
|
||||||
"/": { // Relative path without route prefix.
|
// "/": { // Relative path without prefix.
|
||||||
"favicon.ico",
|
// "favicon.ico",
|
||||||
"js/main.js",
|
// "js/main.js",
|
||||||
"css/main.css",
|
// "css/main.css",
|
||||||
// ^ Relative to the index, if need absolute ones start with a slash ('/').
|
// // ^ Relative to the index, if need absolute ones start with a slash ('/').
|
||||||
},
|
// },
|
||||||
|
// },
|
||||||
|
// OR use regexp:
|
||||||
|
PushTargetsRegexp: map[string]*regexp.Regexp{
|
||||||
|
// Match all js, css and ico files
|
||||||
|
// from all files (recursively).
|
||||||
|
// "/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$"),
|
||||||
|
"/": iris.MatchCommonAssets,
|
||||||
},
|
},
|
||||||
Compress: true,
|
Compress: true,
|
||||||
ShowList: true,
|
ShowList: true,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package iris
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/cache"
|
"github.com/kataras/iris/v12/cache"
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
|
@ -216,6 +217,13 @@ var (
|
||||||
ctx.CompressReader(true)
|
ctx.CompressReader(true)
|
||||||
ctx.Next()
|
ctx.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchCommonAssets is a simple regex expression which
|
||||||
|
// can be used on `DirOptions.PushTargetsRegexp`.
|
||||||
|
// It will match and Push
|
||||||
|
// all available js, css, font and media files.
|
||||||
|
// Ideal for Single Page Applications.
|
||||||
|
MatchCommonAssets = regexp.MustCompile("((.*).js|(.*).css|(.*).ico|(.*).png|(.*).ttf|(.*).svg|(.*).webp|(.*).gif)$")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -48,7 +49,23 @@ type DirOptions struct {
|
||||||
// be served without additional client's requests (HTTP/2 Push)
|
// be served without additional client's requests (HTTP/2 Push)
|
||||||
// when a specific request path (map's key WITHOUT prefix)
|
// when a specific request path (map's key WITHOUT prefix)
|
||||||
// is requested and it's not a directory (it's an `IndexFile`).
|
// is requested and it's not a directory (it's an `IndexFile`).
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// "/": {
|
||||||
|
// "favicon.ico",
|
||||||
|
// "js/main.js",
|
||||||
|
// "css/main.css",
|
||||||
|
// }
|
||||||
PushTargets map[string][]string
|
PushTargets map[string][]string
|
||||||
|
// PushTargetsRegexp like `PushTargets` but accepts regexp which
|
||||||
|
// is compared against all files under a directory (recursively).
|
||||||
|
// The `IndexName` should be set.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// "/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$")
|
||||||
|
// See `iris.MatchCommonAssets` too.
|
||||||
|
PushTargetsRegexp map[string]*regexp.Regexp
|
||||||
|
|
||||||
// When files should served under compression.
|
// When files should served under compression.
|
||||||
Compress bool
|
Compress bool
|
||||||
|
|
||||||
|
@ -407,7 +424,11 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
indexFound := false
|
var (
|
||||||
|
indexFound bool
|
||||||
|
indexDirectory http.File
|
||||||
|
)
|
||||||
|
|
||||||
// use contents of index.html for directory, if present
|
// use contents of index.html for directory, if present
|
||||||
if info.IsDir() && options.IndexName != "" {
|
if info.IsDir() && options.IndexName != "" {
|
||||||
// Note that, in contrast of the default net/http mechanism;
|
// Note that, in contrast of the default net/http mechanism;
|
||||||
|
@ -425,9 +446,11 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
|
||||||
defer fIndex.Close()
|
defer fIndex.Close()
|
||||||
infoIndex, err := fIndex.Stat()
|
infoIndex, err := fIndex.Stat()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
info = infoIndex
|
|
||||||
f = fIndex
|
|
||||||
indexFound = true
|
indexFound = true
|
||||||
|
indexDirectory = f
|
||||||
|
|
||||||
|
f = fIndex
|
||||||
|
info = infoIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,6 +477,25 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if regex, ok := options.PushTargetsRegexp[r.URL.Path]; ok {
|
||||||
|
if pusher, ok := ctx.ResponseWriter().(http.Pusher); ok {
|
||||||
|
for _, indexAsset := range getFilenamesRecursively(fs, indexDirectory, "") {
|
||||||
|
// it's an index file, do not pushed that.
|
||||||
|
if strings.HasSuffix("/"+indexAsset, options.IndexName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// match using relative path (without the first '/' slash)
|
||||||
|
// to keep consistency between the `PushTargets` behavior
|
||||||
|
if regex.MatchString(indexAsset) {
|
||||||
|
// println("Regex Matched: " + indexAsset)
|
||||||
|
if err = pusher.Push(path.Join(r.RequestURI, indexAsset), nil); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Still a directory? (we didn't find an index.html file)
|
// Still a directory? (we didn't find an index.html file)
|
||||||
|
@ -532,6 +574,38 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getFilenamesRecursively(fs http.FileSystem, f http.File, parent string) []string {
|
||||||
|
defer f.Close()
|
||||||
|
info, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var filenames []string
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
fileinfos, err := f.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fileinfo := range fileinfos {
|
||||||
|
fullname := path.Join(parent, fileinfo.Name())
|
||||||
|
ff, err := fs.Open(fullname)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
filenames = append(filenames, getFilenamesRecursively(fs, ff, fullname)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filenames
|
||||||
|
}
|
||||||
|
|
||||||
|
filenames = append(filenames, path.Dir(path.Join(parent, info.Name())))
|
||||||
|
return filenames
|
||||||
|
}
|
||||||
|
|
||||||
// StripPrefix returns a handler that serves HTTP requests
|
// StripPrefix returns a handler that serves HTTP requests
|
||||||
// by removing the given prefix from the request URL's Path
|
// by removing the given prefix from the request URL's Path
|
||||||
// and invoking the handler h. StripPrefix handles a
|
// and invoking the handler h. StripPrefix handles a
|
||||||
|
|
Loading…
Reference in New Issue
Block a user