2026-03-14 17:01:11 +07:00

197 lines
5.0 KiB
Go

package main
import (
"context"
"embed"
"evening_detective/internal/app"
"evening_detective/internal/config"
"evening_detective/internal/modules/cleaner"
"evening_detective/internal/modules/formatter"
"evening_detective/internal/modules/password"
"evening_detective/internal/services"
"evening_detective/internal/services/db"
"evening_detective/internal/services/link"
"evening_detective/internal/services/pdf"
"evening_detective/internal/services/story_service"
"evening_detective/internal/services/story_storage"
proto "evening_detective/proto"
"io/fs"
"log"
"net"
"net/http"
"time"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
)
//go:embed static/user/*
var userFS embed.FS
//go:embed static/admin/*
var adminFS embed.FS
func main() {
// Create a listener on TCP port
lis, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalln("Failed to listen:", err)
}
// Create a gRPC server object
s := grpc.NewServer()
// Attach the Greeter service to the server
dbFilepath := config.GetDBFilepath()
dbService, err := db.NewDBService(dbFilepath)
if err != nil {
log.Fatalln(err)
}
clientHost := config.GetHost()
fileHost := config.GetFileHost()
cleaner := cleaner.NewCleaner()
formatter := formatter.NewFormatter()
storyFilepath := config.GetStoryFilepath()
storyStorage := story_storage.NewFileStoryStorage(storyFilepath)
storyService, err := story_service.NewStoryService(
cleaner,
formatter,
storyStorage,
link.NewLinkService(fileHost),
)
if err != nil {
log.Fatalln(err)
}
linkService := link.NewLinkService(clientHost)
passwordGenerator := password.NewPasswordGenerator()
pdfGenerator := pdf.NewPDFGenerator()
proto.RegisterEveningDetectiveServer(
s,
app.NewServer(
services.NewServices(
dbService,
storyService,
linkService,
passwordGenerator,
pdfGenerator,
),
),
)
// Serve gRPC server
log.Println("Serving gRPC on 0.0.0.0:8080")
go func() {
log.Fatalln(s.Serve(lis))
}()
// Create a client connection to the gRPC server we just started
// This is where the gRPC-Gateway proxies the requests
conn, err := grpc.NewClient(
"0.0.0.0:8080",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatalln("Failed to dial server:", err)
}
gwmux := runtime.NewServeMux(
runtime.WithMetadata(func(ctx context.Context, request *http.Request) metadata.MD {
teamId := request.Header.Get("X-Id")
return metadata.Pairs("team-id", teamId)
}),
runtime.WithMetadata(func(ctx context.Context, request *http.Request) metadata.MD {
password := request.Header.Get("X-Password")
return metadata.Pairs("password", password)
}),
)
// Register Greeter
err = proto.RegisterEveningDetectiveHandler(context.Background(), gwmux, conn)
if err != nil {
log.Fatalln("Failed to register gateway:", err)
}
gwServer := &http.Server{
Addr: ":8090",
Handler: cors(gwmux),
}
// Serve gRPC-Gateway server
log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")
go func() {
log.Fatalln(gwServer.ListenAndServe())
}()
muxUser := http.NewServeMux()
subUserFS, err := fs.Sub(userFS, "static/user")
if err != nil {
log.Fatalln(err)
}
fileServerUser := http.FileServer(http.FS(subUserFS))
muxUser.Handle("/", fileServerUser)
// Serve user web server
log.Println("Serving user web on http://0.0.0.0" + config.ClientPort)
go func() {
log.Fatalln(http.ListenAndServe(config.ClientPort, muxUser))
}()
go func() {
dir := "./data/story/images"
// Создаем файловый сервер
fs := http.FileServer(http.Dir(dir))
// Добавляем middleware для логирования
http.Handle("/", loggingMiddleware(fs))
log.Println("Файловый сервер запущен на http://localhost:8120")
log.Println("Обслуживается директория: " + dir)
log.Fatal(http.ListenAndServe(":8120", nil))
}()
muxAdmin := http.NewServeMux()
subAdminFS, err := fs.Sub(adminFS, "static/admin")
if err != nil {
log.Fatalln(err)
}
fileServerAdmin := http.FileServer(http.FS(subAdminFS))
muxAdmin.Handle("/", fileServerAdmin)
// Serve admin web server
log.Println("Serving admin web on http://0.0.0.0:8110")
log.Fatalln(http.ListenAndServe(":8110", muxAdmin))
}
func cors(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization, ResponseType, X-Id, X-Password")
if r.Method == "OPTIONS" {
return
}
h.ServeHTTP(w, r)
})
}
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// Логируем запрос
log.Printf("[%s] %s %s", r.Method, r.URL.Path, time.Since(start))
next.ServeHTTP(w, r)
})
}