versia-go/server.go

147 lines
4.5 KiB
Go
Raw Normal View History

2024-08-29 00:46:32 +02:00
package main
import (
"context"
"fmt"
"git.devminer.xyz/devminer/unitel"
"git.devminer.xyz/devminer/unitel/unitelhttp"
"github.com/versia-pub/versia-go/internal/api_schema"
"github.com/versia-pub/versia-go/internal/handlers/follow_handler"
"github.com/versia-pub/versia-go/internal/handlers/meta_handler"
"github.com/versia-pub/versia-go/internal/handlers/note_handler"
"github.com/versia-pub/versia-go/internal/service"
"github.com/versia-pub/versia-go/internal/validators"
"net/http"
"sync"
"time"
"github.com/go-logr/zerologr"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/nats-io/nats.go"
"github.com/rs/zerolog/log"
"github.com/versia-pub/versia-go/ent"
"github.com/versia-pub/versia-go/internal/config"
2024-08-29 00:46:32 +02:00
"github.com/versia-pub/versia-go/internal/handlers/user_handler"
)
func shouldPropagate(r *http.Request) bool {
return config.C.ForwardTracesTo.Match([]byte(r.URL.String()))
}
func server(
ctx context.Context,
telemetry *unitel.Telemetry,
database *ent.Client,
natsConn *nats.Conn,
federationService service.FederationService,
requestSigner service.RequestSigner,
bodyValidator validators.BodyValidator,
requestValidator validators.RequestValidator,
userService service.UserService,
noteService service.NoteService,
followService service.FollowService,
instanceMetadataService service.InstanceMetadataService,
inboxService service.InboxService,
) error {
// Handlers
userHandler := user_handler.New(federationService, requestSigner, userService, inboxService, bodyValidator, requestValidator, zerologr.New(&log.Logger).WithName("user-handler"))
noteHandler := note_handler.New(noteService, bodyValidator, requestSigner, zerologr.New(&log.Logger).WithName("notes-handler"))
followHandler := follow_handler.New(followService, federationService, zerologr.New(&log.Logger).WithName("follow-handler"))
metaHandler := meta_handler.New(instanceMetadataService, zerologr.New(&log.Logger).WithName("meta-handler"))
// Initialization
web := fiber.New(fiber.Config{
ProxyHeader: "X-Forwarded-For",
ErrorHandler: fiberErrorHandler,
DisableStartupMessage: true,
AppName: "versia-go",
EnablePrintRoutes: true,
})
web.Use(cors.New(cors.Config{
AllowOriginsFunc: func(origin string) bool {
return true
},
AllowMethods: "GET,POST,PUT,DELETE,PATCH",
AllowHeaders: "Origin, Content-Type, Accept, Authorization, b3, traceparent, sentry-trace, baggage",
AllowCredentials: true,
ExposeHeaders: "",
MaxAge: 0,
}))
web.Use(unitelhttp.FiberMiddleware(telemetry, unitelhttp.FiberMiddlewareConfig{
Repanic: true,
2024-08-29 00:46:32 +02:00
WaitForDelivery: false,
Timeout: 5 * time.Second,
// host for incoming requests
TraceRequestHeaders: []string{"origin", "x-nonce", "x-signature", "x-signed-by", "sentry-trace", "sentry-baggage"},
// origin for outgoing requests
TraceResponseHeaders: []string{"host", "x-nonce", "x-signature", "x-signed-by", "sentry-trace", "sentry-baggage"},
IgnoredRoutes: []string{"/api/health"},
Logger: zerologr.New(&log.Logger).WithName("http-server"),
TracePropagator: shouldPropagate,
}))
web.Use(unitelhttp.RequestLogger(zerologr.New(&log.Logger).WithName("http-server"), true, true))
log.Debug().Msg("Registering handlers")
web.Get("/api/health", healthCheck(database, natsConn))
userHandler.Register(web.Group("/"))
noteHandler.Register(web.Group("/"))
followHandler.Register(web.Group("/"))
metaHandler.Register(web.Group("/"))
wg := sync.WaitGroup{}
wg.Add(2)
addr := fmt.Sprintf(":%d", config.C.Port)
log.Info().Str("addr", addr).Msg("Starting server")
go func() {
<-ctx.Done()
if err := web.Shutdown(); err != nil {
log.Error().Err(err).Msg("Failed to shutdown server")
}
}()
var err error
if config.C.TLSKey != nil {
err = web.ListenTLS(addr, *config.C.TLSCert, *config.C.TLSKey)
} else {
err = web.Listen(addr)
}
return err
}
func healthCheck(db *ent.Client, nc *nats.Conn) fiber.Handler {
return func(c *fiber.Ctx) error {
dbWorking := true
if err := db.Ping(); err != nil {
log.Error().Err(err).Msg("Database healthcheck failed")
dbWorking = false
}
natsWorking := true
if status := nc.Status(); status != nats.CONNECTED {
log.Error().Str("status", status.String()).Msg("NATS healthcheck failed")
natsWorking = false
}
if dbWorking && natsWorking {
return c.SendString("lookin' good")
}
return api_schema.ErrInternalServerError(map[string]any{
"database": dbWorking,
"nats": natsWorking,
})
}
}