diff --git a/server/internal.go b/server/internal.go index 92d0dbd8..37bb2a7b 100644 --- a/server/internal.go +++ b/server/internal.go @@ -4,7 +4,9 @@ import ( "context" "encoding/json" "fmt" + "html/template" "net/http" + "path/filepath" "github.com/golang/glog" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -16,6 +18,7 @@ import ( // InternalServer is handle to internal http server type InternalServer struct { + htmlTemplates[InternalTemplateData] https *http.Server certFiles string db *db.RocksDB @@ -41,6 +44,9 @@ func NewInternalServer(binding, certFiles string, db *db.RocksDB, chain bchain.B Handler: serveMux, } s := &InternalServer{ + htmlTemplates: htmlTemplates[InternalTemplateData]{ + debug: true, + }, https: https, certFiles: certFiles, db: db, @@ -51,11 +57,18 @@ func NewInternalServer(binding, certFiles string, db *db.RocksDB, chain bchain.B is: is, api: api, } + s.htmlTemplates.newTemplateData = s.newTemplateData + s.htmlTemplates.newTemplateDataWithError = s.newTemplateDataWithError + s.htmlTemplates.parseTemplates = s.parseTemplates + s.templates = s.parseTemplates() serveMux.Handle(path+"favicon.ico", http.FileServer(http.Dir("./static/"))) serveMux.HandleFunc(path+"metrics", promhttp.Handler().ServeHTTP) serveMux.HandleFunc(path, s.index) - + serveMux.HandleFunc(path+"admin", s.htmlTemplateHandler(s.adminIndex)) + if s.chainParser.GetChainType() == bchain.ChainEthereumType { + serveMux.HandleFunc(path+"admin/internal-data-errors", s.htmlTemplateHandler(s.internalDataErrors)) + } return s, nil } @@ -97,3 +110,73 @@ func (s *InternalServer) index(w http.ResponseWriter, r *http.Request) { w.Write(buf) } + +const ( + adminIndexTpl = iota + errorInternalTpl + 1 + adminInternalErrorsTpl + + internalTplCount +) + +// InternalTemplateData is used to transfer data to the templates +type InternalTemplateData struct { + CoinName string + CoinShortcut string + CoinLabel string + ChainType bchain.ChainType + Error *api.APIError + InternalDataErrors []db.BlockInternalDataError + InInternalDataRetry bool +} + +func (s *InternalServer) newTemplateData(r *http.Request) *InternalTemplateData { + t := &InternalTemplateData{ + CoinName: s.is.Coin, + CoinShortcut: s.is.CoinShortcut, + CoinLabel: s.is.CoinLabel, + ChainType: s.chainParser.GetChainType(), + } + return t +} + +func (s *InternalServer) newTemplateDataWithError(error *api.APIError, r *http.Request) *InternalTemplateData { + td := s.newTemplateData(r) + td.Error = error + return td +} + +func (s *InternalServer) parseTemplates() []*template.Template { + templateFuncMap := template.FuncMap{ + "formatUint32": formatUint32, + } + createTemplate := func(filenames ...string) *template.Template { + if len(filenames) == 0 { + panic("Missing templates") + } + return template.Must(template.New(filepath.Base(filenames[0])).Funcs(templateFuncMap).ParseFiles(filenames...)) + } + t := make([]*template.Template, internalTplCount) + t[errorTpl] = createTemplate("./static/internal_templates/error.html", "./static/internal_templates/base.html") + t[errorInternalTpl] = createTemplate("./static/internal_templates/error.html", "./static/internal_templates/base.html") + t[adminIndexTpl] = createTemplate("./static/internal_templates/index.html", "./static/internal_templates/base.html") + t[adminInternalErrorsTpl] = createTemplate("./static/internal_templates/block_internal_data_errors.html", "./static/internal_templates/base.html") + return t +} + +func (s *InternalServer) adminIndex(w http.ResponseWriter, r *http.Request) (tpl, *InternalTemplateData, error) { + data := s.newTemplateData(r) + return adminIndexTpl, data, nil +} + +func (s *InternalServer) internalDataErrors(w http.ResponseWriter, r *http.Request) (tpl, *InternalTemplateData, error) { + if r.Method == http.MethodPost { + + } + data := s.newTemplateData(r) + internalErrors, err := s.db.GetBlockInternalDataErrorsEthereumType() + if err != nil { + return errorTpl, nil, err + } + data.InternalDataErrors = internalErrors + return adminInternalErrorsTpl, data, nil +} diff --git a/static/internal_templates/base.html b/static/internal_templates/base.html new file mode 100644 index 00000000..81968276 --- /dev/null +++ b/static/internal_templates/base.html @@ -0,0 +1,28 @@ + + + + + + + + Blockbook {{.CoinLabel}} Internal Admin + + + + +
+
+ {{- template "specific" . -}} +
+
+ + + \ No newline at end of file diff --git a/static/internal_templates/block_internal_data_errors.html b/static/internal_templates/block_internal_data_errors.html new file mode 100644 index 00000000..53217f5b --- /dev/null +++ b/static/internal_templates/block_internal_data_errors.html @@ -0,0 +1,34 @@ +{{define "specific"}} +
+

Blocks with errors from fetching internal data

+
+ {{if .InInternalDataRetry}}Fetching...{{else}} +
+ +
+ {{end}} +
+ +
+ + + + + + + + + + + {{range $e := .InternalDataErrors}} + + + + + + + {{end}} + +
HeightHashRetriesError Message
{{formatUint32 $e.Height}}{{$e.Hash}}{{$e.Retries}}{{$e.ErrorMessage}}
+
+{{end}} \ No newline at end of file diff --git a/static/internal_templates/error.html b/static/internal_templates/error.html new file mode 100644 index 00000000..0b75378b --- /dev/null +++ b/static/internal_templates/error.html @@ -0,0 +1,4 @@ +{{define "specific"}} +

Error

+

{{.Error.Text}}

+{{end}} \ No newline at end of file diff --git a/static/internal_templates/index.html b/static/internal_templates/index.html new file mode 100644 index 00000000..325f8494 --- /dev/null +++ b/static/internal_templates/index.html @@ -0,0 +1,7 @@ +{{define "specific"}} +{{if eq .ChainType 1}} +
+ +
+{{end}} +{{end}} \ No newline at end of file