package serve import ( "database/sql" "log" "net/http" "github.com/spf13/cobra" "github.com/spf13/viper" httpSwagger "github.com/swaggo/http-swagger" "github.com/uptrace/bun" "github.com/uptrace/bun/dialect/sqlitedialect" "github.com/uptrace/bun/driver/sqliteshim" "github.com/uptrace/bun/extra/bunotel" "github.com/uptrace/bunrouter" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.uber.org/zap" _ "gitea.konchin.com/ytshih/inp2025/game/backend/docs" "gitea.konchin.com/ytshih/inp2025/game/backend/handlers/api" "gitea.konchin.com/ytshih/inp2025/game/backend/handlers/auth" "gitea.konchin.com/ytshih/inp2025/game/backend/middlewares" "gitea.konchin.com/ytshih/inp2025/game/implements" "gitea.konchin.com/ytshih/inp2025/game/tracing" "gitea.konchin.com/ytshih/inp2025/game/utils" ) // @title Intro. to Network Programming Game // @version 0.0.1-alpha // @license.name 0BSD // @BasePath / var backendCmd = &cobra.Command{ Use: "backend", Short: "Game backend", Run: func(cmd *cobra.Command, args []string) { ctx := cmd.Context() tracing.InitTracer("game backend") tracing.Logger.Ctx(ctx). Debug("connect to sql", zap.String("sql.url", "file:"+viper.GetString("sqlite-file")+"?cache=shared&mode=rwc")) sqldb, err := sql.Open(sqliteshim.ShimName, "file:"+viper.GetString("sqlite-file")+"?cache=shared&mode=rwc") if err != nil { tracing.Logger.Ctx(ctx). Panic("failed to init sqlite", zap.Error(err)) panic(err) } bunDB := bun.NewDB(sqldb, sqlitedialect.New()) bunDB.AddQueryHook(bunotel.NewQueryHook(bunotel.WithDBName("sqlite"))) if err := utils.InitDB(ctx, bunDB); err != nil { tracing.Logger.Ctx(ctx). Panic("failed to init db schema", zap.Error(err)) panic(err) } db := implements.NewBunDatabase(bunDB) authHandlers := auth.NewHandlers(db) apiHandlers := api.NewHandlers(db) middlewareHandlers := middlewares.NewHandlers(db) router := bunrouter.New() if viper.GetBool("swagger") { router.GET("/swagger/*any", bunrouter.HTTPHandlerFunc( httpSwagger.Handler())) } backend := router.NewGroup(""). Use(middlewareHandlers.ErrorHandler). Use(middlewareHandlers.BunrouterOtel). Use(middlewareHandlers.AccessLog) authGroup := backend.NewGroup("/auth") authGroup.GET("/login", middlewareHandlers.Auth( authHandlers.GetLogin)) authGroup.POST("/logout", middlewareHandlers.Auth( authHandlers.PostLogout)) authGroup.POST("/register", authHandlers.PostRegister) apiGroup := backend.NewGroup("/api"). Use(middlewareHandlers.Auth) apiGroup.GET("/lobby/users", apiHandlers.GetLobbyUsers) tracing.Logger.Ctx(ctx). Info("http server up", zap.String("http.port", viper.GetString("port"))) log.Println(http.ListenAndServe(":"+viper.GetString("port"), otelhttp.NewHandler(router, ""))) }, } func init() { backendCmd.Flags(). String("port", "8080", "Port to listen on") backendCmd.Flags(). Bool("swagger", false, "Enable swagger") backendCmd.Flags(). String("sqlite-file", ":memory:", "File for sqlite") }