forked from kataras/iris
-
Notifications
You must be signed in to change notification settings - Fork 0
/
router_spa_wrapper.go
96 lines (80 loc) · 2.4 KB
/
router_spa_wrapper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package router
import (
"net/http"
"strings"
"github.com/kataras/iris/context"
)
// AssetValidator returns true if "filename"
// is asset, i.e: strings.Contains(filename, ".").
type AssetValidator func(filename string) bool
// SPABuilder helps building a single page application server
// which serves both routes and files from the root path.
type SPABuilder struct {
IndexNames []string
AssetHandler context.Handler
AssetValidators []AssetValidator
}
// NewSPABuilder returns a new Single Page Application builder
// It does what StaticWeb expected to do when serving files and routes at the same time
// from the root "/" path.
//
// Accepts a static asset handler, which can be an app.StaticHandler, app.StaticEmbeddedHandler...
func NewSPABuilder(assetHandler context.Handler) *SPABuilder {
if assetHandler == nil {
assetHandler = func(ctx context.Context) {
ctx.Writef("empty asset handler")
}
}
return &SPABuilder{
IndexNames: []string{"index.html"},
AssetHandler: assetHandler,
AssetValidators: []AssetValidator{
func(path string) bool {
return strings.Contains(path, ".")
},
},
}
}
func (s *SPABuilder) isAsset(reqPath string) bool {
for _, v := range s.AssetValidators {
if !v(reqPath) {
return false
}
}
return true
}
// BuildWrapper returns a wrapper which serves the single page application
// with the declared configuration.
//
// It should be passed to the router's `WrapRouter`:
// https://godoc.org/github.com/kataras/iris/core/router#Router.WrapRouter
//
// Example: https://github.com/kataras/iris/tree/master/_examples/file-server/single-page-application-builder
func (s *SPABuilder) BuildWrapper(cPool *context.Pool) WrapperFunc {
fileServer := s.AssetHandler
indexNames := s.IndexNames
wrapper := func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
path := r.URL.Path
if !s.isAsset(path) {
// it's not asset, execute the registered route's handlers
router(w, r)
return
}
ctx := cPool.Acquire(w, r)
for _, index := range indexNames {
if strings.HasSuffix(path, index) {
localRedirect(ctx, "./")
cPool.Release(ctx)
// "/" should be manually registered.
// We don't setup an index handler here,
// let full control to the user
// (use middleware, ctx.ServeFile or ctx.View and so on...)
return
}
}
// execute file server for path
fileServer(ctx)
cPool.Release(ctx)
}
return wrapper
}