2019-05-05 23:36:49 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-04-11 13:42:43 +03:00
|
|
|
"embed"
|
2023-04-03 15:40:57 +03:00
|
|
|
"flag"
|
2021-04-11 13:42:43 +03:00
|
|
|
"io/fs"
|
|
|
|
"log"
|
2021-06-23 18:22:51 +03:00
|
|
|
"net"
|
2021-04-11 13:42:43 +03:00
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
2021-01-30 13:17:37 +03:00
|
|
|
"github.com/emvi/logbuch"
|
2023-04-03 15:40:57 +03:00
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
middleware "github.com/go-chi/chi/v5/middleware"
|
|
|
|
"github.com/lpar/gzipped/v2"
|
|
|
|
httpSwagger "github.com/swaggo/http-swagger"
|
|
|
|
_ "gorm.io/driver/mysql"
|
|
|
|
_ "gorm.io/driver/postgres"
|
|
|
|
_ "gorm.io/driver/sqlite"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"gorm.io/gorm/logger"
|
|
|
|
|
2022-08-19 14:48:03 +03:00
|
|
|
conf "github.com/muety/wakapi/config"
|
2023-04-03 15:40:57 +03:00
|
|
|
"github.com/muety/wakapi/middlewares"
|
2022-08-19 14:48:03 +03:00
|
|
|
"github.com/muety/wakapi/migrations"
|
|
|
|
"github.com/muety/wakapi/repositories"
|
2020-03-31 13:22:17 +03:00
|
|
|
"github.com/muety/wakapi/routes"
|
2022-08-19 14:48:03 +03:00
|
|
|
"github.com/muety/wakapi/routes/api"
|
2023-04-03 15:40:57 +03:00
|
|
|
shieldsV1Routes "github.com/muety/wakapi/routes/compat/shields/v1"
|
|
|
|
wtV1Routes "github.com/muety/wakapi/routes/compat/wakatime/v1"
|
|
|
|
"github.com/muety/wakapi/routes/relay"
|
2020-03-31 13:22:17 +03:00
|
|
|
"github.com/muety/wakapi/services"
|
2022-08-19 14:48:03 +03:00
|
|
|
"github.com/muety/wakapi/services/mail"
|
2023-04-03 15:40:57 +03:00
|
|
|
docs "github.com/muety/wakapi/static/docs"
|
|
|
|
fsutils "github.com/muety/wakapi/utils/fs"
|
2019-05-05 23:36:49 +03:00
|
|
|
)
|
|
|
|
|
2021-04-11 13:42:43 +03:00
|
|
|
// Embed version.txt
|
2022-09-30 00:33:49 +03:00
|
|
|
//
|
2021-04-11 13:42:43 +03:00
|
|
|
//go:embed version.txt
|
|
|
|
var version string
|
|
|
|
|
|
|
|
// Embed static files
|
2022-09-30 00:33:49 +03:00
|
|
|
//
|
2021-04-11 13:42:43 +03:00
|
|
|
//go:embed static
|
|
|
|
var staticFiles embed.FS
|
|
|
|
|
2020-05-24 17:34:32 +03:00
|
|
|
var (
|
|
|
|
db *gorm.DB
|
2020-09-29 19:55:07 +03:00
|
|
|
config *conf.Config
|
2020-05-24 17:34:32 +03:00
|
|
|
)
|
|
|
|
|
2020-11-01 18:56:36 +03:00
|
|
|
var (
|
2020-11-08 12:12:49 +03:00
|
|
|
aliasRepository repositories.IAliasRepository
|
|
|
|
heartbeatRepository repositories.IHeartbeatRepository
|
|
|
|
userRepository repositories.IUserRepository
|
|
|
|
languageMappingRepository repositories.ILanguageMappingRepository
|
2021-06-11 21:59:34 +03:00
|
|
|
projectLabelRepository repositories.IProjectLabelRepository
|
2020-11-08 12:12:49 +03:00
|
|
|
summaryRepository repositories.ISummaryRepository
|
2022-10-02 01:01:39 +03:00
|
|
|
leaderboardRepository *repositories.LeaderboardRepository
|
2020-11-08 12:12:49 +03:00
|
|
|
keyValueRepository repositories.IKeyValueRepository
|
2021-08-07 11:16:50 +03:00
|
|
|
diagnosticsRepository repositories.IDiagnosticsRepository
|
2022-03-18 20:20:13 +03:00
|
|
|
metricsRepository *repositories.MetricsRepository
|
2020-11-01 18:56:36 +03:00
|
|
|
)
|
|
|
|
|
2020-05-24 17:34:32 +03:00
|
|
|
var (
|
2020-11-08 12:12:49 +03:00
|
|
|
aliasService services.IAliasService
|
|
|
|
heartbeatService services.IHeartbeatService
|
|
|
|
userService services.IUserService
|
|
|
|
languageMappingService services.ILanguageMappingService
|
2021-06-11 21:59:34 +03:00
|
|
|
projectLabelService services.IProjectLabelService
|
2021-12-14 17:30:03 +03:00
|
|
|
durationService services.IDurationService
|
2020-11-08 12:12:49 +03:00
|
|
|
summaryService services.ISummaryService
|
2022-10-02 01:01:39 +03:00
|
|
|
leaderboardService services.ILeaderboardService
|
2020-11-08 12:12:49 +03:00
|
|
|
aggregationService services.IAggregationService
|
2021-04-05 23:57:57 +03:00
|
|
|
mailService services.IMailService
|
2020-11-08 12:12:49 +03:00
|
|
|
keyValueService services.IKeyValueService
|
2021-04-30 15:07:14 +03:00
|
|
|
reportService services.IReportService
|
2021-08-07 11:16:50 +03:00
|
|
|
diagnosticsService services.IDiagnosticsService
|
2022-12-01 22:26:03 +03:00
|
|
|
housekeepingService services.IHousekeepingService
|
2021-01-17 11:24:09 +03:00
|
|
|
miscService services.IMiscService
|
2020-05-24 17:34:32 +03:00
|
|
|
)
|
|
|
|
|
2020-03-31 12:24:44 +03:00
|
|
|
// TODO: Refactor entire project to be structured after business domains
|
|
|
|
|
2021-02-07 13:54:07 +03:00
|
|
|
// @title Wakapi API
|
|
|
|
// @version 1.0
|
|
|
|
// @description REST API to interact with [Wakapi](https://wakapi.dev)
|
|
|
|
// @description
|
|
|
|
// @description ## Authentication
|
|
|
|
// @description Set header `Authorization` to your API Key encoded as Base64 and prefixed with `Basic`
|
|
|
|
// @description **Example:** `Basic ODY2NDhkNzQtMTljNS00NTJiLWJhMDEtZmIzZWM3MGQ0YzJmCg==`
|
|
|
|
|
|
|
|
// @contact.name Ferdinand Mütsch
|
|
|
|
// @contact.url https://github.com/muety
|
|
|
|
// @contact.email ferdinand@muetsch.io
|
|
|
|
|
|
|
|
// @license.name GPL-3.0
|
|
|
|
// @license.url https://github.com/muety/wakapi/blob/master/LICENSE
|
|
|
|
|
|
|
|
// @securitydefinitions.apikey ApiKeyAuth
|
|
|
|
// @in header
|
|
|
|
// @name Authorization
|
|
|
|
|
2019-05-05 23:36:49 +03:00
|
|
|
func main() {
|
2023-04-03 15:40:57 +03:00
|
|
|
var versionFlag = flag.Bool("version", false, "print version")
|
|
|
|
var configFlag = flag.String("config", conf.DefaultConfigPath, "config file location")
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
if *versionFlag {
|
|
|
|
print(version)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
config = conf.Load(*configFlag, version)
|
2020-05-24 17:34:32 +03:00
|
|
|
|
2022-09-30 00:33:49 +03:00
|
|
|
// Configure Swagger docs
|
2022-09-30 12:02:32 +03:00
|
|
|
docs.SwaggerInfo.BasePath = config.Server.BasePath + "/api"
|
2022-09-30 00:33:49 +03:00
|
|
|
|
2021-01-30 13:17:37 +03:00
|
|
|
// Set log level
|
2020-04-25 23:53:55 +03:00
|
|
|
if config.IsDev() {
|
2021-01-30 13:17:37 +03:00
|
|
|
logbuch.SetLevel(logbuch.LevelDebug)
|
|
|
|
} else {
|
|
|
|
logbuch.SetLevel(logbuch.LevelInfo)
|
2020-04-25 23:53:55 +03:00
|
|
|
}
|
2023-04-03 15:40:57 +03:00
|
|
|
logbuch.Info("Wakapi " + version)
|
2019-05-05 23:36:49 +03:00
|
|
|
|
2021-01-31 20:29:24 +03:00
|
|
|
// Set up GORM
|
|
|
|
gormLogger := logger.New(
|
|
|
|
log.New(os.Stdout, "", log.LstdFlags),
|
|
|
|
logger.Config{
|
|
|
|
SlowThreshold: time.Minute,
|
|
|
|
Colorful: false,
|
|
|
|
LogLevel: logger.Silent,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
2019-05-11 18:49:56 +03:00
|
|
|
// Connect to database
|
2020-05-24 17:34:32 +03:00
|
|
|
var err error
|
2022-12-27 06:39:32 +03:00
|
|
|
logbuch.Info("starting with %s database", config.Db.Dialect)
|
2022-12-16 14:33:01 +03:00
|
|
|
db, err = gorm.Open(config.Db.GetDialector(), &gorm.Config{Logger: gormLogger}, conf.GetWakapiDBOpts(&config.Db))
|
2022-08-19 14:48:03 +03:00
|
|
|
if err != nil {
|
|
|
|
logbuch.Error(err.Error())
|
|
|
|
logbuch.Fatal("could not open database")
|
|
|
|
}
|
2020-11-01 22:14:10 +03:00
|
|
|
|
2020-11-06 19:09:41 +03:00
|
|
|
if config.IsDev() {
|
|
|
|
db = db.Debug()
|
|
|
|
}
|
2021-04-27 09:50:39 +03:00
|
|
|
sqlDb, err := db.DB()
|
2020-11-01 22:14:10 +03:00
|
|
|
sqlDb.SetMaxIdleConns(int(config.Db.MaxConn))
|
|
|
|
sqlDb.SetMaxOpenConns(int(config.Db.MaxConn))
|
2019-05-05 23:36:49 +03:00
|
|
|
if err != nil {
|
2021-01-30 13:17:37 +03:00
|
|
|
logbuch.Error(err.Error())
|
|
|
|
logbuch.Fatal("could not connect to database")
|
2019-05-05 23:36:49 +03:00
|
|
|
}
|
2020-11-01 22:14:10 +03:00
|
|
|
defer sqlDb.Close()
|
2019-05-11 18:49:56 +03:00
|
|
|
|
|
|
|
// Migrate database schema
|
2022-04-18 16:18:01 +03:00
|
|
|
if !config.SkipMigrations {
|
|
|
|
migrations.Run(db, config)
|
|
|
|
}
|
2019-05-05 23:36:49 +03:00
|
|
|
|
2020-11-01 18:56:36 +03:00
|
|
|
// Repositories
|
|
|
|
aliasRepository = repositories.NewAliasRepository(db)
|
|
|
|
heartbeatRepository = repositories.NewHeartbeatRepository(db)
|
|
|
|
userRepository = repositories.NewUserRepository(db)
|
2020-11-01 22:14:10 +03:00
|
|
|
languageMappingRepository = repositories.NewLanguageMappingRepository(db)
|
2021-06-11 21:59:34 +03:00
|
|
|
projectLabelRepository = repositories.NewProjectLabelRepository(db)
|
2020-11-01 18:56:36 +03:00
|
|
|
summaryRepository = repositories.NewSummaryRepository(db)
|
2022-10-02 01:01:39 +03:00
|
|
|
leaderboardRepository = repositories.NewLeaderboardRepository(db)
|
2020-11-01 18:56:36 +03:00
|
|
|
keyValueRepository = repositories.NewKeyValueRepository(db)
|
2021-08-07 11:16:50 +03:00
|
|
|
diagnosticsRepository = repositories.NewDiagnosticsRepository(db)
|
2022-03-18 20:20:13 +03:00
|
|
|
metricsRepository = repositories.NewMetricsRepository(db)
|
2020-11-01 18:56:36 +03:00
|
|
|
|
2019-05-06 01:40:41 +03:00
|
|
|
// Services
|
2021-08-07 00:28:03 +03:00
|
|
|
mailService = mail.NewMailService()
|
2020-11-01 18:56:36 +03:00
|
|
|
aliasService = services.NewAliasService(aliasRepository)
|
2021-08-07 00:28:03 +03:00
|
|
|
userService = services.NewUserService(mailService, userRepository)
|
2020-11-01 22:14:10 +03:00
|
|
|
languageMappingService = services.NewLanguageMappingService(languageMappingRepository)
|
2021-06-11 21:59:34 +03:00
|
|
|
projectLabelService = services.NewProjectLabelService(projectLabelRepository)
|
2020-11-01 22:14:10 +03:00
|
|
|
heartbeatService = services.NewHeartbeatService(heartbeatRepository, languageMappingService)
|
2021-12-14 17:30:03 +03:00
|
|
|
durationService = services.NewDurationService(heartbeatService)
|
|
|
|
summaryService = services.NewSummaryService(summaryRepository, durationService, aliasService, projectLabelService)
|
2022-10-02 01:01:39 +03:00
|
|
|
leaderboardService = services.NewLeaderboardService(leaderboardRepository, summaryService, userService)
|
2020-11-01 18:56:36 +03:00
|
|
|
aggregationService = services.NewAggregationService(userService, summaryService, heartbeatService)
|
|
|
|
keyValueService = services.NewKeyValueService(keyValueRepository)
|
2021-04-30 15:07:14 +03:00
|
|
|
reportService = services.NewReportService(summaryService, userService, mailService)
|
2021-08-07 11:16:50 +03:00
|
|
|
diagnosticsService = services.NewDiagnosticsService(diagnosticsRepository)
|
2022-12-01 22:26:03 +03:00
|
|
|
housekeepingService = services.NewHousekeepingService(userService, heartbeatService, summaryService)
|
2022-12-29 19:12:34 +03:00
|
|
|
miscService = services.NewMiscService(userService, heartbeatService, summaryService, keyValueService, mailService)
|
2020-02-20 16:28:55 +03:00
|
|
|
|
2021-01-17 11:24:09 +03:00
|
|
|
// Schedule background tasks
|
2023-04-03 15:40:57 +03:00
|
|
|
go conf.StartJobs()
|
2022-04-18 22:07:15 +03:00
|
|
|
go aggregationService.Schedule()
|
2022-11-20 12:10:24 +03:00
|
|
|
go leaderboardService.Schedule()
|
2022-04-18 22:07:15 +03:00
|
|
|
go reportService.Schedule()
|
2022-12-01 22:26:03 +03:00
|
|
|
go housekeepingService.Schedule()
|
2022-12-23 15:41:32 +03:00
|
|
|
go miscService.Schedule()
|
2019-05-06 01:40:41 +03:00
|
|
|
|
2020-11-08 14:46:12 +03:00
|
|
|
routes.Init()
|
|
|
|
|
2021-02-03 23:28:02 +03:00
|
|
|
// API Handlers
|
|
|
|
healthApiHandler := api.NewHealthApiHandler(db)
|
2021-02-06 22:09:08 +03:00
|
|
|
heartbeatApiHandler := api.NewHeartbeatApiHandler(userService, heartbeatService, languageMappingService)
|
|
|
|
summaryApiHandler := api.NewSummaryApiHandler(userService, summaryService)
|
2022-03-18 20:20:13 +03:00
|
|
|
metricsHandler := api.NewMetricsHandler(userService, summaryService, heartbeatService, keyValueService, metricsRepository)
|
2021-08-07 11:16:50 +03:00
|
|
|
diagnosticsHandler := api.NewDiagnosticsApiHandler(userService, diagnosticsService)
|
2022-02-17 11:53:37 +03:00
|
|
|
avatarHandler := api.NewAvatarHandler()
|
2022-04-18 12:39:26 +03:00
|
|
|
badgeHandler := api.NewBadgeHandler(userService, summaryService)
|
2021-02-03 23:28:02 +03:00
|
|
|
|
|
|
|
// Compat Handlers
|
2021-09-06 20:01:49 +03:00
|
|
|
wakatimeV1StatusBarHandler := wtV1Routes.NewStatusBarHandler(userService, summaryService)
|
2021-02-06 22:09:08 +03:00
|
|
|
wakatimeV1AllHandler := wtV1Routes.NewAllTimeHandler(userService, summaryService)
|
|
|
|
wakatimeV1SummariesHandler := wtV1Routes.NewSummariesHandler(userService, summaryService)
|
|
|
|
wakatimeV1StatsHandler := wtV1Routes.NewStatsHandler(userService, summaryService)
|
2021-04-30 11:12:28 +03:00
|
|
|
wakatimeV1UsersHandler := wtV1Routes.NewUsersHandler(userService, heartbeatService)
|
2021-05-01 14:52:03 +03:00
|
|
|
wakatimeV1ProjectsHandler := wtV1Routes.NewProjectsHandler(userService, heartbeatService)
|
2022-01-28 14:28:47 +03:00
|
|
|
wakatimeV1HeartbeatsHandler := wtV1Routes.NewHeartbeatHandler(userService, heartbeatService)
|
2021-02-03 23:28:02 +03:00
|
|
|
shieldV1BadgeHandler := shieldsV1Routes.NewBadgeHandler(summaryService, userService)
|
|
|
|
|
|
|
|
// MVC Handlers
|
2023-01-18 03:27:07 +03:00
|
|
|
summaryHandler := routes.NewSummaryHandler(summaryService, userService, keyValueService)
|
2021-06-12 11:44:19 +03:00
|
|
|
settingsHandler := routes.NewSettingsHandler(userService, heartbeatService, summaryService, aliasService, aggregationService, languageMappingService, projectLabelService, keyValueService, mailService)
|
2022-12-29 19:12:34 +03:00
|
|
|
subscriptionHandler := routes.NewSubscriptionHandler(userService, mailService, keyValueService)
|
2022-10-03 11:53:27 +03:00
|
|
|
leaderboardHandler := routes.NewLeaderboardHandler(userService, leaderboardService)
|
2021-01-17 11:24:09 +03:00
|
|
|
homeHandler := routes.NewHomeHandler(keyValueService)
|
2021-04-05 23:57:57 +03:00
|
|
|
loginHandler := routes.NewLoginHandler(userService, mailService)
|
2020-11-06 23:19:54 +03:00
|
|
|
imprintHandler := routes.NewImprintHandler(keyValueService)
|
2019-05-06 01:40:41 +03:00
|
|
|
|
2021-10-11 12:00:50 +03:00
|
|
|
// Other Handlers
|
|
|
|
relayHandler := relay.NewRelayHandler()
|
|
|
|
|
2023-03-03 22:40:50 +03:00
|
|
|
// Setup Routing
|
|
|
|
router := chi.NewRouter()
|
|
|
|
router.Use(
|
|
|
|
middleware.CleanPath,
|
|
|
|
middleware.StripSlashes,
|
|
|
|
middleware.Recoverer,
|
|
|
|
middlewares.NewPrincipalMiddleware(),
|
|
|
|
middlewares.NewLoggingMiddleware(logbuch.Info, []string{
|
|
|
|
"/assets",
|
|
|
|
"/favicon",
|
|
|
|
"/service-worker.js",
|
|
|
|
"/api/health",
|
2023-03-25 01:16:36 +03:00
|
|
|
"/api/avatar",
|
2023-03-03 22:40:50 +03:00
|
|
|
}),
|
|
|
|
)
|
2021-03-24 00:12:15 +03:00
|
|
|
if config.Sentry.Dsn != "" {
|
2021-04-29 22:19:43 +03:00
|
|
|
router.Use(middlewares.NewSentryMiddleware())
|
2021-03-24 00:12:15 +03:00
|
|
|
}
|
2023-03-03 22:40:50 +03:00
|
|
|
|
|
|
|
// Setup Sub Routers
|
|
|
|
rootRouter := chi.NewRouter()
|
2021-04-16 13:35:49 +03:00
|
|
|
rootRouter.Use(middlewares.NewSecurityMiddleware())
|
2021-01-30 12:34:52 +03:00
|
|
|
|
2023-03-03 22:40:50 +03:00
|
|
|
apiRouter := chi.NewRouter()
|
|
|
|
|
|
|
|
// Hook sub routers
|
|
|
|
router.Mount("/", rootRouter)
|
|
|
|
router.Mount("/api", apiRouter)
|
|
|
|
|
2021-01-30 12:34:52 +03:00
|
|
|
// Route registrations
|
2021-02-03 23:28:02 +03:00
|
|
|
homeHandler.RegisterRoutes(rootRouter)
|
|
|
|
loginHandler.RegisterRoutes(rootRouter)
|
|
|
|
imprintHandler.RegisterRoutes(rootRouter)
|
|
|
|
summaryHandler.RegisterRoutes(rootRouter)
|
2022-10-03 11:53:27 +03:00
|
|
|
leaderboardHandler.RegisterRoutes(rootRouter)
|
2021-02-03 23:28:02 +03:00
|
|
|
settingsHandler.RegisterRoutes(rootRouter)
|
2022-12-21 01:08:59 +03:00
|
|
|
subscriptionHandler.RegisterRoutes(rootRouter)
|
2021-10-11 12:00:50 +03:00
|
|
|
relayHandler.RegisterRoutes(rootRouter)
|
2021-02-03 23:28:02 +03:00
|
|
|
|
|
|
|
// API route registrations
|
|
|
|
summaryApiHandler.RegisterRoutes(apiRouter)
|
|
|
|
healthApiHandler.RegisterRoutes(apiRouter)
|
|
|
|
heartbeatApiHandler.RegisterRoutes(apiRouter)
|
2021-02-12 20:37:30 +03:00
|
|
|
metricsHandler.RegisterRoutes(apiRouter)
|
2021-08-07 11:16:50 +03:00
|
|
|
diagnosticsHandler.RegisterRoutes(apiRouter)
|
2022-02-17 11:53:37 +03:00
|
|
|
avatarHandler.RegisterRoutes(apiRouter)
|
2022-04-18 12:39:26 +03:00
|
|
|
badgeHandler.RegisterRoutes(apiRouter)
|
2021-09-06 20:01:49 +03:00
|
|
|
wakatimeV1StatusBarHandler.RegisterRoutes(apiRouter)
|
2021-02-07 00:40:54 +03:00
|
|
|
wakatimeV1AllHandler.RegisterRoutes(apiRouter)
|
|
|
|
wakatimeV1SummariesHandler.RegisterRoutes(apiRouter)
|
|
|
|
wakatimeV1StatsHandler.RegisterRoutes(apiRouter)
|
2021-04-30 11:12:28 +03:00
|
|
|
wakatimeV1UsersHandler.RegisterRoutes(apiRouter)
|
2021-05-01 14:52:03 +03:00
|
|
|
wakatimeV1ProjectsHandler.RegisterRoutes(apiRouter)
|
2022-01-28 14:28:47 +03:00
|
|
|
wakatimeV1HeartbeatsHandler.RegisterRoutes(apiRouter)
|
2021-02-07 00:40:54 +03:00
|
|
|
shieldV1BadgeHandler.RegisterRoutes(apiRouter)
|
2020-09-06 13:15:46 +03:00
|
|
|
|
2020-02-20 16:28:55 +03:00
|
|
|
// Static Routes
|
2021-04-11 13:42:43 +03:00
|
|
|
// https://github.com/golang/go/issues/43431
|
2021-04-16 13:24:19 +03:00
|
|
|
embeddedStatic, _ := fs.Sub(staticFiles, "static")
|
|
|
|
static := conf.ChooseFS("static", embeddedStatic)
|
2021-12-26 21:29:17 +03:00
|
|
|
|
2023-01-08 01:59:50 +03:00
|
|
|
assetsStaticFs := fsutils.NewExistsHttpFS(fsutils.NewExistsFS(static).WithCache(!config.IsDev()))
|
|
|
|
assetsFileServer := http.FileServer(assetsStaticFs)
|
|
|
|
if !config.IsDev() {
|
|
|
|
assetsFileServer = gzipped.FileServer(assetsStaticFs)
|
|
|
|
}
|
|
|
|
staticFileServer := http.FileServer(http.FS(fsutils.NeuteredFileSystem{FS: static}))
|
2021-12-20 16:51:05 +03:00
|
|
|
|
2023-03-03 22:40:50 +03:00
|
|
|
router.Get("/contribute.json", staticFileServer.ServeHTTP)
|
|
|
|
router.Get("/assets/*", assetsFileServer.ServeHTTP)
|
|
|
|
router.Get("/swagger-ui", http.RedirectHandler("swagger-ui/", http.StatusMovedPermanently).ServeHTTP) // https://github.com/swaggo/http-swagger/issues/44
|
|
|
|
router.Get("/swagger-ui/*", httpSwagger.WrapHandler)
|
2020-02-21 14:41:29 +03:00
|
|
|
|
2019-05-05 23:36:49 +03:00
|
|
|
// Listen HTTP
|
2020-12-13 00:07:00 +03:00
|
|
|
listen(router)
|
|
|
|
}
|
|
|
|
|
|
|
|
func listen(handler http.Handler) {
|
2021-06-23 18:22:51 +03:00
|
|
|
var s4, s6, sSocket *http.Server
|
2020-12-13 00:07:00 +03:00
|
|
|
|
|
|
|
// IPv4
|
2022-12-06 15:19:18 +03:00
|
|
|
if config.Server.ListenIpV4 != "-" && config.Server.ListenIpV4 != "" {
|
2020-12-13 00:07:00 +03:00
|
|
|
bindString4 := config.Server.ListenIpV4 + ":" + strconv.Itoa(config.Server.Port)
|
|
|
|
s4 = &http.Server{
|
|
|
|
Handler: handler,
|
|
|
|
Addr: bindString4,
|
2021-06-24 22:56:47 +03:00
|
|
|
ReadTimeout: time.Duration(config.Server.TimeoutSec) * time.Second,
|
|
|
|
WriteTimeout: time.Duration(config.Server.TimeoutSec) * time.Second,
|
2020-12-13 00:07:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// IPv6
|
2022-12-06 15:19:18 +03:00
|
|
|
if config.Server.ListenIpV6 != "-" && config.Server.ListenIpV6 != "" {
|
2020-12-13 00:07:00 +03:00
|
|
|
bindString6 := "[" + config.Server.ListenIpV6 + "]:" + strconv.Itoa(config.Server.Port)
|
|
|
|
s6 = &http.Server{
|
|
|
|
Handler: handler,
|
|
|
|
Addr: bindString6,
|
2021-06-24 22:56:47 +03:00
|
|
|
ReadTimeout: time.Duration(config.Server.TimeoutSec) * time.Second,
|
|
|
|
WriteTimeout: time.Duration(config.Server.TimeoutSec) * time.Second,
|
2020-12-13 00:07:00 +03:00
|
|
|
}
|
2019-05-05 23:36:49 +03:00
|
|
|
}
|
2020-12-13 00:07:00 +03:00
|
|
|
|
2021-06-23 18:22:51 +03:00
|
|
|
// UNIX domain socket
|
2022-12-06 23:01:21 +03:00
|
|
|
if config.Server.ListenSocket != "-" && config.Server.ListenSocket != "" {
|
2021-07-10 12:10:55 +03:00
|
|
|
// Remove if exists
|
|
|
|
if _, err := os.Stat(config.Server.ListenSocket); err == nil {
|
2022-12-30 15:32:05 +03:00
|
|
|
logbuch.Info("👉 Removing unix socket %s", config.Server.ListenSocket)
|
2021-07-10 12:10:55 +03:00
|
|
|
if err := os.Remove(config.Server.ListenSocket); err != nil {
|
|
|
|
logbuch.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
}
|
2021-06-23 18:22:51 +03:00
|
|
|
sSocket = &http.Server{
|
2021-06-24 22:40:51 +03:00
|
|
|
Handler: handler,
|
2021-06-24 22:56:47 +03:00
|
|
|
ReadTimeout: time.Duration(config.Server.TimeoutSec) * time.Second,
|
|
|
|
WriteTimeout: time.Duration(config.Server.TimeoutSec) * time.Second,
|
2021-06-23 18:22:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-13 00:07:00 +03:00
|
|
|
if config.UseTLS() {
|
|
|
|
if s4 != nil {
|
2022-12-30 15:32:05 +03:00
|
|
|
logbuch.Info("👉 Listening for HTTPS on %s... ✅", s4.Addr)
|
2021-01-05 13:28:51 +03:00
|
|
|
go func() {
|
|
|
|
if err := s4.ListenAndServeTLS(config.Server.TlsCertPath, config.Server.TlsKeyPath); err != nil {
|
2021-01-30 13:17:37 +03:00
|
|
|
logbuch.Fatal(err.Error())
|
2021-01-05 13:28:51 +03:00
|
|
|
}
|
|
|
|
}()
|
2020-12-13 00:07:00 +03:00
|
|
|
}
|
|
|
|
if s6 != nil {
|
2022-12-30 15:32:05 +03:00
|
|
|
logbuch.Info("👉 Listening for HTTPS on %s... ✅", s6.Addr)
|
2021-01-05 13:28:51 +03:00
|
|
|
go func() {
|
|
|
|
if err := s6.ListenAndServeTLS(config.Server.TlsCertPath, config.Server.TlsKeyPath); err != nil {
|
2021-01-30 13:17:37 +03:00
|
|
|
logbuch.Fatal(err.Error())
|
2021-01-05 13:28:51 +03:00
|
|
|
}
|
|
|
|
}()
|
2020-12-13 00:07:00 +03:00
|
|
|
}
|
2021-06-23 18:22:51 +03:00
|
|
|
if sSocket != nil {
|
2022-12-30 15:32:05 +03:00
|
|
|
logbuch.Info("👉 Listening for HTTPS on %s... ✅", config.Server.ListenSocket)
|
2021-06-23 18:22:51 +03:00
|
|
|
go func() {
|
|
|
|
unixListener, err := net.Listen("unix", config.Server.ListenSocket)
|
|
|
|
if err != nil {
|
|
|
|
logbuch.Fatal(err.Error())
|
|
|
|
}
|
2023-01-08 19:14:43 +03:00
|
|
|
if err := os.Chmod(config.Server.ListenSocket, os.FileMode(config.Server.ListenSocketMode)); err != nil {
|
|
|
|
logbuch.Warn("failed to set user permissions for unix socket, %v", err)
|
|
|
|
}
|
2021-06-23 18:22:51 +03:00
|
|
|
if err := sSocket.ServeTLS(unixListener, config.Server.TlsCertPath, config.Server.TlsKeyPath); err != nil {
|
|
|
|
logbuch.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2020-12-13 00:07:00 +03:00
|
|
|
} else {
|
|
|
|
if s4 != nil {
|
2022-12-30 15:32:05 +03:00
|
|
|
logbuch.Info("👉 Listening for HTTP on %s... ✅", s4.Addr)
|
2021-01-05 13:28:51 +03:00
|
|
|
go func() {
|
|
|
|
if err := s4.ListenAndServe(); err != nil {
|
2021-01-30 13:17:37 +03:00
|
|
|
logbuch.Fatal(err.Error())
|
2021-01-05 13:28:51 +03:00
|
|
|
}
|
|
|
|
}()
|
2020-12-13 00:07:00 +03:00
|
|
|
}
|
|
|
|
if s6 != nil {
|
2022-12-30 15:32:05 +03:00
|
|
|
logbuch.Info("👉 Listening for HTTP on %s... ✅", s6.Addr)
|
2021-01-05 13:28:51 +03:00
|
|
|
go func() {
|
|
|
|
if err := s6.ListenAndServe(); err != nil {
|
2021-01-30 13:17:37 +03:00
|
|
|
logbuch.Fatal(err.Error())
|
2021-01-05 13:28:51 +03:00
|
|
|
}
|
|
|
|
}()
|
2020-12-13 00:07:00 +03:00
|
|
|
}
|
2021-06-23 18:22:51 +03:00
|
|
|
if sSocket != nil {
|
2022-12-30 15:32:05 +03:00
|
|
|
logbuch.Info("👉 Listening for HTTP on %s... ✅", config.Server.ListenSocket)
|
2021-06-23 18:22:51 +03:00
|
|
|
go func() {
|
|
|
|
unixListener, err := net.Listen("unix", config.Server.ListenSocket)
|
|
|
|
if err != nil {
|
|
|
|
logbuch.Fatal(err.Error())
|
|
|
|
}
|
2023-01-08 19:14:43 +03:00
|
|
|
if err := os.Chmod(config.Server.ListenSocket, os.FileMode(config.Server.ListenSocketMode)); err != nil {
|
|
|
|
logbuch.Warn("failed to set user permissions for unix socket, %v", err)
|
|
|
|
}
|
2021-06-23 18:22:51 +03:00
|
|
|
if err := sSocket.Serve(unixListener); err != nil {
|
|
|
|
logbuch.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2020-12-13 00:07:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
<-make(chan interface{}, 1)
|
2019-05-05 23:36:49 +03:00
|
|
|
}
|