all
This commit is contained in:
105
backend/cmd/server/main.go
Normal file
105
backend/cmd/server/main.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"monica-go-completion-backend/internal/api"
|
||||
"monica-go-completion-backend/internal/completion"
|
||||
"monica-go-completion-backend/internal/lsp"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
Port string
|
||||
GoplsPath string
|
||||
WorkspaceDir string
|
||||
AllowOrigin string
|
||||
}
|
||||
|
||||
func main() {
|
||||
cfg := loadConfig()
|
||||
|
||||
lspClient, err := lsp.NewClient(context.Background(), cfg.GoplsPath, cfg.WorkspaceDir)
|
||||
if err != nil {
|
||||
log.Fatalf("create gopls client failed: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = lspClient.Close()
|
||||
}()
|
||||
|
||||
completionService := completion.NewService(lspClient)
|
||||
|
||||
router := gin.New()
|
||||
router.Use(gin.Logger())
|
||||
router.Use(gin.Recovery())
|
||||
router.Use(corsMiddleware(cfg.AllowOrigin))
|
||||
api.RegisterRoutes(router, completionService)
|
||||
|
||||
server := &http.Server{
|
||||
Addr: ":" + cfg.Port,
|
||||
Handler: router,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 60 * time.Second,
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Printf("completion backend listening on :%s", cfg.Port)
|
||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("http server failed: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := server.Shutdown(shutdownCtx); err != nil {
|
||||
log.Printf("http shutdown failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadConfig() config {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
cwd = "."
|
||||
}
|
||||
return config{
|
||||
Port: getenv("PORT", "8080"),
|
||||
GoplsPath: getenv("GOPLS_PATH", "gopls"),
|
||||
WorkspaceDir: getenv("WORKSPACE_DIR", cwd),
|
||||
AllowOrigin: getenv("CORS_ALLOW_ORIGIN", "*"),
|
||||
}
|
||||
}
|
||||
|
||||
func getenv(key, fallback string) string {
|
||||
v := os.Getenv(key)
|
||||
if v == "" {
|
||||
return fallback
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func corsMiddleware(allowOrigin string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Header("Access-Control-Allow-Origin", allowOrigin)
|
||||
c.Header("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
|
||||
c.Header("Access-Control-Allow-Headers", "Content-Type,Authorization")
|
||||
|
||||
if c.Request.Method == http.MethodOptions {
|
||||
c.AbortWithStatus(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user