Modify the SPA example for iris.PrefixDir

This commit is contained in:
Gerasimos (Makis) Maropoulos 2020-09-14 18:36:04 +03:00
parent 076f806925
commit 44d5ebdc9c
No known key found for this signature in database
GPG Key ID: 5DBE766BD26A54E7
10 changed files with 112 additions and 91 deletions

View File

@ -100,7 +100,7 @@
* [Send Files (rate limiter included)](file-server/send-files/main.go) * [Send Files (rate limiter included)](file-server/send-files/main.go)
* Single Page Applications * Single Page Applications
* [Basic SPA](file-server/single-page-application/basic/main.go) * [Basic SPA](file-server/single-page-application/basic/main.go)
* [Embedded Single Page Application](file-server/single-page-application/embedded-single-page-application/main.go) * [Embedded Single Page Application and `iris.PrefixDir`](file-server/single-page-application/embedded-single-page-application/main.go)
* [Embedded Single Page Application with other routes](file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go) * [Embedded Single Page Application with other routes](file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go)
* [Upload File](file-server/upload-file/main.go) * [Upload File](file-server/upload-file/main.go)
* [Upload Multiple Files](file-server/upload-files/main.go) * [Upload Multiple Files](file-server/upload-files/main.go)

View File

@ -1,10 +1,10 @@
// Code generated by go-bindata. (@generated) DO NOT EDIT. // Code generated by go-bindata. (@generated) DO NOT EDIT.
//Package main generated by go-bindata.// sources: // Package main generated by go-bindata.// sources:
// public/app.js // data/public/app.js
// public/app2/index.html // data/public/app2/index.html
// public/css/main.css // data/public/css/main.css
// public/index.html // data/views/index.html
package main package main
import ( import (
@ -168,82 +168,82 @@ func AssetFile() http.FileSystem {
return &assetOperator{} return &assetOperator{}
} }
var _appJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2c\x28\xd0\xcb\x2a\x56\xc8\xc9\x4f\x4c\x49\x4d\x51\x48\x2b\xca\xcf\x55\x88\x51\xd2\x57\xd2\xb4\x06\x04\x00\x00\xff\xff\xa9\x06\xf7\xa3\x27\x00\x00\x00") var _dataPublicAppJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2c\x28\xd0\xcb\x2a\x56\xc8\xc9\x4f\x4c\x49\x4d\x51\x48\x2b\xca\xcf\x55\x88\x51\xd2\x57\xd2\xb4\x06\x04\x00\x00\xff\xff\xa9\x06\xf7\xa3\x27\x00\x00\x00")
func appJsBytes() ([]byte, error) { func dataPublicAppJsBytes() ([]byte, error) {
return bindataRead( return bindataRead(
_appJs, _dataPublicAppJs,
"app.js", "data/public/app.js",
) )
} }
func appJs() (*asset, error) { func dataPublicAppJs() (*asset, error) {
bytes, err := appJsBytes() bytes, err := dataPublicAppJsBytes()
if err != nil { if err != nil {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "app.js", size: 39, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} info := bindataFileInfo{name: "data/public/app.js", size: 39, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info}
return a, nil return a, nil
} }
var _app2IndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8d\x41\x0a\xc2\x40\x0c\x45\xf7\x81\xdc\xe1\x9f\xc0\xd0\xae\x43\xc0\x9d\xd7\xa8\x4c\x24\x85\xd4\x09\x32\x0b\xbd\xbd\xb4\xd6\xe5\x87\xf7\xde\xd7\x18\x5b\x1a\x13\x93\x86\x2f\xcd\x98\x00\x40\xc7\x3a\xd2\xed\x5a\x85\x59\xe5\x37\x98\x54\x4e\x84\x49\xef\xbd\x7d\xfe\x70\x4c\x86\x9b\x67\x76\x3c\x5e\x7d\xc3\x52\x35\xcb\xfa\x6c\xfe\xbe\xec\x71\xa8\xc4\x74\xd8\xa7\x73\x84\xf6\xd7\x6f\x00\x00\x00\xff\xff\xfd\x28\x92\x95\x7c\x00\x00\x00") var _dataPublicApp2IndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\xce\xb1\x0a\x02\x31\x0c\xc6\xf1\x3d\x90\x77\xf8\x46\x5d\x2c\x77\x73\x28\xb8\xdd\xa0\x20\xe8\x0b\x54\x1b\x6d\xa1\x67\x8b\x64\xd0\xb7\x97\x3b\xeb\x18\xf8\xf3\xcb\x27\xc9\xe6\xe2\x99\x98\x24\x69\x88\x9e\x09\x00\xc4\xb2\x15\xf5\xfb\xd6\x30\x8a\xfb\x1d\x4c\xe2\x7a\xc2\x24\xd7\x1a\x3f\xff\x38\x0d\x1e\x9b\xb3\x05\xcb\x37\x4c\x97\xe3\x01\xa7\xf0\xd0\x2d\x26\x2d\xa5\xe2\xfe\xaa\x33\x42\x6b\xa3\xcb\xcf\xa8\xef\xdd\xf2\x0f\xe2\xd2\xb0\x82\x9d\x59\xed\x65\xc8\x37\x00\x00\xff\xff\xf4\x87\x93\x1a\x8f\x00\x00\x00")
func app2IndexHtmlBytes() ([]byte, error) { func dataPublicApp2IndexHtmlBytes() ([]byte, error) {
return bindataRead( return bindataRead(
_app2IndexHtml, _dataPublicApp2IndexHtml,
"app2/index.html", "data/public/app2/index.html",
) )
} }
func app2IndexHtml() (*asset, error) { func dataPublicApp2IndexHtml() (*asset, error) {
bytes, err := app2IndexHtmlBytes() bytes, err := dataPublicApp2IndexHtmlBytes()
if err != nil { if err != nil {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "app2/index.html", size: 124, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} info := bindataFileInfo{name: "data/public/app2/index.html", size: 143, mode: os.FileMode(438), modTime: time.Unix(1600097514, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info}
return a, nil return a, nil
} }
var _cssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00") var _dataPublicCssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00")
func cssMainCssBytes() ([]byte, error) { func dataPublicCssMainCssBytes() ([]byte, error) {
return bindataRead( return bindataRead(
_cssMainCss, _dataPublicCssMainCss,
"css/main.css", "data/public/css/main.css",
) )
} }
func cssMainCss() (*asset, error) { func dataPublicCssMainCss() (*asset, error) {
bytes, err := cssMainCssBytes() bytes, err := dataPublicCssMainCssBytes()
if err != nil { if err != nil {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} info := bindataFileInfo{name: "data/public/css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info}
return a, nil return a, nil
} }
var _indexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8e\x41\x0e\xc2\x20\x10\x45\xf7\x24\xdc\xe1\xa7\x07\x80\x74\x3f\xb2\x76\xe9\xc2\x0b\x60\x41\xc1\x50\x21\xc0\x42\xd3\xf4\xee\x06\x4a\x97\x93\xf7\x66\xde\x90\xab\x6b\x50\x9c\x71\x46\xce\x6a\xa3\x38\x03\x00\xaa\xbe\x06\xab\xb6\x0d\xe2\xa6\x5f\x56\xdc\xdb\x88\x7d\x27\x79\x00\xce\x48\x0e\x9d\x33\x7a\x44\xf3\x3b\x17\xdd\xac\x70\xb5\x21\x44\x3c\x73\x5c\xe1\x3f\xc6\x7e\x45\x6b\x80\xa4\x9b\xbb\x3f\xcc\xb2\x64\x9f\x2a\x4a\x5e\x2e\x93\xd4\x29\x89\x77\x99\x14\x40\xf2\x00\xbd\x31\x2e\xf7\x5c\xfb\xf3\x1f\x00\x00\xff\xff\x25\xe9\x37\x57\xae\x00\x00\x00") var _dataViewsIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\xce\x3d\x0e\xc2\x30\x0c\x05\xe0\x3d\x52\xee\xf0\xd4\x09\x96\x58\xdd\x4d\x66\x46\x86\x5e\x20\xb4\x86\x04\xa5\x34\x6a\x22\x7e\x54\xf5\xee\xa8\x3f\x8c\xd6\xf3\xf3\x67\xf6\xa5\x8f\x56\x2b\xad\xd8\x8b\xeb\xac\x56\x00\xc0\x25\x94\x28\x76\x9a\x60\x2e\xee\x2e\xa6\x59\x46\xcc\x33\xd3\x16\x68\xc5\xb4\xaf\x6b\xc5\xd7\xa1\xfb\xfe\x8b\xbe\xb6\x38\x34\xd2\xa7\xe8\x8a\x1c\x71\x96\x18\x07\xdc\xc6\xa1\xc7\x2b\xc8\x3b\x53\x78\x76\xf2\x31\x0b\x0a\x26\x5f\xaf\x07\xf6\x6a\x6e\xc7\x90\x0a\xf2\xd8\x9e\x2a\x72\x29\x99\x47\xae\x2c\xc0\xb4\x05\x2b\xba\x53\xab\xbf\x3c\xfe\x0b\x00\x00\xff\xff\x4a\xf7\x07\xf6\xbf\x00\x00\x00")
func indexHtmlBytes() ([]byte, error) { func dataViewsIndexHtmlBytes() ([]byte, error) {
return bindataRead( return bindataRead(
_indexHtml, _dataViewsIndexHtml,
"index.html", "data/views/index.html",
) )
} }
func indexHtml() (*asset, error) { func dataViewsIndexHtml() (*asset, error) {
bytes, err := indexHtmlBytes() bytes, err := dataViewsIndexHtmlBytes()
if err != nil { if err != nil {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "index.html", size: 174, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} info := bindataFileInfo{name: "data/views/index.html", size: 191, mode: os.FileMode(438), modTime: time.Unix(1600097531, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info}
return a, nil return a, nil
} }
@ -252,8 +252,8 @@ func indexHtml() (*asset, error) {
// It returns an error if the asset could not be found or // It returns an error if the asset could not be found or
// could not be loaded. // could not be loaded.
func Asset(name string) ([]byte, error) { func Asset(name string) ([]byte, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok { if f, ok := _bindata[canonicalName]; ok {
a, err := f() a, err := f()
if err != nil { if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
@ -278,8 +278,8 @@ func MustAsset(name string) []byte {
// It returns an error if the asset could not be found or // It returns an error if the asset could not be found or
// could not be loaded. // could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) { func AssetInfo(name string) (os.FileInfo, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok { if f, ok := _bindata[canonicalName]; ok {
a, err := f() a, err := f()
if err != nil { if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
@ -300,10 +300,10 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name. // _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){ var _bindata = map[string]func() (*asset, error){
"app.js": appJs, "data/public/app.js": dataPublicAppJs,
"app2/index.html": app2IndexHtml, "data/public/app2/index.html": dataPublicApp2IndexHtml,
"css/main.css": cssMainCss, "data/public/css/main.css": dataPublicCssMainCss,
"index.html": indexHtml, "data/views/index.html": dataViewsIndexHtml,
} }
// AssetDir returns the file names below a certain // AssetDir returns the file names below a certain
@ -317,13 +317,13 @@ var _bindata = map[string]func() (*asset, error){
// b.png // b.png
// then AssetDir("data") would return []string{"foo.txt", "img"} // then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error // AssetDir("foo.txt") and AssetDir("nonexistent") would return an error
// AssetDir("") will return []string{"data"}. // AssetDir("") will return []string{"data"}.
func AssetDir(name string) ([]string, error) { func AssetDir(name string) ([]string, error) {
node := _bintree node := _bintree
if len(name) != 0 { if len(name) != 0 {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
pathList := strings.Split(cannonicalName, "/") pathList := strings.Split(canonicalName, "/")
for _, p := range pathList { for _, p := range pathList {
node = node.Children[p] node = node.Children[p]
if node == nil { if node == nil {
@ -347,14 +347,20 @@ type bintree struct {
} }
var _bintree = &bintree{nil, map[string]*bintree{ var _bintree = &bintree{nil, map[string]*bintree{
"app.js": {appJs, map[string]*bintree{}}, "data": {nil, map[string]*bintree{
"public": {nil, map[string]*bintree{
"app.js": {dataPublicAppJs, map[string]*bintree{}},
"app2": {nil, map[string]*bintree{ "app2": {nil, map[string]*bintree{
"index.html": {app2IndexHtml, map[string]*bintree{}}, "index.html": {dataPublicApp2IndexHtml, map[string]*bintree{}},
}}, }},
"css": {nil, map[string]*bintree{ "css": {nil, map[string]*bintree{
"main.css": {cssMainCss, map[string]*bintree{}}, "main.css": {dataPublicCssMainCss, map[string]*bintree{}},
}},
}},
"views": {nil, map[string]*bintree{
"index.html": {dataViewsIndexHtml, map[string]*bintree{}},
}},
}}, }},
"index.html": {indexHtml, map[string]*bintree{}},
}} }}
// RestoreAsset restores an asset under the given directory // RestoreAsset restores an asset under the given directory
@ -400,6 +406,6 @@ func RestoreAssets(dir, name string) error {
} }
func _filePath(dir, name string) string { func _filePath(dir, name string) string {
cannonicalName := strings.Replace(name, "\\", "/", -1) canonicalName := strings.Replace(name, "\\", "/", -1)
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
} }

View File

@ -0,0 +1,11 @@
<html>
<head>
<title>App 2</title>
</head>
<body>
<h1> (Static HTML Page) Hello from app2/index.html </h1>
</body>
</html>

View File

@ -5,7 +5,7 @@
</head> </head>
<body> <body>
<h1> Hello from index.html </h1> <h1> (Template) Hello from views/index.html </h1>
<script src="/app.js"> </script> <script src="/app.js"> </script>

View File

@ -1,13 +1,9 @@
package main package main
import ( import "github.com/kataras/iris/v12"
"github.com/kataras/iris/v12"
)
// $ go get -u github.com/go-bindata/go-bindata/... // $ go get -u github.com/go-bindata/go-bindata/...
// # OR: go get -u github.com/go-bindata/go-bindata/v3/go-bindata // $ go-bindata -fs ./data/...
// # to save it to your go.mod file
// $ go-bindata -fs -prefix "public" ./public/...
// $ go run . // $ go run .
var page = struct { var page = struct {
@ -17,9 +13,15 @@ var page = struct {
func newApp() *iris.Application { func newApp() *iris.Application {
app := iris.New() app := iris.New()
app.RegisterView(iris.HTML(AssetFile(), ".html")) // Using the iris.PrefixDir you can select
// which directories to use under a particular file system,
// e.g. for views the ./data/views and for static files
// the ./data/public.
templatesFS := iris.PrefixDir("./data/views", AssetFile())
app.RegisterView(iris.HTML(templatesFS, ".html"))
app.HandleDir("/", AssetFile()) publicFS := iris.PrefixDir("./data/public", AssetFile())
app.HandleDir("/", publicFS)
app.Get("/", func(ctx iris.Context) { app.Get("/", func(ctx iris.Context) {
ctx.ViewData("Page", page) ctx.ViewData("Page", page)

View File

@ -55,7 +55,6 @@ func (r resource) loadFromBase(dir string) string {
var urls = []resource{ var urls = []resource{
"/", "/",
"/index.html",
"/app.js", "/app.js",
"/css/main.css", "/css/main.css",
"/app2/", "/app2/",
@ -68,7 +67,11 @@ func TestSPAEmbedded(t *testing.T) {
for _, u := range urls { for _, u := range urls {
url := u.String() url := u.String()
contents := u.loadFromBase("./public") base := "./data/public"
if u == "/" || u == "/index.html" {
base = "./data/views"
}
contents := u.loadFromBase(base)
contents = strings.Replace(contents, "{{ .Page.Title }}", page.Title, 1) contents = strings.Replace(contents, "{{ .Page.Title }}", page.Title, 1)
e.GET(url).Expect(). e.GET(url).Expect().
@ -76,4 +79,6 @@ func TestSPAEmbedded(t *testing.T) {
ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()). ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()).
Body().Equal(contents) Body().Equal(contents)
} }
e.GET("/index.html").Expect().Status(httptest.StatusNotFound) // only root is served.
} }

View File

@ -1,11 +0,0 @@
<html>
<head>
<title>App 2</title>
</head>
<body>
<h1> Hello from app2/index.html </h1>
</body>
</html>

View File

@ -232,6 +232,14 @@ var (
// PrefixDir returns a new FileSystem that opens files // PrefixDir returns a new FileSystem that opens files
// by adding the given "prefix" to the directory tree of "fs". // by adding the given "prefix" to the directory tree of "fs".
//
// Useful when having templates and static files in the same
// bindata AssetFile method. This way you can select
// which one to serve as static files and what for templates.
// All view engines have a `RootDir` method for that reason too
// but alternatively, you can wrap the given file system with this `PrefixDir`.
//
// Example: https://github.com/kataras/iris/blob/master/_examples/file-server/single-page-application/embedded-single-page-application/main.go
func PrefixDir(prefix string, fs http.FileSystem) http.FileSystem { func PrefixDir(prefix string, fs http.FileSystem) http.FileSystem {
return &prefixedDir{prefix, fs} return &prefixedDir{prefix, fs}
} }