graphql-engine/cli/pkg/console/consoleserver.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

151 lines
4.1 KiB
Go
Raw Normal View History

2020-04-07 12:23:20 +03:00
package console
import (
"embed"
2020-04-07 12:23:20 +03:00
"fmt"
"net/http"
"os"
"github.com/gin-contrib/static"
"github.com/fatih/color"
"github.com/gin-gonic/gin"
"github.com/hasura/graphql-engine/cli/v2"
2020-04-07 12:23:20 +03:00
"github.com/sirupsen/logrus"
"github.com/skratchdot/open-golang/open"
errors "github.com/hasura/graphql-engine/cli/v2/internal/errors"
2020-04-07 12:23:20 +03:00
)
//go:embed templates/gohtml/*
var ConsoleFS embed.FS
2020-04-07 12:23:20 +03:00
type ConsoleServer struct {
Logger *logrus.Logger
Port string
APIPort string
Address string
DontOpenBrowser bool
StaticDir string
Browser string
EC *cli.ExecutionContext
TemplateProvider TemplateProvider
Router *gin.Engine
}
type NewConsoleServerOpts struct {
Logger *logrus.Logger
Port string
APIPort string
Address string
DontOpenBrowser bool
StaticDir string
Browser string
TemplateProvider TemplateProvider
EC *cli.ExecutionContext
Router *gin.Engine
}
func NewConsoleServer(opts *NewConsoleServerOpts) *ConsoleServer {
return &ConsoleServer{
Logger: opts.Logger,
Port: opts.Port,
Address: opts.Address,
APIPort: opts.APIPort,
DontOpenBrowser: opts.DontOpenBrowser,
StaticDir: opts.StaticDir,
Browser: opts.Browser,
EC: opts.EC,
TemplateProvider: opts.TemplateProvider,
Router: opts.Router,
}
}
func (c *ConsoleServer) GetHTTPServer() (*http.Server, error) {
// Switch to "release" mode in production.
gin.SetMode(gin.ReleaseMode)
consoleTemplateVersion := c.TemplateProvider.GetTemplateVersion(c.EC.Version)
consoleAssetsVersion := c.TemplateProvider.GetAssetsVersion(c.EC.Version)
c.Logger.Debugf("rendering console template [%s] with assets [%s]", consoleTemplateVersion, consoleAssetsVersion)
consoleServer := &http.Server{
Addr: fmt.Sprintf("%s:%s", c.Address, c.Port),
Handler: c.Router,
}
return consoleServer, nil
}
func (c *ConsoleServer) Serve() {
server, err := c.GetHTTPServer()
if err != nil {
c.Logger.Fatal(fmt.Errorf("error starting server: %w", err))
2020-04-07 12:23:20 +03:00
os.Exit(1)
}
go func() {
if err := server.ListenAndServe(); err != nil {
if err == http.ErrServerClosed {
c.EC.Logger.Infof("server closed on port %s under signal", c.Port)
} else {
c.EC.Logger.WithError(err).Errorf("error listening on port %s", c.Port)
}
}
}()
consoleURL := fmt.Sprintf("http://%s:%s/", c.Address, c.Port)
if !c.DontOpenBrowser {
if c.Browser != "" {
c.EC.Spin(color.CyanString("Opening console on: %s", c.Browser))
defer c.EC.Spinner.Stop()
err := open.RunWith(consoleURL, c.Browser)
if err != nil {
c.EC.Logger.WithError(err).Warnf("failed opening console in '%s', try to open the url manually", c.Browser)
}
} else {
c.EC.Spin(color.CyanString("Opening console using default browser..."))
defer c.EC.Spinner.Stop()
err := open.Run(consoleURL)
if err != nil {
c.EC.Logger.WithError(err).Warn("Error opening browser, try to open the url manually?")
}
}
}
c.EC.Spinner.Stop()
c.Logger.Infof("console running at: %s", consoleURL)
}
func BuildConsoleRouter(templateProvider TemplateProvider, templateVersion, staticDir string, opts gin.H) (*gin.Engine, error) {
var op errors.Op = "console.BuildConsoleRouter"
2020-04-07 12:23:20 +03:00
// An Engine instance with the Logger and Recovery middleware already attached.
gin.SetMode(gin.ReleaseMode)
r := gin.New()
if !templateProvider.DoTemplateExist(templateProvider.BasePath() + templateVersion + templateProvider.TemplateFilename()) {
templateVersion = "latest"
}
// Template console.gohtml
templateRender, err := templateProvider.LoadTemplates(templateProvider.BasePath()+templateVersion+"/", templateProvider.TemplateFilename())
if err != nil {
return nil, errors.E(op, fmt.Errorf("cannot fetch template: %w", err))
2020-04-07 12:23:20 +03:00
}
r.HTMLRender = templateRender
if staticDir != "" {
r.Use(static.Serve("/static", static.LocalFile(staticDir, false)))
opts["cliStaticDir"] = staticDir
}
r.GET("/*action", func(c *gin.Context) {
c.HTML(http.StatusOK, templateProvider.TemplateFilename(), &opts)
})
return r, nil
}