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
|
||||
build-dev-deps: ## Install dependencies for builds
|
||||
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/github-release/github-release
|
||||
|
||||
@ -157,11 +156,6 @@ storagenode-console:
|
||||
-u $(shell id -u):$(shell id -g) \
|
||||
node:${NODE_VERSION} \
|
||||
/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
|
||||
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 (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
@ -45,16 +47,18 @@ type Server struct {
|
||||
notifications *notifications.Service
|
||||
payout *payouts.Service
|
||||
listener net.Listener
|
||||
assets fs.FS
|
||||
|
||||
server http.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{
|
||||
log: logger,
|
||||
service: service,
|
||||
listener: listener,
|
||||
assets: assets,
|
||||
notifications: notifications,
|
||||
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("/payout-history/{period}", payoutController.PayoutHistory).Methods(http.MethodGet)
|
||||
|
||||
if assets != nil {
|
||||
fs := http.FileServer(assets)
|
||||
router.PathPrefix("/static/").Handler(web.CacheHandler(http.StripPrefix("/static", fs)))
|
||||
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)
|
||||
}))
|
||||
}
|
||||
staticServer := http.FileServer(http.FS(server.assets))
|
||||
router.PathPrefix("/static/").Handler(web.CacheHandler(staticServer))
|
||||
router.PathPrefix("/").HandlerFunc(server.appHandler)
|
||||
|
||||
server.server = http.Server{
|
||||
Handler: router,
|
||||
@ -103,6 +101,24 @@ func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifi
|
||||
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.
|
||||
func (server *Server) Run(ctx context.Context) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
@ -7,8 +7,9 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
@ -36,7 +37,6 @@ import (
|
||||
"storj.io/storj/storagenode/bandwidth"
|
||||
"storj.io/storj/storagenode/collector"
|
||||
"storj.io/storj/storagenode/console"
|
||||
"storj.io/storj/storagenode/console/consoleassets"
|
||||
"storj.io/storj/storagenode/console/consoleserver"
|
||||
"storj.io/storj/storagenode/contact"
|
||||
"storj.io/storj/storagenode/gracefulexit"
|
||||
@ -63,6 +63,7 @@ import (
|
||||
"storj.io/storj/storagenode/storageusage"
|
||||
"storj.io/storj/storagenode/trust"
|
||||
version2 "storj.io/storj/storagenode/version"
|
||||
storagenodeweb "storj.io/storj/web/storagenode"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -666,10 +667,13 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
|
||||
return nil, errs.Combine(err, peer.Close())
|
||||
}
|
||||
|
||||
assets := consoleassets.FileSystem
|
||||
var assets fs.FS
|
||||
assets = storagenodeweb.Assets
|
||||
if config.Console.StaticDir != "" {
|
||||
// a specific directory has been configured. use it
|
||||
assets = http.Dir(config.Console.StaticDir)
|
||||
// HACKFIX: Previous setups specify the directory for web/storagenode,
|
||||
// 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(
|
||||
|
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');
|
||||
|
||||
module.exports = {
|
||||
publicPath: "/static/dist",
|
||||
productionSourceMap: false,
|
||||
parallel: true,
|
||||
lintOnSave: false, // disables eslint for builds
|
||||
assetsDir: "static",
|
||||
configureWebpack: {
|
||||
plugins: [],
|
||||
},
|
||||
chainWebpack: config => {
|
||||
config.output.chunkFilename(`js/vendors_[hash].js`);
|
||||
config.output.filename(`js/app_[hash].js`);
|
||||
|
||||
config.resolve.alias
|
||||
.set('@', path.resolve('src'));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user