83 lines
2.2 KiB
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
|
|
}
|