shiori/internal/http/server.go
Felipe Martin cc7c75116d
refactor: migrate bookmark static pages to new http server (#775)
* migrate bookmark content route to new http server

* new archive page

* remove unused go generate comment

* database mock

* utils cleanup

* unused var

* domains refactor and tests

* fixed secret key type

* redirect to login on ui errors

* fixed archive folder with storage domain

* webroot documentation

* some bookmark route tests

* fixed error in bookmark domain for non existant bookmarks

* centralice errors

* add coverage data to unittests

* added tests, refactor storage to use afero

* removed mock to avoid increasing complexity

* using deps to copy files around

* remove config usage (to deps)

* remove handler-ui file
2023-12-28 18:18:32 +01:00

110 lines
2.8 KiB
Go

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/dependencies"
"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/http/templates"
"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
}
func (s *HttpServer) Setup(cfg *config.Config, deps *dependencies.Dependencies) (*HttpServer, error) {
if !cfg.Development {
gin.SetMode(gin.ReleaseMode)
}
s.engine = gin.New()
templates.SetupTemplates(s.engine)
// s.engine.Use(gzip.Gzip(gzip.DefaultCompression))
s.engine.Use(requestid.New())
if cfg.Http.AccessLog {
s.engine.Use(ginlogrus.Logger(deps.Log))
}
s.engine.Use(
middleware.AuthMiddleware(deps),
gin.Recovery(),
)
if cfg.Http.ServeWebUI {
routes.NewFrontendRoutes(s.logger, cfg).Setup(s.engine)
}
// 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)
s.handle("/system", routes.NewSystemRoutes(s.logger))
s.handle("/bookmark", routes.NewBookmarkRoutes(s.logger, deps))
s.handle("/api/v1", api_v1.NewAPIRoutes(s.logger, deps, legacyRoutes.HandleLogin))
s.handle("/swagger", routes.NewSwaggerAPIRoutes(s.logger))
s.http.Handler = s.engine
s.http.Addr = fmt.Sprintf("%s%d", cfg.Http.Address, cfg.Http.Port)
return s, nil
}
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("stopping 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")
}
}
func NewHttpServer(logger *logrus.Logger) *HttpServer {
return &HttpServer{
logger: logger,
http: &http.Server{},
}
}