storagenode,web/storagenode: use go:embed for assets
Go can now directly embed files without relying on external tools. This makes code use go:embed and avoid the external tooling. go:embed requires files to be present in the embedded directory, hence we need to add .keep to "dist" folder. We also add one to public/.keep, such that it won't be deleted when building storagenode. Change-Id: I8bef81236be6829ed37ed4c16ef693677b93a631
This commit is contained in:
parent
5f7ea1358d
commit
dc0f7b5f77
6
Makefile
6
Makefile
@ -48,7 +48,6 @@ help:
|
|||||||
.PHONY: build-dev-deps
|
.PHONY: build-dev-deps
|
||||||
build-dev-deps: ## Install dependencies for builds
|
build-dev-deps: ## Install dependencies for builds
|
||||||
go get golang.org/x/tools/cover
|
go get golang.org/x/tools/cover
|
||||||
go get github.com/go-bindata/go-bindata/go-bindata
|
|
||||||
go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
|
go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
|
||||||
go get github.com/github-release/github-release
|
go get github.com/github-release/github-release
|
||||||
|
|
||||||
@ -157,11 +156,6 @@ storagenode-console:
|
|||||||
-u $(shell id -u):$(shell id -g) \
|
-u $(shell id -u):$(shell id -g) \
|
||||||
node:${NODE_VERSION} \
|
node:${NODE_VERSION} \
|
||||||
/bin/bash -c "npm ci && npm run build"
|
/bin/bash -c "npm ci && npm run build"
|
||||||
# embed web assets into go
|
|
||||||
go-bindata -prefix web/storagenode/ -fs -o storagenode/console/consoleassets/bindata.resource.go -pkg consoleassets web/storagenode/dist/... web/storagenode/static/...
|
|
||||||
# configure existing go code to know about the new assets
|
|
||||||
/usr/bin/env echo -e '\nfunc init() { FileSystem = AssetFile() }' >> storagenode/console/consoleassets/bindata.resource.go
|
|
||||||
gofmt -w -s storagenode/console/consoleassets/bindata.resource.go
|
|
||||||
|
|
||||||
.PHONY: multinode-console
|
.PHONY: multinode-console
|
||||||
multinode-console:
|
multinode-console:
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
// Copyright (C) 2019 Storj Labs, Inc.
|
|
||||||
// See LICENSE for copying information.
|
|
||||||
|
|
||||||
package consoleassets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileSystem is nil by default, but when our Makefile generates
|
|
||||||
// embedded resources via go-bindata, it will also drop an init method
|
|
||||||
// that sets this to not nil.
|
|
||||||
var FileSystem http.FileSystem
|
|
@ -6,6 +6,8 @@ package consoleserver
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@ -45,16 +47,18 @@ type Server struct {
|
|||||||
notifications *notifications.Service
|
notifications *notifications.Service
|
||||||
payout *payouts.Service
|
payout *payouts.Service
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
|
assets fs.FS
|
||||||
|
|
||||||
server http.Server
|
server http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates new instance of storagenode console web server.
|
// NewServer creates new instance of storagenode console web server.
|
||||||
func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifications.Service, service *console.Service, payout *payouts.Service, listener net.Listener) *Server {
|
func NewServer(logger *zap.Logger, assets fs.FS, notifications *notifications.Service, service *console.Service, payout *payouts.Service, listener net.Listener) *Server {
|
||||||
server := Server{
|
server := Server{
|
||||||
log: logger,
|
log: logger,
|
||||||
service: service,
|
service: service,
|
||||||
listener: listener,
|
listener: listener,
|
||||||
|
assets: assets,
|
||||||
notifications: notifications,
|
notifications: notifications,
|
||||||
payout: payout,
|
payout: payout,
|
||||||
}
|
}
|
||||||
@ -86,15 +90,9 @@ func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifi
|
|||||||
payoutRouter.HandleFunc("/periods", payoutController.HeldAmountPeriods).Methods(http.MethodGet)
|
payoutRouter.HandleFunc("/periods", payoutController.HeldAmountPeriods).Methods(http.MethodGet)
|
||||||
payoutRouter.HandleFunc("/payout-history/{period}", payoutController.PayoutHistory).Methods(http.MethodGet)
|
payoutRouter.HandleFunc("/payout-history/{period}", payoutController.PayoutHistory).Methods(http.MethodGet)
|
||||||
|
|
||||||
if assets != nil {
|
staticServer := http.FileServer(http.FS(server.assets))
|
||||||
fs := http.FileServer(assets)
|
router.PathPrefix("/static/").Handler(web.CacheHandler(staticServer))
|
||||||
router.PathPrefix("/static/").Handler(web.CacheHandler(http.StripPrefix("/static", fs)))
|
router.PathPrefix("/").HandlerFunc(server.appHandler)
|
||||||
router.PathPrefix("/").Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
req := r.Clone(r.Context())
|
|
||||||
req.URL.Path = "/dist/"
|
|
||||||
fs.ServeHTTP(w, req)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
server.server = http.Server{
|
server.server = http.Server{
|
||||||
Handler: router,
|
Handler: router,
|
||||||
@ -103,6 +101,24 @@ func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifi
|
|||||||
return &server
|
return &server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appHandler is web app http handler function.
|
||||||
|
func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
header := w.Header()
|
||||||
|
|
||||||
|
header.Set("Content-Type", "text/html; charset=UTF-8")
|
||||||
|
header.Set("X-Content-Type-Options", "nosniff")
|
||||||
|
header.Set("Referrer-Policy", "same-origin")
|
||||||
|
|
||||||
|
f, err := server.assets.Open("index.html")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, `web/storagenode unbuilt, run "npm install && npm run build" in web/storagenode.`, http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() { _ = f.Close() }()
|
||||||
|
|
||||||
|
_, _ = io.Copy(w, f)
|
||||||
|
}
|
||||||
|
|
||||||
// Run starts the server that host webapp and api endpoints.
|
// Run starts the server that host webapp and api endpoints.
|
||||||
func (server *Server) Run(ctx context.Context) (err error) {
|
func (server *Server) Run(ctx context.Context) (err error) {
|
||||||
defer mon.Task()(&ctx)(&err)
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
@ -7,8 +7,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -36,7 +37,6 @@ import (
|
|||||||
"storj.io/storj/storagenode/bandwidth"
|
"storj.io/storj/storagenode/bandwidth"
|
||||||
"storj.io/storj/storagenode/collector"
|
"storj.io/storj/storagenode/collector"
|
||||||
"storj.io/storj/storagenode/console"
|
"storj.io/storj/storagenode/console"
|
||||||
"storj.io/storj/storagenode/console/consoleassets"
|
|
||||||
"storj.io/storj/storagenode/console/consoleserver"
|
"storj.io/storj/storagenode/console/consoleserver"
|
||||||
"storj.io/storj/storagenode/contact"
|
"storj.io/storj/storagenode/contact"
|
||||||
"storj.io/storj/storagenode/gracefulexit"
|
"storj.io/storj/storagenode/gracefulexit"
|
||||||
@ -63,6 +63,7 @@ import (
|
|||||||
"storj.io/storj/storagenode/storageusage"
|
"storj.io/storj/storagenode/storageusage"
|
||||||
"storj.io/storj/storagenode/trust"
|
"storj.io/storj/storagenode/trust"
|
||||||
version2 "storj.io/storj/storagenode/version"
|
version2 "storj.io/storj/storagenode/version"
|
||||||
|
storagenodeweb "storj.io/storj/web/storagenode"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -666,10 +667,13 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
|
|||||||
return nil, errs.Combine(err, peer.Close())
|
return nil, errs.Combine(err, peer.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
assets := consoleassets.FileSystem
|
var assets fs.FS
|
||||||
|
assets = storagenodeweb.Assets
|
||||||
if config.Console.StaticDir != "" {
|
if config.Console.StaticDir != "" {
|
||||||
// a specific directory has been configured. use it
|
// HACKFIX: Previous setups specify the directory for web/storagenode,
|
||||||
assets = http.Dir(config.Console.StaticDir)
|
// instead of the actual built data. This is for backwards compatibility.
|
||||||
|
distDir := filepath.Join(config.Console.StaticDir, "dist")
|
||||||
|
assets = os.DirFS(distDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
peer.Console.Endpoint = consoleserver.NewServer(
|
peer.Console.Endpoint = consoleserver.NewServer(
|
||||||
|
23
web/storagenode/assets.go
Normal file
23
web/storagenode/assets.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (C) 2022 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
package storagenodeweb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed dist/*
|
||||||
|
var assets embed.FS
|
||||||
|
|
||||||
|
// Assets contains either the built storagenode from web/storagenode/dist directory
|
||||||
|
// or it is empty.
|
||||||
|
var Assets = func() fs.FS {
|
||||||
|
dist, err := fs.Sub(assets, "dist")
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("invalid embedding: %w", err))
|
||||||
|
}
|
||||||
|
return dist
|
||||||
|
}()
|
0
web/storagenode/dist/.keep
vendored
Normal file
0
web/storagenode/dist/.keep
vendored
Normal file
0
web/storagenode/public/.keep
Normal file
0
web/storagenode/public/.keep
Normal file
@ -4,17 +4,14 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
publicPath: "/static/dist",
|
|
||||||
productionSourceMap: false,
|
productionSourceMap: false,
|
||||||
parallel: true,
|
parallel: true,
|
||||||
lintOnSave: false, // disables eslint for builds
|
lintOnSave: false, // disables eslint for builds
|
||||||
|
assetsDir: "static",
|
||||||
configureWebpack: {
|
configureWebpack: {
|
||||||
plugins: [],
|
plugins: [],
|
||||||
},
|
},
|
||||||
chainWebpack: config => {
|
chainWebpack: config => {
|
||||||
config.output.chunkFilename(`js/vendors_[hash].js`);
|
|
||||||
config.output.filename(`js/app_[hash].js`);
|
|
||||||
|
|
||||||
config.resolve.alias
|
config.resolve.alias
|
||||||
.set('@', path.resolve('src'));
|
.set('@', path.resolve('src'));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user