Skip to content
Snippets Groups Projects
Unverified Commit 22b13291 authored by Wolfgang Welz's avatar Wolfgang Welz Committed by GitHub
Browse files

Fix: Report HTTP server errors (#370)

parent aba33d58
No related branches found
No related tags found
No related merge requests found
......@@ -20,16 +20,18 @@ var (
engine *echo.Echo
)
const name = "Analysis HTTP Server"
// PluginName is the name of the analysis server plugin.
const PluginName = "Analysis HTTP Server"
var assetsBox = packr.New("Assets", "./static")
// Configure configures the plugin.
func Configure() {
log = logger.NewLogger(name)
log = logger.NewLogger(PluginName)
engine = echo.New()
engine.HideBanner = true
engine.HidePort = true
// we only need this special flag, because we always keep a packed box in the same directory
if config.Node.GetBool(CfgDev) {
......@@ -47,17 +49,19 @@ func Configure() {
// Run runs the plugin.
func Run() {
log.Infof("Starting %s ...", name)
if err := daemon.BackgroundWorker(name, start, shutdown.PriorityAnalysis); err != nil {
log.Infof("Starting %s ...", PluginName)
if err := daemon.BackgroundWorker(PluginName, worker, shutdown.PriorityAnalysis); err != nil {
log.Errorf("Error starting as daemon: %s", err)
}
}
func start(shutdownSignal <-chan struct{}) {
func worker(shutdownSignal <-chan struct{}) {
defer log.Infof("Stopping %s ... done", PluginName)
stopped := make(chan struct{})
bindAddr := config.Node.GetString(CfgBindAddress)
go func() {
log.Infof("Started %s: http://%s", name, bindAddr)
log.Infof("Started %s: http://%s", PluginName, bindAddr)
if err := engine.Start(bindAddr); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
log.Errorf("Error serving: %s", err)
......@@ -66,19 +70,18 @@ func start(shutdownSignal <-chan struct{}) {
}
}()
// stop if we are shutting down or the server could not be started
select {
case <-shutdownSignal:
case <-stopped:
}
log.Infof("Stopping %s ...", name)
log.Infof("Stopping %s ...", PluginName)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := engine.Shutdown(ctx); err != nil {
log.Errorf("Error stopping: %s", err)
}
log.Info("Stopping %s ... done", name)
}
func index(e echo.Context) error {
......
package dashboard
import (
"context"
"errors"
"net"
"net/http"
"runtime"
......@@ -34,7 +36,9 @@ const PluginName = "Dashboard"
var (
// Plugin is the plugin instance of the dashboard plugin.
Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
log *logger.Logger
server *echo.Echo
nodeStartAt = time.Now()
......@@ -60,54 +64,79 @@ func configure(plugin *node.Plugin) {
configureLiveFeed()
configureDrngLiveFeed()
configureServer()
}
func run(plugin *node.Plugin) {
notifyStatus := events.NewClosure(func(mps uint64) {
wsSendWorkerPool.TrySubmit(mps)
})
daemon.BackgroundWorker("Dashboard[WSSend]", func(shutdownSignal <-chan struct{}) {
metrics.Events.ReceivedMPSUpdated.Attach(notifyStatus)
wsSendWorkerPool.Start()
<-shutdownSignal
log.Info("Stopping Dashboard[WSSend] ...")
metrics.Events.ReceivedMPSUpdated.Detach(notifyStatus)
wsSendWorkerPool.Stop()
log.Info("Stopping Dashboard[WSSend] ... done")
}, shutdown.PriorityDashboard)
func configureServer() {
server = echo.New()
server.HideBanner = true
server.HidePort = true
server.Use(middleware.Recover())
runLiveFeed()
if config.Node.GetBool(CfgBasicAuthEnabled) {
server.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if username == config.Node.GetString(CfgBasicAuthUsername) &&
password == config.Node.GetString(CfgBasicAuthPassword) {
return true, nil
}
return false, nil
}))
}
setupRoutes(server)
}
func run(*node.Plugin) {
// rune the message live feed
runLiveFeed()
// run dRNG live feed if dRNG plugin is enabled
if !node.IsSkipped(drng.Plugin) {
runDrngLiveFeed()
}
// allow any origin for websocket connections
upgrader.CheckOrigin = func(r *http.Request) bool {
return true
log.Infof("Starting %s ...", PluginName)
if err := daemon.BackgroundWorker(PluginName, worker, shutdown.PriorityAnalysis); err != nil {
log.Errorf("Error starting as daemon: %s", err)
}
}
e := echo.New()
e.HideBanner = true
e.Use(middleware.Recover())
if config.Node.GetBool(CfgBasicAuthEnabled) {
e.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if username == config.Node.GetString(CfgBasicAuthUsername) &&
password == config.Node.GetString(CfgBasicAuthPassword) {
return true, nil
func worker(shutdownSignal <-chan struct{}) {
defer log.Infof("Stopping %s ... done", PluginName)
// start the web socket worker pool
wsSendWorkerPool.Start()
defer wsSendWorkerPool.Stop()
// submit the mps to the worker pool when triggered
notifyStatus := events.NewClosure(func(mps uint64) { wsSendWorkerPool.TrySubmit(mps) })
metrics.Events.ReceivedMPSUpdated.Attach(notifyStatus)
defer metrics.Events.ReceivedMPSUpdated.Detach(notifyStatus)
stopped := make(chan struct{})
bindAddr := config.Node.GetString(CfgBindAddress)
go func() {
log.Infof("Started %s: http://%s", PluginName, bindAddr)
if err := server.Start(bindAddr); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
log.Errorf("Error serving: %s", err)
}
return false, nil
}))
}
close(stopped)
}
}()
setupRoutes(e)
addr := config.Node.GetString(CfgBindAddress)
// stop if we are shutting down or the server could not be started
select {
case <-shutdownSignal:
case <-stopped:
}
log.Infof("You can now access the dashboard using: http://%s", addr)
go e.Start(addr)
log.Infof("Stopping %s ...", PluginName)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Errorf("Error stopping: %s", err)
}
}
// sends the given message to all connected websocket clients
......@@ -128,6 +157,7 @@ var webSocketWriteTimeout = time.Duration(3) * time.Second
var (
upgrader = websocket.Upgrader{
HandshakeTimeout: webSocketWriteTimeout,
CheckOrigin: func(r *http.Request) bool { return true },
EnableCompression: true,
}
)
......@@ -195,7 +225,7 @@ type neighbormetric struct {
}
func neighborMetrics() []neighbormetric {
stats := []neighbormetric{}
var stats []neighbormetric
// gossip plugin might be disabled
neighbors := gossip.Manager().AllNeighbors()
......
......@@ -2,6 +2,8 @@ package webapi
import (
"context"
"errors"
"net/http"
"time"
"github.com/iotaledger/goshimmer/packages/shutdown"
......@@ -18,38 +20,52 @@ const PluginName = "WebAPI"
var (
// Plugin is the plugin instance of the web API plugin.
Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
log *logger.Logger
// Server is the web API server.
Server = echo.New()
log *logger.Logger
)
func configure(plugin *node.Plugin) {
func configure(*node.Plugin) {
log = logger.NewLogger(PluginName)
// configure the server
Server.HideBanner = true
Server.HidePort = true
Server.GET("/", IndexRequest)
}
func run(plugin *node.Plugin) {
log.Info("Starting Web Server ...")
func run(*node.Plugin) {
log.Infof("Starting %s ...", PluginName)
if err := daemon.BackgroundWorker("WebAPI Server", worker, shutdown.PriorityWebAPI); err != nil {
log.Errorf("Error starting as daemon: %s", err)
}
}
daemon.BackgroundWorker("WebAPI Server", func(shutdownSignal <-chan struct{}) {
log.Info("Starting Web Server ... done")
func worker(shutdownSignal <-chan struct{}) {
defer log.Infof("Stopping %s ... done", PluginName)
go func() {
if err := Server.Start(config.Node.GetString(CfgBindAddress)); err != nil {
log.Info("Stopping Web Server ... done")
stopped := make(chan struct{})
bindAddr := config.Node.GetString(CfgBindAddress)
go func() {
log.Infof("Started %s: http://%s", PluginName, bindAddr)
if err := Server.Start(bindAddr); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
log.Errorf("Error serving: %s", err)
}
}()
<-shutdownSignal
close(stopped)
}
}()
log.Info("Stopping Web Server ...")
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
// stop if we are shutting down or the server could not be started
select {
case <-shutdownSignal:
case <-stopped:
}
if err := Server.Shutdown(ctx); err != nil {
log.Errorf("Couldn't stop server cleanly: %s", err.Error())
}
}, shutdown.PriorityWebAPI)
log.Infof("Stopping %s ...", PluginName)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := Server.Shutdown(ctx); err != nil {
log.Errorf("Error stopping: %s", err)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment