sshpoke/internal/api/rest/server.go

83 lines
2.2 KiB
Go

//go:generate swag init --parseInternal --parseDependency --parseDepth 1 --output docs -g internal/api/rest/server.go --dir ../../../
package rest
import (
"context"
"errors"
"net"
"net/http"
"strconv"
"github.com/Neur0toxine/sshpoke/internal/api/rest/handler"
"github.com/Neur0toxine/sshpoke/internal/api/rest/middleware"
"github.com/Neur0toxine/sshpoke/internal/logger"
"github.com/gin-contrib/secure"
"github.com/gin-gonic/gin"
cors "github.com/rs/cors/wrapper/gin"
"go.uber.org/zap"
)
const (
DefaultPort = 25680
httpProto = "http://"
)
// @title sshpoke REST API
// @version 1.0
// @BasePath /api/v1
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description Rest API token (leave empty if it's not provided in config).
func StartServer(ctx context.Context, token string, port int, log *zap.SugaredLogger, debug bool) {
if !debug {
gin.SetMode(gin.ReleaseMode)
}
logMiddleware := middleware.SetupLogger(log)
g := gin.New()
g.Use(logMiddleware)
g.Use(cors.New(cors.Options{
AllowedOrigins: []string{
httpProto + net.JoinHostPort("localhost", strconv.Itoa(port)),
httpProto + net.JoinHostPort("127.0.0.1", strconv.Itoa(port)),
},
AllowedMethods: []string{"HEAD", "GET", "POST", "PUT", "DELETE"},
MaxAge: 60 * 10,
AllowCredentials: true,
}))
g.Use(secure.New(secureConfig()))
router(g, token)
srv := &http.Server{
Addr: net.JoinHostPort("127.0.0.1", strconv.Itoa(port)),
Handler: g,
}
go func() {
<-ctx.Done()
if err := srv.Shutdown(ctx); err != nil {
logger.Sugar.Errorf("failed to stop the server gracefully: %s", err)
}
}()
err := srv.ListenAndServe()
if err != nil && !errors.Is(err, http.ErrServerClosed) {
logger.Sugar.Errorf("cannot start Rest API server on port %d: %s", port, err)
}
}
func router(g *gin.Engine, token string) {
g.GET("/swagger/*any", handler.DocsHandler())
api := g.Group("/api/v1")
{
api.Use(middleware.Auth(token))
api.GET("/config", handler.Config)
api.GET("/status", handler.Status)
}
}
func secureConfig() secure.Config {
cfg := secure.DefaultConfig()
cfg.SSLRedirect = false
cfg.ContentSecurityPolicy = cfg.ContentSecurityPolicy + " 'unsafe-inline'; img-src 'self' data:"
return cfg
}