2023-07-17 21:30:18 +08:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
"github.com/gin-contrib/requestid"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/go-shiori/shiori/internal/config"
|
|
|
|
"github.com/go-shiori/shiori/internal/http/middleware"
|
|
|
|
"github.com/go-shiori/shiori/internal/http/routes"
|
|
|
|
api_v1 "github.com/go-shiori/shiori/internal/http/routes/api/v1"
|
|
|
|
"github.com/go-shiori/shiori/internal/model"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
ginlogrus "github.com/toorop/gin-logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type HttpServer struct {
|
|
|
|
engine *gin.Engine
|
|
|
|
http *http.Server
|
|
|
|
logger *logrus.Logger
|
|
|
|
}
|
|
|
|
|
2023-07-20 00:25:41 +08:00
|
|
|
func (s *HttpServer) Setup(cfg *config.Config, deps *config.Dependencies) *HttpServer {
|
|
|
|
if !cfg.Development {
|
|
|
|
gin.SetMode(gin.ReleaseMode)
|
|
|
|
}
|
|
|
|
|
|
|
|
s.engine = gin.New()
|
|
|
|
|
|
|
|
s.engine.Use(requestid.New())
|
|
|
|
|
|
|
|
if cfg.Http.AccessLog {
|
|
|
|
s.engine.Use(ginlogrus.Logger(deps.Log))
|
|
|
|
}
|
|
|
|
|
2023-07-17 21:30:18 +08:00
|
|
|
s.engine.Use(
|
|
|
|
middleware.AuthMiddleware(deps),
|
|
|
|
gin.Recovery(),
|
|
|
|
)
|
|
|
|
|
2023-07-20 00:25:41 +08:00
|
|
|
if cfg.Http.ServeWebUI {
|
|
|
|
routes.NewFrontendRoutes(s.logger, cfg).Setup(s.engine)
|
2023-07-17 21:30:18 +08:00
|
|
|
}
|
|
|
|
|
2023-07-20 00:25:41 +08:00
|
|
|
// LegacyRoutes will be here until we migrate everything from internal/webserver to this new
|
|
|
|
// package.
|
|
|
|
legacyRoutes := routes.NewLegacyAPIRoutes(s.logger, deps, cfg)
|
|
|
|
legacyRoutes.Setup(s.engine)
|
|
|
|
|
2023-07-17 21:30:18 +08:00
|
|
|
s.handle("/system", routes.NewSystemRoutes(s.logger))
|
2023-07-20 00:25:41 +08:00
|
|
|
// s.handle("/bookmark", routes.NewBookmarkRoutes(s.logger, deps))
|
|
|
|
s.handle("/api/v1", api_v1.NewAPIRoutes(s.logger, deps, legacyRoutes.HandleLogin))
|
2023-07-17 21:30:18 +08:00
|
|
|
s.handle("/swagger", routes.NewSwaggerAPIRoutes(s.logger))
|
|
|
|
|
|
|
|
s.http.Handler = s.engine
|
2023-07-20 00:25:41 +08:00
|
|
|
s.http.Addr = fmt.Sprintf("%s%d", cfg.Http.Address, cfg.Http.Port)
|
2023-07-17 21:30:18 +08:00
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HttpServer) handle(path string, routes model.Routes) {
|
|
|
|
group := s.engine.Group(path)
|
|
|
|
routes.Setup(group)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HttpServer) Start(_ context.Context) error {
|
|
|
|
s.logger.WithField("addr", s.http.Addr).Info("starting http server")
|
|
|
|
go func() {
|
|
|
|
if err := s.http.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
|
|
s.logger.Fatalf("listen and serve error: %s\n", err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HttpServer) Stop(ctx context.Context) error {
|
|
|
|
s.logger.WithField("addr", s.http.Addr).Info("stoppping http server")
|
|
|
|
return s.http.Shutdown(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HttpServer) WaitStop(ctx context.Context) {
|
|
|
|
signals := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
|
|
|
|
sig := <-signals
|
|
|
|
s.logger.WithField("signal", sig.String()).Info("signal received, shutting down")
|
|
|
|
|
|
|
|
if err := s.Stop(ctx); err != nil {
|
|
|
|
s.logger.WithError(err).Error("error stopping server")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-20 00:25:41 +08:00
|
|
|
func NewHttpServer(logger *logrus.Logger) *HttpServer {
|
2023-07-17 21:30:18 +08:00
|
|
|
return &HttpServer{
|
|
|
|
logger: logger,
|
|
|
|
http: &http.Server{},
|
|
|
|
}
|
|
|
|
}
|